要么一起成功,要么都失败。
package com.ibeidiao.utils;
import org.junit.Test;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class Transaction {
@Test
public void transaction() throws SQLException {
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
try {
conn = JDBCUtils.getConn();
conn.setAutoCommit(false); // 关闭事务自动提交
String sql = "update account set money=money-? where id = ?";
ps = conn.prepareStatement(sql);
ps.setInt(1, 100); //第一个参数
ps.setInt(2, 1); //第二个参数
ps.executeUpdate();
int a = 10/0;
// rs = ps.executeQuery();
ps.setInt(1, -100); //第一个参数
ps.setInt(2, 2); //第二个参数
ps.executeUpdate();
conn.commit();
}catch (SQLException e){
conn.rollback();
e.printStackTrace();
}finally {
JDBCUtils.release(conn, ps,rs);
}
}
}
事务的安全隐患:
- 如果不设置隔离级别,会引发脏读:
脏读:一个事务读到了另一个事务还未提交到的数据 - 如果设置了隔离级别,可以屏蔽掉脏读,但是会造成数据库的不可重复读,两次查询的结果不一样。(默认就是可重复读).但是这样还是查不到数据库真实的数据。
设置最高级别的隔离,就可以把所有的问题全部屏蔽掉:Serializable(可串行化)
悲观锁:可以再查询的时候自己设置。
select * from account **for update** 认为事务一定会出现问题,提前开启锁机制
乐观锁: 要求程序员自己控制。