Java JDBC事务处理:手动提交与回滚实战
JDBC连接默认处于自动提交模式,每个SQL语句执行后即写入数据库。为提升性能或确保业务流程的原子性,开发者通常需手动控制事务。本文阐述如何关闭自动提交,并通过Commit和Rollback机制处理成功提交与异常回滚的场景。
为何需要手动事务管理
在默认的自动提交模式下,任何一条SQL语句一旦完成便会立即生效。虽然这对简单应用足够,但在以下场景中必须关闭自动提交:
- 提高性能:批量操作时减少与数据库的网络交互次数。
- 保持业务完整性:将一组相关的SQL语句(如转账、订单创建)绑定为一个逻辑单元,要么全部成功,要么全部失败。
- 分布式事务需求:涉及多个资源库的数据一致性保障。
核心操作步骤
第1步:关闭自动提交模式
要实现手动事务控制,首先需要将数据库连接设置为非自动提交状态。使用 setAutoCommit(boolean) 方法,传入 false 即可关闭自动提交。
conn.setAutoCommit(false);
此时,后续的SQL执行结果将暂存在内存中,不会真正写入数据库。
第2步:执行业务SQL并尝试提交
在同一个 try 块中执行一系列必要的SQL操作。如果所有步骤均无异常,调用 commit() 方法将挂起的更改永久应用到数据库。
// ... 执行 SQL ... conn.commit();
第3步:异常捕获与回滚处理
若在执行过程中抛出 SQLException,说明某条语句失败或发生其他错误。此时应进入 catch 块,并调用 rollback() 取消当前事务内所有的更改,使数据库恢复到事务开始前的状态。
}catch(SQLException se){
conn.rollback();
}
完整的事务控制代码实现
以下代码展示了一个完整的 JDBCExample.java 流程。它涵盖了从驱动加载、获取连接、设置事务属性、执行INSERT操作到最终清理资源的整个过程。
关键逻辑说明:
- 环境准备:使用
DriverManager.getConnection获取连接,并立即调用conn.setAutoCommit(false)锁定事务控制权。 - 数据插入:连续插入两条员工记录(ID 106 和 107)。
- 验证输出:通过
printRs辅助方法查询当前表内容,观察数据是否已刷新。 - 异常安全:
finally块负责关闭 ResultSet、Statement 和 Connection;catch (SQLException)块负责触发conn.rollback()。
import java.sql.*;
public class JDBCExample {
// JDBC driver name and database URL
static final String JDBC_DRIVER = "com.mysql.jdbc.Driver";
static final String DB_URL = "jdbc:mysql://localhost/EMP";
// Database credentials
static final String USER = "username";
static final String PASS = "password";
public static void main(String[] args) {
Connection conn = null;
Statement stmt = null;
try{
//STEP 2: Register JDBC driver
Class.forName("com.mysql.jdbc.Driver");
//STEP 3: Open a connection
System.out.println("Connecting to database...");
conn = DriverManager.getConnection(DB_URL,USER,PASS);
//STEP 4: Set auto commit as false.
conn.setAutoCommit(false);
//STEP 5: Execute a query to create statment with
// required arguments for RS example.
System.out.println("Creating statement...");
stmt = conn.createStatement(
ResultSet.TYPE_SCROLL_INSENSITIVE,
ResultSet.CONCUR_UPDATABLE);
//STEP 6: INSERT a row into Employees table
System.out.println("Inserting one row....");
String SQL = "INSERT INTO Employees " +
"VALUES (106, 20, 'Rita', 'Tez')";
stmt.executeUpdate(SQL);
//STEP 7: INSERT one more row into Employees table
SQL = "INSERT INTO Employees " +
"VALUES (107, 22, 'Sita', 'Singh')";
stmt.executeUpdate(SQL);
//STEP 8: Commit data here.
System.out.println("Commiting data here....");
conn.commit();
//STEP 9: Now list all the available records.
String sql = "SELECT id, first, last, age FROM Employees";
ResultSet rs = stmt.executeQuery(sql);
System.out.println("List result set for reference....");
printRs(rs);
//STEP 10: Clean-up environment
rs.close();
stmt.close();
conn.close();
}catch(SQLException se){
//Handle errors for JDBC
se.printStackTrace();
// If there is an error then rollback the changes.
System.out.println("Rolling back data here....");
try{
if(conn!=null)
conn.rollback();
}catch(SQLException se2){
se2.printStackTrace();
}//end try
}catch(Exception e){
//Handle errors for Class.forName
e.printStackTrace();
}finally{
//finally block used to close resources
try{
if(stmt!=null)
stmt.close();
}catch(SQLException se2){
}
try{
if(conn!=null)
conn.close();
}catch(SQLException se){
se.printStackTrace();
}
}
System.out.println("Goodbye!");
}//end main
public static void printRs(ResultSet rs) throws SQLException{
//Ensure we start with first row
rs.beforeFirst();
while(rs.next()){
//Retrieve by column name
int id = rs.getInt("id");
int age = rs.getInt("age");
String first = rs.getString("first");
String last = rs.getString("last");
//Display values
System.out.print("ID: " + id);
System.out.print(", Age: " + age);
System.out.print(", First: " + first);
System.out.println(", Last: " + last);
}
System.out.println();
}
}
编译与运行
在命令行中使用 javac 编译源文件,然后运行 Java 类:
javac JDBCExample.java java JDBCExample
程序正常运行后的典型输出如下(显示新插入的记录已成功持久化):
Connecting to database... Creating statement... Inserting one row.... Commiting data here.... List result set for reference.... 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!
上述输出表明两行新数据(106号和107号)被正确提交。如果在 STEP 7 故意制造语法错误(例如将 INSERT 拼写为 INSERTED),控制台将打印 “Rolling back data here....”,且数据库中不会出现这两行数据,从而保证了数据的一致性。
总结
JDBC中的事务管理主要依靠 setAutoCommit(false) 开启人工控制,随后配合 commit() 确认变更或 rollback() 撤销变更。这种方式特别适用于金融转账、多表关联更新等对数据准确性要求极高的场景。
以上就是Java JDBC事务提交的详细内容,更多关于Java数据库编程的资料请关注本站其它相关文章!
本站声明
本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。













