is this actually a resource leak? - java

I have an "Invitation" object that is modeled in a MySQL database. This object has one list ("treatmentPlanIDsToCopyf") and is maintained in the database with a second table. The method I have written to insert into the main table and then loop through the list and insert records for each item in the list into the second table is below. At the line ps = cn.prepareStatement(sql);Eclipse is giving me a warning that says "Resource leak: 'ps' is not closed at this location". I am closing the prepared statement in the finally clause, so I wanted to know if there really is a resource leak I need to fix. This is my first time using batches with prepared statements, so I wasn't really sure. Thanks.
public void invitationCreate(Connection cn, Invitation invitation) throws SQLException{
PreparedStatement ps = null;
try {
//first insert primary invitation data into the invitation table
String sql = "INSERT INTO invitiation (invitation_code, recipient_email, sender_user_id_fk, date_intived, date_accepted, accepted, recipient_first_name, recipient_last_name) VALUES (?, ?, ?, ?, ?, ?, ?, ?)";
ps = cn.prepareStatement(sql);
ps.setString(1, invitation.getInvitationCode());
ps.setString(2, invitation.getRecipientEmail());
ps.setInt(3, invitation.getSenderUserID());
ps.setTimestamp(4, convertLocalTimeDateToTimstamp(invitation.getDateInvited()));
ps.setTimestamp(5, convertLocalTimeDateToTimstamp(invitation.getDateAccepted()));
ps.setBoolean(6, invitation.isAccepted());
ps.setString(7, invitation.getRecipientFirstName());
ps.setString(8, invitation.getRecipientLastName());
int success = ps.executeUpdate();
//now loop through all the treatmentPlanIDs in the invitation that are to be copied into the invitees account when the register
sql = "INSERT INTO invitation_treatment_plans (invitation_code_fk, invitation_treatment_plan_id_fk) VALUES (?, ?)";
ps = cn.prepareStatement(sql);//TODO confirm this if this is actually a resource leak
for(int treatmentPlanID : invitation.getTreatmentPlanIDsToCopy()){
ps.setString(1, invitation.getInvitationCode());
ps.setInt(2, treatmentPlanID);
ps.addBatch();
}
ps.executeBatch();
} finally {
DbUtils.closeQuietly(ps);
}
}

I believe the leak is in the first prepared statement.
After int success = ps.executeUpdate(); you need to close that prepared statement before you assign the variable to a new prepared statement.

Related

how to check if a sql statement is ready to be executed?

How do I check if the statement can execute in my code? the second parameter won't be set if txtFirstName.getText() is empty.
String sql = "INSERT INTO Employees (id, firstName, lastName, adress, phone, email, photo, comments) VALUES (?, ?, ?, ?, ?, ?, ?, ?)";
PreparedStatement statement = database.connection.prepareStatement(sql);
statement.setString(1, database.users.size() + 1 + "");
if (txtFirstName.getText().matches(""))
statement.setString(2, txtFirstName.getText());
statement.setString(3, txtLastName.getText());
statement.setString(4, txtAdress.getText());
statement.setString(5, txtPhone.getText());
statement.setString(6, txtEmail.getText());
statement.setString(7, txtPhotoURL.getText());
statement.setString(8, txtComment.getText());
statement.executeUpdate();
the second parameter won't be set if txtFirstName.getText() is empty.
Yes, it will; it will be set to an empty string. Whether that's valid for this specific query and table structure is beyond the realm of JDBC.
You need to check your constraints in advance, separately, and then either make the call or not.
You need an else condition to specify what to do if txtFirstName does not match the pattern, e.g.:
if (txtFirstName.getText().matches("")){
statement.setString(2, txtFirstName.getText());
}else {
throw new IllegalArgumentException("Invalid name pattern");
}
This will prevent the code from executing errorneous preparedstatement and throw an exception with appropriate error message.

Insert database mysql get issue

i got issue when i go to Insert value to DB (do nothing).
before that i do select table to get last id, and it worked.
Here's my Code:
IDBManager dbManager = getParentExtension().getParentZone().getDBManager();
Connection connection = null;
int idRoom = params.getInt("idRoom");
String betsmall = params.getUtfString("betsmall");
int Uid = params.getInt("recid");
try{
connection = dbManager.getConnection();
PreparedStatement stmt = connection.prepareStatement("SELECT id_game from detail_game ORDER BY id_game DESC LIMIT 1");
ResultSet res = stmt.executeQuery();
if (!res.first())
{
trace("bla bla");
}
int id = res.getInt("id_game");
trace (id);
// **till here there is no problem, i can get id from select query
PreparedStatement stmts = connection.prepareStatement("INSERT INTO detil_bet (id_user, id_room, id_bet, bettype) VALUES (?, ?, ?, ? ");
stmts.setInt(1, Uid);
stmts.setInt(2, idRoom);
stmts.setInt(3, id);
stmts.setString(4, betsmall);
stmts.executeUpdate();
}
}
Here's the problem, insert do nothing.
PreparedStatement stmts = connection.prepareStatement("INSERT INTO detil_bet (id_user, id_room, id_bet, bettype) VALUES (?, ?, ?, ? ");
Looks like you need some end parentheses in "VALUES".
A catch block to print stack trace would have told you the issue here as well. I'm not the best SQL guy, I always use this to check my SQL syntax as well to double check if I've done everything right.
your connection seems not auto commit. Try to add
stmts.commit();
after "stmts.executeUpdate();".

Cannot put entry in the mysql database

private void B_save_pActionPerformed(java.awt.event.ActionEvent evt) {
try{
String db = "jdbc:mysql://localhost/ar";
Connection con = DriverManager.getConnection(db, "rehan", "1234");
PreparedStatement ps;
String sql = "INSERT INTO purchase (item_type, md_by, model, selling_price, purchase_price, purchase_date, item_image, vouch_no, vouch_date) VALUES ('?', '?', '?', ?, ?, '?', ?, ?, '?');" ;
ps = con.prepareStatement(sql);
ps.setString(1 , txt_itype_p.getText());
ps.setString(2, txt_md_by_p.getText());
ps.setString(3, txt_model_p.getText());
ps.setString(4, txt_s_price_p.getText());
ps.setString(5 , txt_p_price.getText());
ps.setString(6, null);
ps.setString(7, null);
ps.setString(8, txt_vouch_p.getText());
ps.setString(9 , null);
ps.execute();
}
catch(SQLException ex){
JOptionPane.showMessageDialog(null, ex);
}
DefaultTableModel tblModel = (DefaultTableModel) Table_p.getModel();
if(!txt_itype_p.getText().trim().equals("")) {
tblModel.addRow(new Object[]{tbl_sr, txt_itype_p.getText(),txt_model_p.getText(),txt_md_by_p.getText(),txt_date_p.getText(),txt_p_qty.getText(),txt_p_price.getText(),txt_s_price_p.getText()});
txt_itype_p.setText(null);
txt_ipath.setText(null);
txt_itype_p.setText(null);
txt_md_by_p.setText(null);
txt_model_p.setText(null);
txt_p_date.setText(sdf.format(date));
txt_p_price.setText(null);
txt_p_qty.setText(null);
txt_s_price_p.setText(null);
}
tbl_sr = tbl_sr +1;
saved = true;/*If someone accidently click the close button, system will
confirm while getting the value of this bolean variable*/
}
This is my code for the save button which is supposed to show the entries on a JTable in a JFrame and also saves the entries into mysql database in 'purchase' table, but the problem is it shows the entries on the JTable but doesnot saves in database. I have same code to create new users which saves username, password and account type in the login table in database and that code is working fine. I have a feeling that this problem is due to some data types issue but i am not confirmed.
I am using Netbeans and mysql database. I tried to send 'null' to date and image data types but still its not working.
Someone please help me.
This line has a problem:
String sql = "INSERT INTO purchase (item_type, md_by, model, selling_price, purchase_price, purchase_date, item_image, vouch_no, vouch_date) VALUES ('?', '?', '?', ?, ?, '?', ?, ?, '?');" ;
The problem is the five ?s that are surrounded by single quotes. JDBC does not recognise these as placeholders and assumes you want to insert a string containing just a ? character into the item_type, md_by, model, purchase_date and vouch_date columns.
The fix is to remove all of the single quotes around the ? marks:
String sql = "INSERT INTO purchase (item_type, md_by, model, selling_price, purchase_price, purchase_date, item_image, vouch_no, vouch_date) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?);" ;

Java JDBC - Multiple prepared statement bulk insert

Using JDBC (Oracle) I need to insert about thousand rows into each of two tables. Something like this:
"INSERT INTO TABLE_A (A_ID, A_NAME, A_LAST_NAME) VALUES (MY_SEQUENCE.NEXTVAL, ?, ?)";
"INSERT INTO TABLE_B (B_ID, B_DESCRIPTION) VALUES (MY_SEQUENCE.CURRVAL, ?)";
The problem is that both tables are connected through common sequence, so that order of statements is important.
It would be quite easy if I had only one table. In that case I used code:
String insert = "Insert into TABLE_A(A_ID, A_NAME, A_LAST_NAME) values(MY_SEQUENCE.NEXTVAL, ?, ?)";
conn.setAutoCommit(false);
PreparedStatement ps = conn.prepareStatement(insert);
for(MyObject obj : myCollection) {
ps.setString(1, obj.getName());
ps.setString(2, obj.getLastName());
ps.addBatch();
}
ps.executeBatch();
conn.commit();
ps.close();
But this approach can work only with one prepared statment and thus with only one Insert. How can I provide a solution for this problem?
You can try
PreparedStatement ps = conn.prepareStatement(insert, Statement.RETURN_GENERATED_KEYS);
...
ps.executeBatch();
then
ResultSet rs = ps.getGeneratedKeys();
ps = conn.prepareStatement("INSERT INTO TABLE_B (B_ID, B_DESCRIPTION) VALUES (?, ?)");
for ( int counter =0;rs.next(); counter++ ) {
ps.setInt(1,rs.getInt(0));
ps.setString(2, myCollection.get(counter).getDescription());
ps.addBatch();
}
...
If I understand your problem correctly, you have a problem with NEXTVAL and CURRVAL since CURRVAL might change due to other DB use?
If so, you can change your code to this order:
currentNextVal = select NEXTVAL
INSERT into table_a with currentNextVal as the id
INSERT into table_b with the same currentNextVal
Did I understand your problem correctly?

Java General Error On Insert...???

I am trying to do an Insert, Update and Delete on a table in MS Access. Everything works fine
for a SELECT statement. But when doing the other three operations, I don't seem to get any
errors, but the actions are not reflected on to the DB. Please help...
THe INSERT statement is as follows:
PreparedStatement ps = con.prepareStatement("INSERT INTO Student VALUES (?, ?, ?, ?, ?, ?, ?, ?)");
ps.setInt(1,1);
ps.setString(2,"ish");
ps.setInt(3,100);
ps.setInt(4,100);
ps.setInt(5,100);
ps.setInt(6,300);
ps.setInt(7,100);
ps.setString(8,"A");
ps.executeUpdate();
Also may I know why PreparedStatement is used except for SELECT statement...
I get this error:
Exception in thread "main" java.sql.SQLException: General error
at sun.jdbc.odbc.JdbcOdbc.createSQLException(JdbcOdbc.java:6986)
at sun.jdbc.odbc.JdbcOdbc.standardError(JdbcOdbc.java:7114)
at sun.jdbc.odbc.JdbcOdbc.SQLExecute(JdbcOdbc.java:3149)
at sun.jdbc.odbc.JdbcOdbcPreparedStatement.execute(JdbcOdbcPreparedState
ment.java:216)
at sun.jdbc.odbc.JdbcOdbcPreparedStatement.executeUpdate(JdbcOdbcPrepare
dStatement.java:138)
at Student.main(Student.java:19)
This is my code...
import java.sql.*;
import java.io.*;
class Student {
public static void main(String args[]) throws SQLException, IOException, ClassNotFoundException {
Class.forName("sun.jdbc.odbc.JdbcOdbcDriver");
Connection con = DriverManager.getConnection("jdbc:odbc:Student","","");
Statement st = con.createStatement();
PreparedStatement ps = con.prepareStatement("INSERT INTO Student VALUES (?, ?, ?, ?,
?, ?, ?, ?)");
ps.setInt(1,1);
ps.setString(2,"Girish");
ps.setInt(3,100);
ps.setInt(4,100);
ps.setInt(5,100);
ps.setInt(6,300);
ps.setInt(7,100);
ps.setString(8,"A");
ps.executeUpdate();
con.commit();
con.close();
}
}
This can happen when you don't commit/close the connection. Ensure that you're committing the connection after executing the statement and are closing the connection (and statement and resultset) in the finally block of the try block where they are been acquired and executed.
As to why the PreparedStatement is used, it's the common approach to avoid SQL injection attacks and to ease setting fullworthy Java objects like Date, InputStream, etc in a SQL query without the need to convert them to String.
I believe your prepared statement is of the wrong format. The documentation for INSERT INTO (available here: http://msdn.microsoft.com/en-us/library/bb208861(v=office.12).aspx) gives this format:
Single-record append query:
INSERT INTO target [(field1[, field2[, …]])] VALUES (value1[, value2[, …])
You give the format:
INSERT INTO target VALUES (value1[, value2[, …])
edit:
To be more clear I believe you want something like:
PreparedStatement ps = con.prepareStatement("INSERT INTO Student (Year, Name, field3 ...) VALUES (?, ?, ?, ?, ?, ?, ?, ?)");
Where Year, Name, field3 ... are the names of the fields you are trying to insert into.
The main reason for using a PreparedStatement is security. Generating a SQL query by concating strings is unsafe as the variable parts may contain SQL statements entered by a user. This would allow to execute statements like DROP TABLE * to the user (see SQL Injection). Theres is is a good idea only to use PreparedStatemnts if the SQL query is not static (doe snot contain variable parts).
Therefore it would be better also to use PreparedStatement for SELECT statements.
Edit :
You try to Insert your Student Primary Key, if it's an Identity column, it will not work.
You need to prepare your statement like this :
PreparedStatement ps = con.prepareStatement("INSERT INTO Student(Field1,Field2,Field3,Field4,Field5,Field6,Field7) VALUES (?, ?, ?, ?, ?, ?, ?)");
Without your Primary Key set, the DB will do it for you.
.
.
.
Original post :
There is a kind of similar question on StackOverflow.
You won't see any result from INSERT queries with Access until you close your Connection properly.
Your code doesn't close any resources, which will surely bring you grief. Call the close methods (in reverse order if there are more than one) in a finally block.
Here is a class DataBaseUtils to help you if needed.
public class DatabaseUtils
{
public static Connection createConnection(String driver, String url, String username, String password)
throws ClassNotFoundException, SQLException
{
Class.forName(driver);
return DriverManager.getConnection(url, username, password);
}
public static void close(Connection connection)
{
try
{
if (connection != null)
{
connection.close();
}
}
catch (SQLException e)
{
e.printStackTrace(e);
}
}
public static void close(Statement statement)
{
try
{
if (statement != null)
{
statement.close();
}
}
catch (SQLException e)
{
e.printStackTrace(e);
}
}
public static void close(ResultSet rs)
{
try
{
if (rs != null)
{
rs.close();
}
}
catch (SQLException e)
{
e.printStackTrace(e);
}
}
}

Categories