要么一起成功,要么都失败。
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** 认为事务一定会出现问题,提前开启锁机制
乐观锁: 要求程序员自己控制。