JAVA & SQL database save changes - java

I am working on Java GUI application which connects to SQL database on localhost (I use XAMPP). When I change some entry, for example Age, I click on "Save changes", it is saved and changes are done in SQL database, but when I click on ">" or "<" to view next or previous person and then go back to the person, where I did changes, every entry is without changes in its initial state. But when I close the application and reopen it, all the changes which I made are done. This is part of the code where is mistake, I think. Thank you.
private void jButtonSaveChangesActionPerformed(java.awt.event.ActionEvent evt) {
try {
Statement stmt = con.createStatement();
try {
String query1 = "UPDATE list1 SET " +
"name ='" + jTextFieldName.getText() + "', " +
"surname ='" + jTextFieldSurname.getText() + "', " +
"age ='" + jTextFieldAge.getText() + "' " +
"WHERE ID = " + jLabelActualID.getText();
stmt.executeUpdate(query1);
} catch (Exception e) {
System.err.println(e);
}
} catch (Exception e) {
System.err.println(e);
}
}
Picture of application:

You are not closing, which can be done more safe and automatically with try-with-resources.
This means a commit might not have happened yet. There is an autocommit setting too.
String query1 = "UPDATE list1 SET " +
"name = ?, " +
"surname = ?, " +
"age = ? " +
"WHERE ID = ?";
try (PreparedStatement stmt = con.prepareStatement(query1)) { // Closes stmt.
stmt.setString(1, jTextFieldName.getText());
stmt.setString(2, jTextFieldSurname.getText());
stmt.setInt(3, Integer.parseInt(jTextFieldAge.getText()));
stmt.setString(4, jLabelActualID.getText());
int updateCount = stmt.executeUpdate();
} catch (SQLException | NumberFormatException e) {
System.err.println(e);
}
The same may hold (or may not hold) for the SQL connection.
Also one should use a PreparedStatement for security (SQL injection) and type safeness / escaping of backslash, quote in strings. As you see it is even more readable.
Another case is a second application accessing the database: it can use its own cache, thereby be a bit outdated.

Related

Java & SQL prepareStatement error (Parameter index out of range)

I've been trying to fix a part of my code that throws a
java.sql.SQLException: Parameter index out of range (2 > number of parameters, which is 1).
I already searched stackoverflow and other parts of the internet but couldnt find the solution, that corrected the error.
This is the start of the class file:
PreparedStatement stmt;
And this is my constructer:
public DataAccessObjectImpl() throws Exception {
this.conn = new DBConnector();
}
This is the method thats cause the problem:
#Override
public boolean addAlbum(int UID, String artist, String album) {
String sql = "";
try {
stmt = conn.getConnection().prepareStatement("INSERT INTO music (identifier, UID, artist, album) VALUES (?,?,?,?);");
stmt.setString(1, getNewIdentifier());
stmt.setInt(2, UID);
stmt.setString(3, artist);
stmt.setString(4, album);
stmt.executeUpdate();
} catch (Exception ex) {
System.out.println("nugget 1 : " + ex);
} finally {
try {
if (stmt != null) {
stmt.close();
return true;
}
} catch (Exception e) {
System.out.println("Nugget 2 : " + e);
}
}
return false;
}
(the word "nugget" is just so its easy for myself to find in the log / console)
From what i could gather on stackoverflow its probably my question marks thats the problem, but I can't seem to figure out how. I used prepareStatement for other methods thats working just fine in the same class.
I have some working code I provided down below, I want to replace this code with preparestatement to patch SQL Injection:
try {
stmtb = conn.getConnection().createStatement();
sql = "INSERT INTO music VALUES ('" + getNewIdentifier() + "','" + UID + "','" + artist + "','" + album + "')";
} catch (SQLException ex) {
}
try {
stmt.executeUpdate(sql);
return true;
} catch (Exception e) {
System.out.println(e);
}
return false;
Thank you in advanced!
Fixed by changing this line:
stmt = conn.getConnection().prepareStatement("INSERT INTO music (identifier, UID, artist, album) VALUES (?,?,?,?);");
and i changed it to this:
PreparedStatement stmt = conn.getConnection().prepareStatement("SELECT * FROM user WHERE username = (?);");
and deleted this line:
PreparedStatement stmt;
Thank you Kayaman for the help!
Since the query is correct, but the exception occurs, the only possible explanation is that the stmt gets corrupted somehow. The only realistic situation would be in a multi-threaded environment with multiple threads using the same stmt to perform queries.
Since you're using prepareStatement() to create a new PreparedStatement object, there's no reason to share a "global" reference. In most cases the best practice is to define and use variables in the smallest scope possible.
Therefore remove the stmt variable from the outer scope, and instead just write
PreparedStatement stmt = conn.getConnection().prepareStatement(query);
where ever you need to.
In the query, which works, UID is passed like a VARCHAR, because it is surrounded with ''
sql = "INSERT INTO music VALUES ('" + getNewIdentifier() + "','" + UID + "','" + artist + "','" + album + "')";
Please, re-check database schema and ensure that UID is INTEGER. Also you may try to replace
stmt.setInt(2, UID);
with
stmt.setString(2, Integer.toString(UID));
to replicate simple Statement behaviour.

Search the MYSQL Database filtering using either first name or last name typed in JTextfield on JTable

I want to use either last name or first name to filter result shown on JTable from the database such that when i type either Nikola or Tesla in the JTextfield, the row with either of the names is filtered.
I have stored name as one field in the database i.e 'Nikola Tesla' when i type Nikola, it is working right and when i type Tesla it shows no result.
I have one field for name that stores both names.
I don't want to have separate First_Name and Last_Name field.
Please suggest what i should add on my code shown below:
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();
}
}
You need to add % before the jTextFieldSearch.getText() also. See below
pstmt.setString(1, "%" + jTextFieldSearch.getText() + "%");
The true solution is this, you should to use %% inside quots '%%', without quotes you get that error:
LIKE '%Name%'
so, with prepared statement we should to change Name with ? and the result is like that:
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";
i hope this can help you, good luck.

Code exiting try and going in catch after first executeQuery?

I am a beginner in android development. This is a part of my sign up code in my first android studio app: The code is going into catch right after the first execute query line and not executing my second query. If i check the Database a user is added but not a fan.
Any idea why? Any help is appreciated.
try {
Connection con = connectionClass.CONN();
if (con == null) {
z = "Error in connection with SQL server";
} else {
Statement stmt = con.createStatement();
String query1 = "INSERT INTO Usertb Values ('" + userid + "', '" + Password + "', '" + 1 + "')";
stmt.executeQuery(query1);
String query = "INSERT INTO Fan Values ('" + FirstName + "', '" + LastName + "','" + Age + "', '" + Email + "', '"
+ null + "', '" + i + "', '" + null + "')";
rs = stmt.executeQuery(query);
if (rs.next()) {
z = "Sign Up successfull";
isSuccess = true;
}
}
} catch (Exception ex) {
isSuccess = false;
z = "Exceptions";
}
One has to use executeUpdate (INSERT/UPDATE) instead of executeQuery.
String sql = "INSERT INTO Usertb(userid, passw, n) VALUES (?, PASSWORD(?), ?)";
try (PreparedStatement stmt = con.prepareStatement(sql, Statement.RETURN_GENERATED_KEYS)) {
stmt.setString(1, userName);
stmt.setString(2, password);
stmt.setInt(3, 1);
int updateCount = stmt.executeUpdate(query1); // 1 when 1 record inserted
if (updateCount != 0) {
// If you want to use an autincrement primary key:
try (ResultSet rsKeys = stm.getGeneratedKeys()) {
if (rsKeys.next()) {
long id = rsKeys.getLong(1);
}
}
}
} // Closes stmt
Furthermore it is very important to use prepared statements to prevent SQL injection. It also takes care of single quotes and backslash in the strings.
Additionally there is shown how to use AUTOINCR fields, to retrieve a database generated key, for example for the second INSERT.
For the second use a new PreparedStatement.
Passwords should better be stored encrypted in the database, should someone steal the data. You might look into that subject. My solution is quite minimal, look for seeding and other encryption functions.

ORA-00917: missing comma - Insert query failed

I'm trying to create insert query in JSP page as follows
try
{
Class.forName("oracle.jdbc.driver.OracleDriver");
}
catch (ClassNotFoundException e)
{
e.printStackTrace();
}
try
{
connection = DriverManager.getConnection(
"jdbc:oracle:thin:#localhost:1521:" + "XE", "hr","hr");
if (connection != null)
{
statement = connection.createStatement();
String q2 = "INSERT INTO HR.tweets (";
q2 = q2 + "DATE_TIME,USER_NAME,TWEET_BEFORE,TWEET_AFTER)";
q2 = q2 + "VALUES (";
q2 = q2 + "(select SYSDATE from dual),";
q2 = q2 + "'" + tweet.getUser().getScreenName() + "'" + ",";
q2 = q2 + "'" + tweet.getText() + "'" +",";
q2 = q2 + "'" + finalstring + "')";
statement.execute(q2);
statement.close();
connection.close();
}
}
catch (SQLException e)
{
e.printStackTrace();
}
At statement.execute(q2) I'm getting ORA-00917: missing comma error.
The following query is created in a code :
INSERT INTO HR.tweets (DATE_TIME,USER_NAME,TWEET_BEFORE,TWEET_AFTER)VALUES ((select SYSDATE from dual),'Dannazxcv','RT #HugotInhinyero: Wish we could turn back time to the good old days. When our mama sings us to sleep but now we're stressed out.🎶🎶
#engin…','hugotinhinyero turn back time good days. mama sing sleep we're stress out. engin' )
Please help me.
Your SQL insert has an syntax error since one of your parameters contains a ':
'hugotinhinyero turn back time good days. mama sing sleep we're stress out. engin'
To avoid this kind of errors, don't build SQL strings manually, but use a PreparedStatement and parameters instead:
String insert = "INSERT INTO HR.tweets (DATE_TIME,USER_NAME,TWEET_BEFORE,TWEET_AFTER) " +
" VALUES ((select SYSDATE from dual),?,?,?)";
PreparedStatement stmt = connection.prepareStatement(insert);
stmt.setParameter(1, tweet.getUser().getScreenName());
stmt.setParameter(2, tweet.getText());
stmt.setParameter(3, finalstring);
stmt.executUpdate();
Use PreparedStatement instead of Statement.
Your query will always fail if any of your field will contain quote character (').
Besides, your query is vulnerable to SQL injection attack, while PreparedStatement guards against a such attack.
Details on PreparedStatement can be found in this tutorial:
http://docs.oracle.com/javase/tutorial/jdbc/basics/prepared.html
This is a very very basic knowledge so I dont't explain it here.
The problem here is that you are using special characters, which causes the statement sent through to the database to be invalid.
Try using a prepared statement like this...
PreparedStatement pstatement = null;
Connection connection = null;
try
{
connection = DriverManager.getConnection(
"jdbc:oracle:thin:#localhost:1521:" + "XE", "hr","hr");
if (connection != null)
{
pstatement = connection.prepareStatement("INSERT INTO HR.tweets (DATE_TIME,USER_NAME,TWEET_BEFORE,TWEET_AFTER) VALUES ((select SYSDATE from dual),?,?,?)");
q2 = q2 + "'" + tweet.getUser().getScreenName() + "'" + ",";
q2 = q2 + "'" + tweet.getText() + "'" +",";
q2 = q2 + "'" + finalstring + "')";
pstatement.setString(1, tweet.getUser().getScreenName());
pstatement.setString(2,tweet.getText());
pstatement.setString(3, finalstring);
pstatement.execute();
}
}
catch (SQLException e)
{
e.printStackTrace();
}finally{
pstatement.close();
connection.close();
}
...prepared statements usually take care of malformed strings and invalid quotes sent to the DB.
As mentioned by #wero, the issue with the query is that it contains a quote ('). To escape it you can use a backslash (\).
Eg: we\'re
However like other's have suggested, its safer to use prepared-statements which also take care of guarding against sql-injection as a bonus !

Data does not get inserted into the table sometime

I have a table A. I insert data into table A through a user interface. Table A has an ID(primary key), which is generated using a sequence, and 16 other columns. One of the column is called cntrct_no.
When I try to insert data into the table through UI, it works fine the first time. I check the table A and all the data are there.
But when I try to insert the same data again without changing anything, it looks like the data is getting added to the table and I do not get any errors. But when I check table A, the data inserted the second time is not there.
If I try to insert the same data directly thorough SQL developer, the data gets inserted into the table.
The weird thing is if I just change the value of the cntrct_no in the UI and leave rest of the data same, the data gets inserted.
Can anyone please explain to me what could possibly cause this?
Not sure if this helps: stmt.executeUpdate(); returns 0 when the data is not inserted and a 1 when it's inserted.
public void writeToAudit(String contractNo, String tripNo,
String tripEffDate,
String tripDiscDate, String transpModeId, String userId,
String transType, AplLeg[] legs) {
final Session session = HibernateUtil.getSession();
Connection con = null;
con = session.connection();
PreparedStatement stmt = null;
PreparedStatement stmtSelId = null;
ResultSet rs = null;
long nextId = -1;
int i=0;
try {
for(i=0;i<legs.length;i++) {
String sqlNextId = "SELECT rpt_audit_transportation_seq.NEXTVAL as seqval FROM DUAL";
stmtSelId = con.prepareStatement(sqlNextId, ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_UPDATABLE);
rs = stmtSelId.executeQuery();
rs.last();
final int rows = rs.getRow();
if (rows == 0){
nextId = -1;
}
rs.beforeFirst();
rs.next();
nextId = rs.getInt(1);
if(nextId==-1)
throw new SQLException("Cannot get next val from rpt_audit_transportation sequence.");
stmt = con.prepareStatement(WRITE_TO_AUDIT_DML);
stmt.setLong(1, nextId);
stmt.setString(2, userId.toUpperCase());
stmt.setString(3, transType);
stmt.setString(4, contractNo);
stmt.setString(5, tripNo);
stmt.setInt(6, Integer.parseInt(transpModeId));
stmt.setString(7, tripEffDate);
stmt.setString(8, tripDiscDate);
stmt.setLong(9, legs[i].getLegId().longValue());
int temp = stmt.executeUpdate();
con.commit();
}
stmt.close();
}
catch (Exception e) {
}
finally {
closeConnection(session, con, stmtSelId, rs);
}
}
THE SQL STATEMENT:
private static final String WRITE_TO_AUDIT_DML =
"INSERT INTO rpt_audit_transportation " +
"(audit_id, audit_date, audit_process, audit_userid, " +
"audit_trans_type, audit_route_no, audit_trip_no, " +
"audit_eff_dt, audit_disc_dt, audit_orig_facility_id, " +
"audit_dest_facility_id, audit_arvl_tm, audit_dprt_tm, " +
"audit_leg_seq_no, audit_freq_id, audit_trnsp_mode_id) " +
"(SELECT ?, " + // audit id
"SYSDATE, " +
"'TOPS_UI', " +
"?, " + // userId
"?, " +
"rte.cntrct_no, " +
"trp.trip_no, " +
"rte.cntrct_eff_dt, " +
"rte.cntrct_disc_dt, " +
"NVL(leg.orig_facility_id, trp.orig_fac_id), " +
"NVL(leg.dest_facility_id, trp.dest_fac_id), " +
"NVL(leg.arvl_tm, trp.arvl_tm), " +
"NVL(leg.dprt_tm, trp.dprt_tm), " +
"leg.leg_seq, " +
"trp.freq_id, " +
"rte.trnsp_mode_id " +
"FROM apl_contract rte, " +
"apl_trip trp, " +
"apl_leg leg " +
"WHERE rte.cntrct_no = ? " + // contract id
"AND trp.trip_no = ? " + // trip no
"AND rte.trnsp_mode_id = ? " + // transp mode id
"AND rte.cntrct_locked_ind = 'N' " +
"AND trp.trip_eff_dt = to_date(?,'MM/DD/YYYY') " + // trip eff date
"AND trp.trip_disc_dt = to_date(?,'MM/DD/YYYY') " + // trip disc date
"AND trp.cntrct_id = rte.cntrct_id " +
"AND leg.trip_id = trp.trip_id " +
"AND leg.leg_id = ?) ";
Looks like you're not inserting plain values, but a result of a select based on the parameters.
What you are using is an INSERT ... SELECT () clause, so if the SELECT part does not return any rows, the INSERT won't insert anything, and stmt.executeUpdate() will return 0. Find out why SELECT returns no rows.
This may be due some triggers saving stuff in other tables when you do the insert into rpt_audit_transportation, but it's just a guess.
The problem is that you have a catch that is swallowing your exceptions
catch (Exception e) {
}
That means that when the SQL statement throws an error, you're telling your code to catch the exception and ignore it. It is almost always an error to do that since, as you're discovering, it means that your code can fail to do what you expect with no way of letting you know that something failed. At a minimum, you would need to log the exception somewhere. In general, though, if you cannot fix whatever condition lead to the exception, you ought to re-raise the exception or simply not catch it in the first place.
My guess is that the second insert is violating some constraint defined on the table. But since your code is catching the exception and throwing it away, you're not being notified that there was a constraint violation nor is your code noting which constraint was violated.
When the cntrct_no is same you are getting an exception and you are supperessing that as told by #Justin Cave. This may be because you are having a unique constraint for that field and the DB throws an error and you are suppressing.
When cntrct_no is changed - obviously the constraint wont fail and for primary key since you are using the sequence it would have generated the next number and it happily gets inserted in the DB.
Don't ever suppress the exception. Do some thing in that block either rethrow as application specific exception or convert to error code and propagate that to the front end.

Categories