In preparation for an exam I am asked to debug and answer the questions below, but this goes over my head. Help much appreciated.
Assuming the syntax is correct, why will this code produce an
error when connecting to the database?
Suggest two ways how to improve security of database connection in this code.
import java.sql.*;
public class UpdateCar {
public static void updateCarNum (int carNo, int empNo)
throws SQLException {
Connection con=null;
PreparedStatement pstmt=null;
try {
con = DriverManager.getConnection(
"jdbc:default:connection");
pstmt= con.prepareStatement("UPDATE EMPLOYEES " +
"SET CAR_NUMBER = ? " +
"WHERE EMPLOYEE_NUMBER = " + empNo);
pstmt.setInt(2, empNo);
pstmt.executeUpdate();
}
finally {
if (pstmt != null) pstmt.close();
}
}
}
Change
pstmt= con.prepareStatement("UPDATE EMPLOYEES " +
"SET CAR_NUMBER = ? " +
"WHERE EMPLOYEE_NUMBER = " + empNo);
pstmt.setInt(2, empNo);
to
pstmt= con.prepareStatement("UPDATE EMPLOYEES " +
"SET CAR_NUMBER = ? " +
"WHERE EMPLOYEE_NUMBER = ?");
pstmt.setInt(1, carNo);
pstmt.setInt(2, empNo);
And you should also read a bit about what JDBC is, and how to use it.
Check your DiverManager. in java there is jdbc driver that may not work with your database . try another driver for your connection
Related
Could you please tell me what to add on my code so that when i type a letter in the textfield, before i finish typing the search result already start showing on jtable without waiting for me to type the whole word?
Below please find my code for key released event on the textbox. Thank you for your help.
private void jTextFieldSearchKeyReleased(java.awt.event.KeyEvent evt) {
try{
String selected=(String)jComboBoxSelected.getSelectedItem();
Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/"
+ "employee_certificate","root","");
String sql="SELECT stuff.Emp_Id,stuff.Emp_Name, stuff.Department, "
+ "certificate.Cert_Code, certificate.Cert_Name,\n" +
"certificate.Cert, certificate.Vendor, certificate.Date_Taken, "
+ "certificate.Expiry_Date FROM stuff LEFT JOIN certificate"
+ " ON stuff.Emp_Id=certificate.Emp_Id "
+ "WHERE "+selected+" =? ORDER BY stuff.Emp_Name\n" ;
PreparedStatement pstmt=con.prepareStatement(sql);
pstmt.setString(1, jTextFieldSearch.getText());
ResultSet rs=pstmt.executeQuery();
jTable1.setModel(DbUtils.resultSetToTableModel(rs));
pstmt.close();
//con.close();
}
catch(Exception ex){ex.printStackTrace();}
}
After a two day struggle finally i got an answer...i just needed to use LIKE '%' as shown.No one should suffer as i did
private void jTextFieldSearchKeyReleased(java.awt.event.KeyEvent evt) {
try{
String selected=(String)jComboBoxSelected.getSelectedItem();
Connection con = DriverManager.getConnection("jdbc:mysql://localhost:3306/"+ "employee_certificate","root","");
String sql="SELECT stuff.Emp_Id,stuff.Emp_Name, stuff.Department, "
+ "certificate.Cert_Code, certificate.Cert_Name,\n" +
"certificate.Cert, certificate.Vendor, certificate.Date_Taken, "
+ "certificate.Expiry_Date FROM stuff LEFT JOIN certificate"
+ " ON stuff.Emp_Id=certificate.Emp_Id "
+"WHERE "+selected+" LIKE ? ORDER BY stuff.Emp_Name\n" ;
PreparedStatement pstmt=con.prepareStatement(sql);
pstmt.setString(1,jTextFieldSearch.getText() + "%");
ResultSet rs=pstmt.executeQuery();
jTable1.setModel(DbUtils.resultSetToTableModel(rs));
pstmt.close();
con.close();
}
catch(Exception ex){ex.printStackTrace();}
}
I've got the following code in my app
String sql = "SELECT colA, colB, colC " +
"FROM " + tblName + " WHERE UserId = " + userId +
" AND InsertTimestamp BETWEEN " + lastDate +
" AND " + DataProcessor.TODAY + " ORDER BY UserId, Occurred";
try{
if(null == conn)
openDatabaseConnection();
PreparedStatement stmt = conn.prepareStatement(sql);
ResultSet rs = stmt.executeQuery(); <------- this is the line which throws the SQL exception
retArray = this.getArrayListFromResultSet(rs);
}catch(SQLException sqle){
JSONObject parms = new JSONObject();
eh.processSQLException(methodName, sqle, sql, parms);
}
So when I run my app in the debugger, I get this exception message
com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '00:00:00.0 AND 2014-08-20 00:00:00.0 ORDER BY UserId, Occurred' at line 1
I'm reasonably certain that there's simple and reasonable solution to this, but I have not been able to find it.
I've tried looking in the MySQL manual for a solution or a different format.
I've tried running my timestamps through a TIMESTAMP() functino and a DATE() function in the SQL, neither of which helped.
I pulled the fully formed SQL out of the Java code and ran it in MySQL Workbench with no issues, what-so-ever. So now I'm looking to the experts for help.
Dates in SQL must be enclosed within single quotes like strings.
As you're using a prepared statemtent, why you don't use '?' and stmt.setDate(...)?
String sql = "SELECT colA, colB, colC " +
"FROM " + tblName + " WHERE UserId = ?" +
" AND InsertTimestamp BETWEEN ?" +
" AND ? ORDER BY UserId, Occurred";
try {
if(null == conn) {
openDatabaseConnection();
}
PreparedStatement stmt = conn.prepareStatement(sql);
stmt.setInt(1, userId);
stmt.setDate(2, lastDate);
stmt.setDate(3, DataProcessor.TODAY);
ResultSet rs = stmt.executeQuery();
retArray = this.getArrayListFromResultSet(rs);
} catch(SQLException sqle) {
JSONObject parms = new JSONObject();
eh.processSQLException(methodName, sqle, sql, parms);
}
Anyway, I think you are setting the dates in the opposite order. You should put first 'today' then lastDate. Although I don't know your constraints...
i'm having an exam in a couple of days and there's a sample exam with a code:
import java.sql.*;
public class UpdateCar {
public static void UpdateCarNum(int carNo, int empNo) throws SQLException {
Connection con = null;
PreparedStatement pstmt = null;
try { con = DriverManager.getConnection( "jdbc:default:connection");
pstmt = con.prepareStatement( "UPDATE EMPLOYEES " + "SET CAR_NUMBER = ? " + "WHERE EMPLOYEE_NUMBER = " + empNo);
pstmt.setInt(2, empNo);
pstmt.executeUpdate();
}
finally {
if (pstmt != null) pstmt.close();
}
}
}
So the question is what returns an error in this code with connection to the database and bring out two ways how to improve the connection safety.
It returns an error because pstmt.setInt(2,empNo) is not defined, it should be pstmt.setInt(1,carNo).
And one way to improve safety would be to set all values in query with setInt not with variable empNo. For example
pstmt = con.prepareStatement("UPDATE EMPLOYEES "+"SET CAR NUMBER = ? "+"WHERE EMPLOYEE_NUMBER = ?");
pstmt.setInt(1,carNo);
pstmt.setInt(2,empNo);
What could i do more to improve safety (second way, thought, idea - thing requested)?
If an employee doesn't have a car then you can only set the car number to 0 or -1 but not to NULL. If you use
public static void UpdateCarNum(Integer carNo, int empNo) throws SQLException {
then you can also support this case.
If you would use String for the carNo to support this. And if you do no checks. Then someone can inject SQL and do ugly stuff if you concatenate it like in your example. Use the advantage of the prepared statement also there by putting just a ? in. Although then you can't use Integer and could use BigDecimal for carNo (because there is no pstmt.setInteger() only a pstmt.setBigDecimal()). Or alternatively use Integer and if it is null you can use pstmt.setNull() otherwise pstmt.setInt(..., carNo.intValue()).
You could also use a stringbuilder to spot this kind of error more quickly:
StringBuilder myStatement = new StringBuilder();
myStatement.append( "UPDATE EMPLOYEES" );
myStatement.append( " SET CAR_NUMBER = " + carNo );
myStatement.append( " WHERE EMPT_NO = " + emptNo );
pstmt = con.prepareStatement( myStatement.toString() );
and close you connection "con" in the finally-block
Connection is not closed. You should use try-with-resouce statement for saving resources.
try (Connection con = DriverManager.getConnection("jdbc:default:connection")) {
try (PreparedStatemt pstmt = con.prepareStatement("UPDATE EMPLOYEES SET CAR_NUMBER = ? WHERE EMPLOYEE_NUMBER = ?")) {
pstmt.setInt(1, carNo);
pstmt.setInt(2, empNo);
pstmt.executeUpdate();
}
}
I have a Postgresql database and I want to truncate some tables using JDBC. How do I do that?
This is what I tried, but none worked... without even any error being reported:
Using CallableStatement.
try (Connection connection = getConnection();
CallableStatement statement = connection.prepareCall("TRUNCATE " + tableName)) {
return statement.execute();
}
Using Statement.
try (Connection connection = getConnection();
Statement statement = connection.createStatement()) {
return statement.execute("TRUNCATE " + tableName);
}
Using PreparedStatement.
try (Connection connection = getConnection();
PreparedStatement statement = connection.prepareStatement("TRUNCATE " + tableName)) {
return statement.execute();
}
After the truncate, I need to commit:
try (Connection connection = getConnection();
Statement statement = connection.createStatement()) {
int result = statement.executeUpdate("TRUNCATE " + tableName);
connection.commit();
return result;
}
From the documentation:
TRUNCATE is transaction-safe with respect to the data in the tables: the truncation will be safely rolled back if the surrounding transaction does not commit.
You may run into issues if the table has dependencies. If so, truncate the parent tables first, and also use the CASCADE option.
Connection connection = getConnection();
try {
PreparedStatement statement = connection.prepareStatement("TRUNCATE " + parentTable1, parentTable2, ... + " CASCADE");
try {
return statement.execute();
} finally {
statement.close();
}
} finally {
connection.close();
}
First, if you are truncating a table, you probably want to also RESTART IDENTITY (in addition to possibly doing CASCADE, as John Hogan mentioned).
Second, as far as doing a connection.commit(), the assumption is that you have autocommit set to OFF. My Postgres was set up with it set to ON (apparently, that is sometimes the default).
If it is set to ON, then calling the commit is unnecessary, and will result in the error:
"org.postgresql.util.PSQLException: Cannot commit when autoCommit is enabled."
Third, you may not have permission to truncate a table (or restart identity). In that case, you will need to:
DELETE from your_table
SELECT setval('your_table_id', 1)
The following worked for me:
public String truncateTable(String tableName, boolean cascadeFlag) {
String message = "";
try {
connection = DriverManager.getConnection(url, username, password);
Statement statement = connection.createStatement();
String truncation = "TRUNCATE TABLE yourSchema." + tableName + " RESTART IDENTITY" + (cascadeFlag ? " CASCADE" : "");
System.out.println("truncateTable: Executing query '" + truncation + "'.");
int result = statement.executeUpdate(truncation);
// connection.commit(); // If autocommit is enabled (which it is for our DB), then throws exception after truncating the table.
statement.close();
connection.close();
} catch (SQLException sqlex) {
message = "Could not truncate table " + tableName + ". " + sqlex.getMessage();
System.err.println(message);
sqlex.printStackTrace();
}
return message;
}
Also:
public int deleteResetTable(String tableName, String fieldName) {
int affectedRows = 0;
try {
connection = DriverManager.getConnection(url, username, password);
String sql = "DELETE FROM yourSchema." + tableName;
PreparedStatement preparedStatement = connection.prepareStatement(sql);
affectedRows = preparedStatement.executeUpdate();
System.out.println("Deleted " + affectedRows+ " rows from table " + tableName + ".");
sql = "SELECT setval('yourSchema." + fieldName + "', 1)";
preparedStatement = connection.prepareStatement(sql);
affectedRows = preparedStatement.executeUpdate();
System.out.println("Reset " + affectedRows+ " values from table " + tableName + ".");
} catch (SQLException ex) {
System.out.println("Failed to delete rows from " + tableName + " " + ex.getMessage());
}
return affectedRows;
}
what's wrong with my insert method?
my table has two columns, name, and artist..and timestamp, that too
actually, how do i pass timestamp argument to the insert statement?
ok.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
try {
/*FileWriter dir = new FileWriter(nameOfSong.getText()
+ ".txt");
BufferedWriter buffer = new BufferedWriter(dir);
buffer.write(nameOfSong.getText());
buffer.newLine();
buffer.write(artist.getText());
buffer.newLine();
buffer.newLine();
buffer.write(lyrics.getText());
buffer.close();
*/
Statement statement = connection.createStatement();
statement.executeUpdate("INSERT INTO lyrics1_lyrics1 VALUES(" +
nameOfSong.getText() + ", " + artist.getText() + "");
} catch (Exception z) {
System.err.println("Error: " + z.getMessage());
}
internalFrame.dispose();
}
});
)
Always use PreparedStatement.
String sql="INSERT INTO lyrics1_lyrics1 VALUES (?,?)";
PreparedStatement statement = connection.prepareStatement(sql);
statement.setString(1,nameOfSong.getText());
statement.setString(2,artist.getText());
statement.executeUpdate();
statement.close();
connection.close();
The text values need to be surrounded by single quotes ('').
And SQL-escaped to avoid SQL injection attacks, or the first time you have a song by Little Bobby Tables, all your DB are belong to him.
Better yet, use a PreparedStatement, and let the machine do work for you.
You can use prepared statement for it
String query = "INSERT INTO lyrics1_lyrics1(name, artist, timestamp) values(?, ?, ?)";
PreparedStatement pstmt = conn.prepareStatement(query);
pstmt.setString(1, name); // set input parameter 2
pstmt.setString(2, artist);
pstmt.setString(3, new TimeStamp(new Date().getTime()));
You need to add an import statement for the TimeStap;
import java.sql.Timestamp;
or else use
pstmt.setString(3, new java.sql.TimeStamp(new Date().getTime()));
Example: Prepared Statement Insert.
You can find a lot of example in java2s site.
Change the line to:
statement.executeUpdate("INSERT INTO lyrics1_lyrics1 VALUES('" +
nameOfSong.getText() + "', '" + artist.getText() + "'");
This might solve your problem:
statement.executeUpdate("INSERT INTO lyrics1_lyrics1 VALUES('" + nameOfSong.getText() + "', '" + artist.getText() + "')");`