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

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.

Related

is this actually a resource leak?

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.

SELECT after INSERT statement?

So my issue is after I insert a new record in the database, I want to do a SELECT query that should include that new record. However, the data being returned excludes the newly added record. It seems like whenever I first open the connection, whatever is already in the database is what my program goes off. I hope this makes sense. All input is appreciated.
Update:
So here is the INSERT snippet
String DML = "INSERT INTO MEMBERS (FIRST_NAME, LAST_NAME, BIRTHDATE, DEATH_DATE, MARITAL_STATUS,"
+ " WEDDING_DATE, SPOUSE_NAME, MILITARY_SERVICE, DATE_JOINED, DEPARTURE_DATE, ACCEPTANCE_MODE, DEPARTURE_MODE,"
+ " RELATED_TO, NOTES) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
PreparedStatement pstmt = conn.prepareStatement(DML);
pstmt.setString(1, jTextField2.getText());
pstmt.setString(2, jTextField1.getText());
pstmt.setString(3, jTextField6.getText());
pstmt.setString(4, jTextField11.getText());
pstmt.setString(5, jTextField3.getText());
pstmt.setString(6, jTextField5.getText());
pstmt.setString(7, jTextField4.getText());
pstmt.setString(8, jTextField8.getText());
pstmt.setString(9, jTextField7.getText());
pstmt.setString(10, jTextField10.getText());
pstmt.setString(11, jTextField9.getText());
pstmt.setString(12, jTextField13.getText());
pstmt.setString(13, jTextField14.getText());
pstmt.setString(14, jTextArea1.getText());
pstmt.executeUpdate();
if (conn.getAutoCommit() == false)
conn.commit();
Now this is the SELECT snippet which if fired after the INSERT
pstmt=conn.prepareStatement("SELECT CONCAT(LAST_NAME, ', ', FIRST_NAME) AS NAME FROM MEMBERS ORDER BY LAST_NAME, FIRST_NAME");
rs=pstmt.executeQuery();
It is very likely that you have autocommit mode disabled and/or you are running the 2 queries (INSERT then SELECT) as a transaction.
Try turning autocommit mode on and then running the 2 queries again (INSERT then SELECT), it should work.
If you mean this
stmt.executeUpdate("insert into t1 ...");
ResultSet rs = stmt.executeQuery("select ... from t1");
then data inserted in statement 1 is always visible in statement 2, both in autocommit on and off modes.
It is only possibly that select does not see inserted records if you insert in one transaction, do not commit, and read in another transaction
Something like this can be done:
You can use an autoincrement column say call it serialID.
Insert data normally. When retrieving use MAX(serialID)
SELECT CONCAT(LAST_NAME, ', ', FIRST_NAME) AS NAME FROM MEMBERS ORDER BY
LAST_NAME, FIRST_NAME where serialID = (select max(serialID) from MEMBERS);
You'll have to do this in one transaction.

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 (?, ?, ?, ?, ?, ?, ?, ?, ?);" ;

What am I doing wrong in inserting data to mysql table?

After executing code I get the Data saved message but no data is recorded in my clients table? I'm new to databases with Java, What am I doing wrong or how can I fix my code?
String sqlUrl = "jdbc:mysql://localhost:3306/clientinformation";
String user = "root";
String pass = "root";
String name = firstName.getText();
String lname = lastName.getText();
String cEmail = email.getText();
String rate = rateDbl.getText();
String cUrl = url.getText();
try {
Connection con = DriverManager.getConnection(sqlUrl, user, pass);
PreparedStatement st = con.prepareStatement("insert into clients
values('"+name+"', '"+lname+"', "
+ "'"+cEmail+"', '"+rate+"', '"+cUrl+"')");
JOptionPane.showMessageDialog(null, "Data saved!");
} catch (SQLException ex) {
Logger.getLogger(newClient.class.getName()).log(Level.SEVERE, null, ex);
}
What am I doing wrong
Well, you're building your SQL statement by concatenating values. That leads to SQL injection attacks - amongst other issues. Fortunately, that hasn't actually created a problem just yet - because you're never executing your statement.
You need to:
Parameterize your SQL, to avoid a SQL injection attack - use question marks for the parameters, and then use st.setString to set each parameter:
Connection con = DriverManager.getConnection(sqlUrl, user, pass);
PreparedStatement st = con.prepareStatement(
"insert into clients values (?, ?, ?, ?, ?)");
st.setString(1, name);
st.setString(2, lname);
st.setString(3, cEmail);
st.setString(4, rate); // Should this really be a string?
st.setString(5, cUrl);
st.executeUpdate();
JOptionPane.showMessageDialog(null, "Data saved!");
Call st.executeUpdate before you display the dialog box. (Ideally you shouldn't be mixing UI and data access in the same method, but...)
Please make the changes in that order though - do not just add a call to st.executeUpdate, or you've got a horrible security hole in your app.
The reason you're not seeing the data is you prepare the statement but never execute it. Call st.execute(); or st.executeUpdate(); to execute it.
Separately, though: That code is subject to SQL injection (attacks or otherwise); fun illustration here. Half the point of prepared statements is to protect against them. Use the parameters that prepared statements give you:
PreparedStatement st = con.prepareStatement("insert into clients values(?, ?, ?, ?, ?)");
int n = 1;
st.setString(n++, name);
st.setString(n++, lname);
st.setString(n++, cEmail);
st.setString(n++, rate);
st.setString(n++, cUrl);
// And then the missing execute
st.execute();

error java.sql.SQLException: Parameter index out of range

I still get error that I don't provide value for 1 parameter and I don't have idea what is wrong.
ps("INSERT INTO slide (presentation_id, duration, position, type) values (?, ?, ?, ?) ").set(this.getId()).set(slide.getDuration()).set(slide.getPosition()).set(slide.getType().ordinal()).update();
In table I only do not provide value for one column for which autoincrement is set.
Everything seems alright for me but please give any advice what might be wrong.
dont include the auto inc fieldin your column list.
ps("INSERT INTO slide (duration, position, type) values (?, ?, ?) ").set(slide.getDuration()).set(slide.getPosition()).set(slide.getType().ordinal()).update();
Try to do something more clean instead of this "train code"
This is an example:
String insertTableSQL = "INSERT INTO DBUSER"
+ "(USER_ID, USERNAME, CREATED_BY, CREATED_DATE) VALUES"
+ "(?,?,?,?)";
PreparedStatement preparedStatement = dbConnection.prepareStatement(insertTableSQL);
preparedStatement.setInt(1, 11);
preparedStatement.setString(2, "mkyong");
preparedStatement.setString(3, "system");
preparedStatement.setTimestamp(4, getCurrentTimeStamp());
// execute insert SQL stetement
preparedStatement .executeUpdate();
and here is the link to follow: http://www.mkyong.com/jdbc/jdbc-preparestatement-example-insert-a-record/

Categories