public static void main(String[] argv) {
try {
createTable();
insertRecordIntoTable("leo","123");
} catch (SQLException e) {
System.out.println(e.getMessage());
}
}
private static void createTable() throws SQLException {
Connection dbConnection = null;
PreparedStatement preparedStatement = null;
String sequence = "CREATE SEQUENCE ID_SEQ INCREMENT BY 1 MAXVALUE 99999999999999999999 MINVALUE 1 CACHE 20";
String createTableSQL = "CREATE TABLE DBUSER1("
+ "USER_ID NUMBER(5) NOT NULL, "
+ "USERNAME VARCHAR(20) NOT NULL, "
+ "PASSWORD VARCHAR(20) NOT NULL, "
+ "PRIMARY KEY (USER_ID) "
+ ")";
try {
dbConnection = getDBConnection();
preparedStatement = dbConnection.prepareStatement(createTableSQL);
System.out.println(createTableSQL);
// execute create SQL stetement
preparedStatement.executeUpdate(createTableSQL);
preparedStatement.executeUpdate(sequence);
System.out.println("Table \"dbuser\" is created!");
} catch (SQLException e) {
System.out.println(e.getMessage());
} finally {
if (preparedStatement != null) {
preparedStatement.close();
}
if (dbConnection != null) {
dbConnection.close();
}
}
}
private static Connection getDBConnection() {
Connection dbConnection = null;
try {
Class.forName(DB_DRIVER);
} catch (ClassNotFoundException e) {
System.out.println(e.getMessage());
}
try {
dbConnection = DriverManager.getConnection(
DB_CONNECTION, DB_USER,DB_PASSWORD);
return dbConnection;
} catch (SQLException e) {
System.out.println(e.getMessage());
}
return dbConnection;
}
private static void insertRecordIntoTable(String username, String password) throws SQLException {
Connection dbConnection = null;
PreparedStatement preparedStatement = null;
String insertTableSQL = "INSERT INTO DBUSER1"
+ "(USER_ID, USERNAME, PASSWORD) VALUES"
+ "(ID_SEQ.NEXTVAL,?,?)";
try {
dbConnection = getDBConnection();
preparedStatement = dbConnection.prepareStatement(insertTableSQL);
// execute insert SQL stetement
preparedStatement.setString(1, username);
preparedStatement.setString(2, password);
preparedStatement.executeUpdate();
System.out.println("Record is inserted into DBUSER table!");
} catch (SQLException e) {
System.out.println(e.getMessage());
} finally {
if (preparedStatement != null) {
preparedStatement.close();
}
if (dbConnection != null) {
dbConnection.close();
}
}
}
I cannot find the error when I try to create a sequence for my table.
When I try to insert some data in my table with the sequence it says it doesn't exist, but I did create it. Also I am not sure if i need a preparedStatement.setInt(1, seq_id.nextval); it gives an error but im not quite sure how I would do this
The solution might be adding the schema name (owner) before the name of sequence:
CREATE SEQUENCE some_nameOf_schema.ID_SEQ INCREMENT BY 1 MAXVALUE 99999999999999999999 MINVALUE 1 CACHE 20
You're preparing a statement with one SQL text, and executing the statement with two different SQL texts;
preparedStatement = dbConnection.prepareStatement(createTableSQL);
preparedStatement.executeUpdate(createTableSQL);
preparedStatement.executeUpdate(sequence);
...which is actually invalid according to the docs;
int executeUpdate(String sql)
throws SQLException
Executes the given SQL statement, which may be an INSERT, UPDATE, or DELETE statement or an SQL statement that returns nothing, such as an SQL DDL statement.
Note:This method cannot be called on a PreparedStatement or CallableStatement.
What you need to do is to prepare and execute two different statements;
preparedStatement = dbConnection.prepareStatement(createTableSQL);
preparedStatement.executeUpdate();
preparedStatement = dbConnection.prepareStatement(sequence);
preparedStatement.executeUpdate();
In general, it doesn't make much sense to CREATE database objects every time your application starts up, because this is something that's usually done only once, when you install/upgrade the database/schema the application uses.
However, if you really have to do it this way, the current solution could be improved so that the following points are considered:
Only execute the CREATE statements when the objects do not yet exist in the DB. This can be done by first inspecting the USER_OBJECTS data dictionary view.
Use a plain Statement instead of PreparedStatement for executing the DDL (prepared statements are only useful for DML operations that use input variables)
Handle JDBC resources (Connection / Statement / ResultSet) concisely and safely through the try-with-resources construct
Here's how the code could look like:
// query constants
private static final String CHECK_DB_OBJECT =
"SELECT 1 FROM user_objects WHERE object_name = ?";
private static final String CREATE_SEQUENCE =
"CREATE SEQUENCE ID_SEQ INCREMENT BY 1 MAXVALUE 99999999999999999999" +
" MINVALUE 1 CACHE 20";
private static final String CREATE_TABLE = "CREATE TABLE DBUSER1("
+ "USER_ID NUMBER(5) NOT NULL, "
+ "USERNAME VARCHAR(20) NOT NULL, "
+ "PASSWORD VARCHAR(20) NOT NULL, "
+ "PRIMARY KEY (USER_ID) "
+ ")";
/* clip the main method etc. */
/**
* Creates the table and sequence only if they do not already exist.
*/
private static void createTableAndSequenceIfAbsent() {
try (Connection dbConnection = DriverManager.getConnection(
DB_CONNECTION, DB_USER, DB_PASSWORD);
PreparedStatement ps = dbConnection
.prepareStatement(CHECK_DB_OBJECT)) {
if (!dbObjectExists(ps, "ID_SEQ")) {
executeDDL(dbConnection, CREATE_SEQUENCE);
}
if (!dbObjectExists(ps, "DBUSER1")) {
executeDDL(dbConnection, CREATE_TABLE);
}
} catch (SQLException e) {
e.printStackTrace();
}
}
private static boolean dbObjectExists(PreparedStatement ps,
String objectName) throws SQLException {
ps.setString(1, objectName);
ResultSet rs = ps.executeQuery();
// if the #CHECK_DB_OBJECT query returned a row, the object exists
return rs.next();
}
private static void executeDDL(Connection c, String sql)
throws SQLException {
try (Statement st = c.createStatement()) {
st.execute(sql);
}
}
Related
I just started learning about MySQL and I am now trying to learn prepared statements. When I uses them, I get this error java.sql.SQLSyntaxErrorException. Can someone tell me where am I getting the syntax wrong? Thanks. Here is my code:
public class DBConnector {
private Statement statement;
private ResultSet result;
private PreparedStatement preparedStatement;
public void createDB() {
try {
sql = "CREATE DATABASE IF NOT EXISTS ?";
tableName = "test_name";
preparedStatement = connection.prepareStatement(sql);
preparedStatement.setString(1, tableName);
int myResult = preparedStatement.executeUpdate();
if(myResult == 1){
System.out.println("Database successfully created.");
}else{
System.out.println("Database with that name already exists. Please try again with different name.");
createDB();
}
}catch (SQLException e) {
System.out.println("Database creation failed.");
e.printStackTrace();
}
}
}
We can't bind Database names in Query parameters.
Statement stmt=con.createStatement();
int rs=stmt.executeUpdate("CREATE DATABASE dbname");
Try in this way, Database will create.
I am developing a simple app as a school project that is designed to be used by the client on his computer. I decide to use derby DB as it can work in embedded mode. However as everything works fine in eclipse, when I try to export it to executable jar file the app does not work properly.
I am trying to connect to DB and create tables if they don't exist as shown in the code. After the first launch of a jar new file named sampleDB appears on a screen so I guess that db is created. However, besides GUI components, the program does not work at all. I am executing those table methods in main as the first ones so I guess there may be something wrong with them, however, eclipse doesn't show any errors.
Here is a fragment of code responsible for connection and the creation of a table, that I mentioned.
public static Connection getConnection() throws Exception{
try {
Class.forName("org.apache.derby.jdbc.EmbeddedDriver");
//Getting the Connection object
String URL = "jdbc:derby:sampleDB;create=true";
conn = DriverManager.getConnection(URL);
return conn;
}catch(Exception e) {System.out.println(e);}
return null;
}
public static void table1() throws Exception {
Connection conn = getConnection();
try {
java.sql.Statement stmt = conn.createStatement();
if (!doesTableExists("costs", conn)) {
String query= "CREATE TABLE costs("
+"Id INT NOT NULL GENERATED ALWAYS AS IDENTITY, "
+"Name VARCHAR(60),"
+"value DOUBLE NOT NULL, "
+"driverdependent INT NOT NULL,"
+"costorpofit INT NOT NULL, "
+"fixedorvariable INT NOT NULL,"
+"driver VARCHAR(40),"
+"truck VARCHAR(40),"
+"semitrailer VARCHAR(40),"
+"Data TIMESTAMP,"
+"PRIMARY KEY (Id))";
stmt.execute(query);
}
}catch(Exception e) {System.out.println(e);}
}
static boolean doesTableExists(String tableName, Connection conn)
throws SQLException {
DatabaseMetaData meta = conn.getMetaData();
ResultSet result = meta.getTables(null, null, tableName.toUpperCase(), null);
return result.next();
}
public static void table2() throws Exception {
try {
Connection conn = getConnection();
java.sql.Statement stmt = conn.createStatement();
if (!doesTableExists("journeys", conn)) {
String query= "CREATE TABLE journeys("
+"Id INT NOT NULL GENERATED ALWAYS AS IDENTITY, "
+"millage DOUBLE NOT NULL, "
+"driver VARCHAR(40),"
+"truck VARCHAR(40),"
+"semitrailer VARCHAR(40),"
+"Data TIMESTAMP,"
+"PRIMARY KEY (Id))";
stmt.execute(query);
}
}catch(Exception e) {System.out.println(e);}
}
public static void table3() throws Exception {
try {
Connection conn = getConnection();
java.sql.Statement stmt = conn.createStatement();
if (!doesTableExists("routes", conn)) {
String query= "CREATE TABLE routes("
+"millage DOUBLE NOT NULL, "
+"Name VARCHAR(40))";
stmt.execute(query);
}
}catch(Exception e) {System.out.println(e);}
}
I'm creating a simple app which uses JDBC to get data from MySQL. I use a dao to get data from the database. All but one are working fine (code is the same for all DAOs). Also I'm committing INSERT and UPDATE methods manually.
Workbench returns valid result even if I set isolation level read committed manually.
JDBCSessionDao create method:
public void create(Session session) throws SQLException{
try(PreparedStatement ps = conn.prepareStatement(INSERT_SESSION)){
conn.setAutoCommit(false);
LocalTime start = session.getStartTime();
LocalTime end = session.getEndTime();
System.out.println(start + ", " + end);
System.out.println(Time.valueOf(start) + ", " + Time.valueOf(end));
ps.setTime(1, Time.valueOf(start));
ps.setTime(2, Time.valueOf(end));
ps.setDate(3, Date.valueOf(session.getDate()));
ps.setLong(4, session.getMovieId());
ps.executeUpdate();
conn.commit();
conn.setAutoCommit(true);
}
catch (SQLException e){
logger.error(e.getMessage());
conn.rollback();
}
}
JDBCSessionDao findByDate method
public List<Session> findByDate(LocalDate date) {
List<Session> sessions = new ArrayList<>();
SessionMapper mapper = new SessionMapper();
try(PreparedStatement ps = conn.prepareStatement(SELECT_BY_DATE_ORDER_BY_TIME_ASC)){
ps.setDate(1, Date.valueOf(date));
ResultSet rs = ps.executeQuery();
System.out.println(rs.getFetchSize());
while(rs.next()){
Session s = mapper.extractFromResultSet(rs);
sessions.add(s);
}
}
catch (SQLException e){
logger.error(e.getMessage());
}
return sessions;
}
Query:
String SELECT_BY_DATE_ORDER_BY_TIME_ASC = "SELECT * FROM sessions WHERE session_date=? ORDER by start_time ASC";
JDBCDaoFactory getConnection() method:
private Connection getConnection(){
String url = "jdbc:mysql://localhost:3306/cinemajee?useLegacyDatetimeCode=false&serverTimezone=Europe/Kiev";
String user = "root";
String password = "root";
try{
Class.forName("com.mysql.cj.jdbc.Driver");
return DriverManager.getConnection(url, user, password);
}
catch (SQLException | ClassNotFoundException e){
e.printStackTrace();
throw new RuntimeException();
}
}
Query result in workbench:
query result
Try modifying the query in your code. Perhaps the session_date parameter isn't working. So change from this:
"SELECT * FROM sessions WHERE session_date=? ORDER by start_time ASC"'
to this:
"SELECT * FROM sessions ORDER by start_time ASC LIMIT 5"'
I've forgot to change column names in SessionMapper, they were written in camel case (e.g. sessionId) but my db columns is in snake case (e.g. session_id).
I want to create an in-memory database and check that the table exists afterwards. Unfortunately, my code doesn't print anything to the console, so either the check for a table or the table creation process is wrong.
How do I fix it?
import java.sql.*;
public class Main {
private static String url = "jdbc:sqlite::memory";
private static void createNewTable(Connection conn) {
String sql = "CREATE TABLE IF NOT EXISTS students (\n"
+ " id integer PRIMARY KEY,\n"
+ " name text NOT NULL"
+ ");";
try (Statement stmt = conn.createStatement();) {
stmt.execute(sql);
} catch (SQLException e) {
System.out.println(e.getMessage());
}
}
private static void checkTable(Connection conn){
String sql = "SELECT name FROM sqlite_temp_master WHERE type='table'";
try (Statement stmt = conn.createStatement();) {
ResultSet rs = stmt.executeQuery(sql);
while (rs.next()) {
System.out.println("table: " + rs.getString(1));
}
} catch (SQLException e) {
System.out.println(e.getMessage());
}
}
public static void main(String[] args) {
Connection conn;
try{
conn = DriverManager.getConnection(url);
createNewTable(conn);
checkTable(conn);
} catch (SQLException e) {
System.out.println(e.getMessage());
}
}
}
I need help with the code below and getting it to return a true or false value. Any and all help would be appreciated.
public synchronized static boolean checkCompanyName(String companyName,
Statement statement) {
try {
ResultSet res = statement
.executeQuery("SELECT `companyName` FROM `companys` WHERE companyName = '"
+ companyName + "';");
boolean containsCompany = res.next();
res.close();
return containsCompany;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
Try to make your query like this:
ResultSet res = statement.executeQuery("SELECT companyName FROM companys WHERE companyName = " + companyName);
Or you can either you PreparedStatement which is better then you did before
You should be using a PreparedStatement (for that end pass the Connection in to the method). Also, you should retrieve the value from the ResultSet and validate it matches your companyName. Something like
static final String query = "SELECT `companyName` FROM "
+ "`companys` WHERE companyName = ?";
public synchronized static boolean checkCompanyName(String companyName,
Connection conn) {
PreparedStatement ps = null;
ResultSet rs = null;
try {
ps = conn.prepareStatement(query);
ps.setString(1, companyName);
rs = ps.executeQuery();
if (rs.next()) {
String v = rs.getString(1);
return v.equals(companyName);
}
} catch (Exception e) {
e.printStackTrace();
} finally {
if (rs != null) {
try {
rs.close();
} catch (SQLException e) {
}
}
if (ps != null) {
try {
ps.close();
} catch (SQLException e) {
}
}
}
return false;
}
Two comments:
You only need to check if there's at least one row matching your criteria, so you can use .first()
Your code is vulnerable to SQL Injection attacks. Please read this to learn more about it.
The easiest way to avoid SQL injection attacs is to use prepared statements. So let me strike two birds with a single stone and give you a solution using them:
/*
Check if the company exists.
Parameters:
conn - The connection to your database
company - The name of the company
Returns:
true if the company exists, false otherwise
*/
public static boolean checkCompanyName(Connection conn, String company) {
boolean ans = false;
try(PreparedStatement ps = conn.prepareStatement(
"select companyName from companies where companyName = ?"
) // The question mark is a place holder
) {
ps.setString(1, company); // You set the value for each place holder
// using setXXX() methods
try(ResultSet rs = ps.executeQuery()) {
ans = rs.first();
} catch(SQLException e) {
// Handle the exception here
}
} catch(SQLException e) {
// Handle the exception here
}
return ans;
}
Suggested reads:
Bobby Tables: A guide to preventing SQL injection
The Java Tutorials - JDBC: Using prepared statements