Rollback transaction not working properly - mysql

In database manipulation command such as insert, update or delete can sometime throws exception due to invalid data. To protect the integrity of application data we must make sure when we a transaction was failed we must rollback
PreparedStatement ps = null;
Connection conn = null;
try {
conn = DriverManager.getConnection( URL, USERNAME, PASSWORD );
String query = "INSERT INTO tbl1(id, username) " +
"VALUES (?, ?)";
ps = conn.prepareStatement( query );
ps.setString( 1, "javaduke" );
ps.execute();
query = "INSERT INTO tbl2 (id, tbl1_id, " +
"quantity, price) VALUES (?, ?, ?, ?)";
ps = conn.prepareStatement( query );
ps.setInt( 1, id );
ps.setInt( 2, tbl_id );
ps.setInt( 3, 10 );
ps.setDouble( 4, 29.99 );
ps.execute();
}
catch ( SQLException e )
{
conn.rollback()
e.printStackTrace();
}

I guess this is Java.
Right after you get your connection object, turn off autocommit, like so.
conn = DriverManager.getConnection( URL, USERNAME, PASSWORD );
conn.setAutoCommit(false);
Right after your last execute() do this.
conn.commit();
Then the rollback() in your exception handler should do what you expect.
This should extend the scope of your transaction to beyond a single SQL query.

Related

Spark jdbc batch processing not inserting all records

In my spark job, I'm using jdbc batch processing to insert records into MySQL. But I noticed that all the records were not making it into MySQL. For example;
//count records before insert
println(s"dataframe: ${dataframe.count()}")
dataframe.foreachPartition(partition => {
Class.forName(jdbcDriver)
val dbConnection: Connection = DriverManager.getConnection(jdbcUrl, username, password)
var preparedStatement: PreparedStatement = null
dbConnection.setAutoCommit(false)
val batchSize = 100
partition.grouped(batchSize).foreach(batch => {
batch.foreach(row => {
val productName = row.getString(row.fieldIndex("productName"))
val quantity = row.getLong(row.fieldIndex("quantity"))
val sqlString =
s"""
|INSERT INTO myDb.product (productName, quantity)
|VALUES (?, ?)
""".stripMargin
preparedStatement = dbConnection.prepareStatement(sqlString)
preparedStatement.setString(1, productName)
preparedStatement.setLong(2, quantity)
preparedStatement.addBatch()
})
preparedStatement.executeBatch()
dbConnection.commit()
preparedStatement.close()
})
dbConnection.close()
})
I see 650 records in the dataframe.count but when I checked mysql, I see 195 records. And this is deterministic. I tried different batch sizes and still see the same number. But when I moved preparedStatement.executeBatch() inside the batch.foreach() i.e. the next line right after preparedStatement.addBatch(), I see the full 650 records in mysql..which isnt batching the insert statements anymore as its executing it immediately after adding it within a single iteration. What could be the issue preventing batching the queries?
It seems you're creating a new preparedStatement in each iteration, which means preparedStatement.executeBatch() is applied to the last batch only i.e. 195 instead of 650 records. Instead, you should create one preparedStatement then substitute the parameters in the iteration, like this:
dataframe.foreachPartition(partition => {
Class.forName(jdbcDriver)
val dbConnection: Connection = DriverManager.getConnection(jdbcUrl, username, password)
val sqlString =
s"""
|INSERT INTO myDb.product (productName, quantity)
|VALUES (?, ?)
""".stripMargin
var preparedStatement: PreparedStatement = dbConnection.prepareStatement(sqlString)
dbConnection.setAutoCommit(false)
val batchSize = 100
partition.grouped(batchSize).foreach(batch => {
batch.foreach(row => {
val productName = row.getString(row.fieldIndex("productName"))
val quantity = row.getLong(row.fieldIndex("quantity"))
preparedStatement = dbConnection.prepareStatement(sqlString)
preparedStatement.setString(1, productName)
preparedStatement.setLong(2, quantity)
preparedStatement.addBatch()
})
preparedStatement.executeBatch()
dbConnection.commit()
preparedStatement.close()
})
dbConnection.close()
})

"JSP First Connection cause second connection not running when it had ended"

I'm trying to get two data(GenreID & GameID) from two different tables(genre & games) and insert them into another table(games_genre). However, it will close the connection to the database after inserting the GenreID successfully even though i had created another new connection to the database.
I have tried to create connection1 and connection2 to the same database. Connection1 is used to insert GenreID and connection2 is used to insert GameID
<%# page import="java.sql.*,java.util.*,java.text.*,java.text.SimpleDateFormat" %>
String gametitle = request.getParameter("gametitle");
String [] checkbox1 = request.getParameterValues("checkbox");
try {
Class.forName("com.mysql.cj.jdbc.Driver");
String connURL ="jdbc:mysql://localhost/assignment?user=root&password=root&serverTimezone=UTC";
Connection conn = DriverManager.getConnection(connURL);
Connection conn2 = DriverManager.getConnection(connURL);
Statement stmt = conn.createStatement();
if (checkbox1!= null){
for(String s: checkbox1){
String sqlStr2 = "Select * FROM genre WHERE GenreName='" + s + "'";
ResultSet rs = stmt.executeQuery(sqlStr2);
while(rs.next()){
String genreid = rs.getString("GenreID");
String sqlStr3 = "INSERT INTO games_genre(GenreID) VALUES ('" + genreid + "')";
int j = stmt.executeUpdate(sqlStr3);
if (j>0) {
out.println("Adding GenreID Successfully!");}
}
}
}
conn.close();
Statement stmt2 = conn2.createStatement();
String sqlStr4 = "Select * FROM games WHERE GameTitle='" + gametitle +"'";
ResultSet rs2 = stmt2.executeQuery(sqlStr4);
if(rs2.next()){
String gameid = rs2.getString("GameID");
String sqlStr5 = "INSERT INTO games_genre(GameID) VALUES ('" + gameid + "')";
int k = stmt2.executeUpdate(sqlStr5);
if (k>0) {
out.println("Adding GameID Successfully!");
}
}
conn2.close();
} catch (Exception e) {
out.println("Error :" + e);
}
Adding Game Successfully! Adding GenreID Successfully! Error :java.sql.SQLException: Operation not allowed after ResultSet closed
I don't understand that why do you need to create two Connection as you need to access same database . So ,just create multiple Statement to execute multiple query like below :
Statement stmt=null;
Statement stmt2=null;
try {
Class.forName("com.mysql.cj.jdbc.Driver");
String connURL ="jdbc:mysql://localhost/assignment?user=root&password=root&serverTimezone=UTC";
Connection conn = DriverManager.getConnection(connURL);
stmt = conn.createStatement();
if (checkbox1!= null){
....
}
<!--using same conn object -->
stmt2 = conn.createStatement();
String sqlStr4 = "Select * FROM games WHERE GameTitle='" + gametitle +"'";
ResultSet rs2 = stmt2.executeQuery(sqlStr4);
if(rs2.next()){
...
}
<!--finally close connection-->
conn.close();
} catch (Exception e) {
out.println("Error :" + e);
}
Note : Also try using PreparedStatement for preventing from Sql Injection as concatenating values into a query string is unsafe .

How to read a data file and insert data into a mysql database

I am new to Java and I'm trying to insert data into a mysql database using a text file. My text file has 5 rows. I have 3 SQL insert Queries. Each query will insert 5 rows into the database.
Example queries are:
INSERT INTO `session` (`emp`, `SessionID`, `SessionDate`, `SessionStartTime`, 'SessionEndTime') VALUES (Tyler, NULL, ?, ?, ?);
INSERT INTO `session` (`emp`, `SessionID`, `SessionDate`, `SessionStartTime`,'SessionEndTime') VALUES (MAX, NULL, ?, ?, ?);
INSERT INTO `session` (`emp`, `SessionID`, `SessionDate`, `SessionStartTime`,'SessionEndTime') VALUES (James, NULL, ?, ?, ?);
Example text file:
textfile
Here is a snippet of my code. I having problems with figuring out how to read the text file and inserting it into the database. Note that the code only has one my queries. I'm trying to get one query to work before adding the others.
I'm looking for some advice on reading the file and the prepared statements for the date, start time, and end time.
any suggestions?
try
{
//Create a mysql database connection
String dbUrl = "jdbc:mysql://localhost:3306/mytest";
String username = "root"; //Database Username
String password = "abcdefg"; //Database Password
Class.forName("com.mysql.jdbc.Driver"); //Load mysql jdbc driver
Connection con = DriverManager.getConnection(dbUrl,username,password); //Create Connection to DB
// mysql query to insert data into session table
String query = " INSERT INTO `session` (`emp`, `SessionID`,
`SessionDate`, `SessionStartTime`) VALUES (Tyler, NULL, ?, ?, ?);
try {
BufferedReader bReader = new BufferedReader(newFileReader("c:/sessionstime"));
String line = "";
while ((line = bReader.readLine()) != null)
{
try
{
if (line != null)
{
String[] array = line.split(",");
for(String result:array)
{
// create mysql insert preparedstatement
PreparedStatement preparedStmt = con.prepareStatement(query);
preparedStmt.setDate (1, sessiondate[0]);
preparedStmt.setTime (2, sessionstarttime[1]);
preparedStmt.setTime (3, sessionendtime[2]);
preparedStmt.addBatch();
// execute the preparedstatement
preparedStmt.executeBatch();
// close database connection
con.close();
}
catch (Exception e)
{
System.err.println("Got an exception!");
System.err.println(e.getMessage());
}

Insert values in existing record. sqlite using prepared statement

I want to insert values into an existing record using prepared statment. The value of that record is the last record inserted, I tried LAST function and MAX but it didn't seems to work, also I tried SELECT statment inside INSERT with no luck.
public static void insertCoordinates(){
java.sql.Connection c = null;
try {
String str1 = Singelton.getInstance().getTxtField1().getText();
Class.forName("org.sqlite.JDBC");
c = DriverManager.getConnection("jdbc:sqlite:timeline_DB.db");
c.setAutoCommit(false);
PreparedStatement preparedStatement = c.prepareStatement("insert into event_table(bar_length, x_bar, y_bar) values (?, ?, ?) WHERE event_title =?");
preparedStatement.setInt(1, CanvasNewTimeLine.Event_length);
preparedStatement.setInt(2, CanvasNewTimeLine.x);
preparedStatement.setInt(3, CanvasNewTimeLine.H_LINE);
preparedStatement.setString(4,str1);
preparedStatement.executeUpdate();
c.commit();
c.close();
} catch ( Exception e ) {
System.err.println( e.getClass().getName() + ": " + e.getMessage() );
System.exit(0);
System.err.println("problem");
}
System.out.println("yesssssss successfully");
}
I used update instead of insert:
public static void insertCoordinates(){
java.sql.Connection c = null;
try {
String str1 = Singelton.getInstance().getTxtField1().getText();
Class.forName("org.sqlite.JDBC");
c = DriverManager.getConnection("jdbc:sqlite:timeline_DB.db");
c.setAutoCommit(false);
String updateTableSQL = "UPDATE event_table SET bar_length = ?, x_bar=?, y_bar=? WHERE event_title = ?";
PreparedStatement preparedStatement = c.prepareStatement(updateTableSQL);
preparedStatement.setInt(1, CanvasNewTimeLine.Event_length);
preparedStatement.setInt(2, CanvasNewTimeLine.x);
preparedStatement.setInt(3, CanvasNewTimeLine.H_LINE);
preparedStatement.setString(4,str1);
// execute
preparedStatement .executeUpdate();
c.commit();
c.close();
} catch ( Exception e ) {
System.err.println( e.getClass().getName() + ": " + e.getMessage() );
System.exit(0);
System.err.println("problem");
}
System.out.println("yesssssss successfully");
}

Prepared Statement INSERT JDBC MySQL

I am getting an error on doing ' mvn tomcat:run " . The error I am getting is:
exception
org.springframework.web.util.NestedServletException: Request processing failed; nested exception is org.springframework.jdbc.BadSqlGrammarException: PreparedStatementCallback; bad SQL grammar [INSERT INTO ibstechc_dev.device (key, ip_address, type, name) VALUES (?, ?, ?, ?)]; nested exception is 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 'key, ip_address, type, name) VALUES ('abcd', 'abcd', 1234, 'abcd')' at line 1
root cause
org.springframework.jdbc.BadSqlGrammarException: PreparedStatementCallback; bad SQL grammar [INSERT INTO ibstechc_dev.device (key, ip_address, type, name) VALUES (?, ?, ?, ?)]; nested exception is 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 'key, ip_address, type, name) VALUES ('abcd', 'abcd', 1234, 'abcd')' at line 1
org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator.doTranslate(SQLErrorCodeSQLExceptionTranslator.java:237)
org.springframework.jdbc.support.AbstractFallbackSQLExceptionTranslator.translate(AbstractFallbackSQLExceptionTranslator.java:72
My code segment is:
List<Device> devices = this.jdbcTemplate.query(
"select * from xyz.device a,xyz.user_device b "
+ "where b.user_id = ? and a.device_id = b.device_id and "
+ "a.type = ?",
new Object[]{userId,type},
new RowMapper<Device>() {
public Device mapRow(ResultSet rs, int rowNum) throws SQLException {
Device device = new Device();
device.setId(Long.valueOf(rs.getInt(1)));
device.setKey(rs.getString(2));
device.setIPAddress(rs.getString(3));
device.setType(rs.getInt(4));
device.setName(rs.getString(5));
return device;
}
});
System.out.println("Found for user..." + userId);
return devices;
}
public void create(Device device) {
this.jdbcTemplate.update("INSERT INTO xyz.device (key, ip_address, type, name) VALUES (?, ?, ?, ?)",
new Object[]{device.getKey(), device.getIPAddress(), device.getType(), device.getName()});
}
public void delete(Device device) {
this.jdbcTemplate.update("DELETE FROM xyz.device WHERE device_id = ?", new Object[] {device.getId()});
}
public void update(Device device) {
this.jdbcTemplate.update(
"UPDATE xyz.device SET key = ?, ip_address = ?, type = ?, name =? WHERE device_id = ?", new Object[]{device.getId(),device.getKey(), device.getIPAddress(), device.getType(), device.getName()});
And my Debug.java code is:
public String getNavBarData(){
Device device = new Device();
device.setKey("abcd");
device.setIPAddress("abcd");
device.setType(1234);
device.setName("abcd");
deviceDao.create(device);
return "";
The MySQL table has the same columns as in my code above with NOT NULL for each field. I have used the same code for a different functionality and it works there. Why am I getting this error for this one? Pls. Help.
KEY is a reserved word in Mysql. Therefore you either rename the column (which is better in a long run) or use back ticks around it.
That being said you insert statement should look like this
INSERT INTO xyz.device (`key`, ip_address, type, name) VALUES (?, ?, ?, ?)
^ ^
The same goes to your update statement
UPDATE xyz.device SET `key` = ?, ip_address = ?, type = ?, name =? WHERE device_id = ?
^ ^