详解Java的JDBC API中事务的提交和回滚
如果JDBC连接是在自动提交模式下,它在默认情况下,那么每个SQL语句都是在其完成时提交到数据库。
这可能是对简单的应用程序,但有三个原因,你可能想关闭自动提交和管理自己的事务:
- 为了提高性能
- 为了保持业务流程的完整性
- 使用分布式事务
若要控制事务,以及何时更改应用到数据库。它把单个SQL语句或一组SQL语句作为一个逻辑单元,而且如果任何语句失败,整个事务失败。
若要启用,而不是JDBC驱动程序默认使用auto-commit模式手动事务支持,使用Connection对象的的setAutoCommit()方法。如果传递一个布尔值false到setAutoCommit(),关闭自动提交。可以传递一个布尔值true将其重新打开。
例如,如果有一个名为connConnection对象,以下代码来关闭自动提交:
conn.setAutoCommit(false);
提交和回滚
一旦已经完成了变化,要提交更改,然后调用commit(在连接对象)方法,如下所示:
conn.commit();
否则回滚更新对数据库所做的使用命名连接conn,使用下面的代码:
conn.rollback();
下面的例子演示了如何使用一个提交和回滚对象:
try{
//Assumeavalidconnectionobjectconn
conn.setAutoCommit(false);
Statementstmt=conn.createStatement();
StringSQL="INSERTINTOEmployees"+
"VALUES(106,20,'Rita','Tez')";
stmt.executeUpdate(SQL);
//SubmitamalformedSQLstatementthatbreaks
StringSQL="INSERTEDINEmployees"+
"VALUES(107,22,'Sita','Singh')";
stmt.executeUpdate(SQL);
//Ifthereisnoerror.
conn.commit();
}catch(SQLExceptionse){
//Ifthereisanyerror.
conn.rollback();
}
在这种情况下没有上述INSERT语句会成功,一切都将被回滚。
事务提交和回滚示例
以下是使用事务提交和回滚描述的例子。
基于对环境和数据库安装在前面的章节中做此示例代码已学习过。
复制过去下面的例子中JDBCExample.java,编译并运行,如下所示:
//STEP1.Importrequiredpackages
importjava.sql.*;
publicclassJDBCExample{
//JDBCdrivernameanddatabaseURL
staticfinalStringJDBC_DRIVER="com.mysql.jdbc.Driver";
staticfinalStringDB_URL="jdbc:mysql://localhost/EMP";
//Databasecredentials
staticfinalStringUSER="username";
staticfinalStringPASS="password";
publicstaticvoidmain(String[]args){
Connectionconn=null;
Statementstmt=null;
try{
//STEP2:RegisterJDBCdriver
Class.forName("com.mysql.jdbc.Driver");
//STEP3:Openaconnection
System.out.println("Connectingtodatabase...");
conn=DriverManager.getConnection(DB_URL,USER,PASS);
//STEP4:Setautocommitasfalse.
conn.setAutoCommit(false);
//STEP5:Executeaquerytocreatestatmentwith
//requiredargumentsforRSexample.
System.out.println("Creatingstatement...");
stmt=conn.createStatement(
ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_UPDATABLE);
//STEP6:INSERTarowintoEmployeestable
System.out.println("Insertingonerow....");
StringSQL="INSERTINTOEmployees"+
"VALUES(106,20,'Rita','Tez')";
stmt.executeUpdate(SQL);
//STEP7:INSERTonemorerowintoEmployeestable
SQL="INSERTINTOEmployees"+
"VALUES(107,22,'Sita','Singh')";
stmt.executeUpdate(SQL);
//STEP8:Commitdatahere.
System.out.println("Commitingdatahere....");
conn.commit();
//STEP9:Nowlistalltheavailablerecords.
Stringsql="SELECTid,first,last,ageFROMEmployees";
ResultSetrs=stmt.executeQuery(sql);
System.out.println("Listresultsetforreference....");
printRs(rs);
//STEP10:Clean-upenvironment
rs.close();
stmt.close();
conn.close();
}catch(SQLExceptionse){
//HandleerrorsforJDBC
se.printStackTrace();
//Ifthereisanerrorthenrollbackthechanges.
System.out.println("Rollingbackdatahere....");
try{
if(conn!=null)
conn.rollback();
}catch(SQLExceptionse2){
se2.printStackTrace();
}//endtry
}catch(Exceptione){
//HandleerrorsforClass.forName
e.printStackTrace();
}finally{
//finallyblockusedtocloseresources
try{
if(stmt!=null)
stmt.close();
}catch(SQLExceptionse2){
}//nothingwecando
try{
if(conn!=null)
conn.close();
}catch(SQLExceptionse){
se.printStackTrace();
}//endfinallytry
}//endtry
System.out.println("Goodbye!");
}//endmain
publicstaticvoidprintRs(ResultSetrs)throwsSQLException{
//Ensurewestartwithfirstrow
rs.beforeFirst();
while(rs.next()){
//Retrievebycolumnname
intid=rs.getInt("id");
intage=rs.getInt("age");
Stringfirst=rs.getString("first");
Stringlast=rs.getString("last");
//Displayvalues
System.out.print("ID:"+id);
System.out.print(",Age:"+age);
System.out.print(",First:"+first);
System.out.println(",Last:"+last);
}
System.out.println();
}//endprintRs()
}//endJDBCExample
现在让我们来编译上面的例子如下:
C:>javacJDBCExample.java
当运行JDBCExample,它会产生以下结果:
C:>javaJDBCExample
Connectingtodatabase... Creatingstatement... Insertingonerow.... Commitingdatahere.... Listresultsetforreference.... ID:100,Age:18,First:Zara,Last:Ali ID:101,Age:25,First:Mahnaz,Last:Fatma ID:102,Age:30,First:Zaid,Last:Khan ID:103,Age:28,First:Sumit,Last:Mittal ID:106,Age:20,First:Rita,Last:Tez ID:107,Age:22,First:Sita,Last:Singh Goodbye!