详解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!