在JDBC中处理事务,都是通过Connection完成的。JDBC中一个Connection对象被创建时,默认是auto-commit模式,也就是一个sql Statement作为一个事务,执行完成后自动commit。如果支持多个Statement组成一个事务,则要禁止auto-commit模式,也就是非自动提交事务。
1.JDBC如何使用事务
Connection的四个方法与事务有关:
实例:使用事务插入一条记录之后抛出RuntimeException,并实现回滚。
public class TransactionDemo {
public static void main(String[] args) {
String sql = "insert into students (sname,gender) values (?,?)";
Connection conn = null;
PreparedStatement pstmt = null;
try{
conn = DBUtils.getConnection();
pstmt = conn.prepareStatement(sql);
//开启事务
conn.setAutoCommit(false);
//设置事务的隔离级别
//注意:通常不推荐修改数据库默认的事务隔离级别,这里仅仅是做个测试。
conn.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE);
pstmt.setString(1,"刘备");
pstmt.setString(2,"男");
pstmt.executeUpdate();
//这里抛出一个RuntimeException;
System.out.println(100/0);
}catch(Exception ex){
ex.printStackTrace();
try {
//回滚
conn.rollback();
}catch(SQLException e){
e.printStackTrace();
}
}finally{
try {
//提交事务
conn.commit();
conn.setAutoCommit(true);
}catch(SQLException e){
e.printStackTrace();
}
}
}
}
2.设置保存点
class Students {
private String sname;
private String gender;
public Students() {
}
public Students(String sname, String gender) {
this.sname = sname;
this.gender = gender;
}
public String getSname() {
return sname;
}
public void setSname(String sname) {
this.sname = sname;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
@Override
public String toString() {
return "Students{" +
"sname='" + sname + '\'' +
", gender='" + gender + '\'' +
'}';
}
}
public class TransactionDemo {
public static List<Students> studentsList = new ArrayList<Students>();
public static void initStudentsList() {
for (int i = 1; i <= 10; i++) {
Students s = new Students("张" + i, "男");
studentsList.add(s);
}
}
public static void main(String[] args) {
initStudentsList();
String sql = "insert into students (sname,gender) values (?,?)";
Connection conn = null;
PreparedStatement pstmt = null;
Savepoint savepoint=null;
try{
conn = DBUtils.getConnection();
pstmt = conn.prepareStatement(sql);
//开启事务
conn.setAutoCommit(false);
//设置事务的隔离级别
conn.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE);
for(Students s : studentsList) {
pstmt.setString(1, s.getSname());
pstmt.setString(2,s.getGender());
pstmt.addBatch();
}
//执行批处理
pstmt.executeBatch();
savepoint = conn.setSavepoint("保存点1");
//这里抛出一个MysqlDataTruncationException;‘未知性别’超出了gender字段的长度。
sql = "update students set gender = '未知性别' where sid = 5";
pstmt.addBatch(sql);
pstmt.executeBatch();
}catch(Exception ex){
ex.printStackTrace();
try {
//回滚到保存点
conn.rollback(savepoint);
}catch(SQLException e){
e.printStackTrace();
}
}finally{
try {
//提交事务
conn.commit();
conn.setAutoCommit(true);
}catch(SQLException e){
e.printStackTrace();
}
}
}
}
运行后,我们发现尽管在执行更新语句(update)时抛出了一个MysqlDataTruncation异常。但是并不影响前十条插入语句执行成功,说明成功回滚到了保存点位置。