1 如果多个操作,写个操作使用的是自己的单独的连接,则无法保证事物。事物要求多个操作一起执行,一起回滚。
2 具体操作:
1)事物操作开始前,开始事物,取消Connection的默认提交行为。
2)如果事物的操作都成功,则提交事务
3)若出现异常,则在catch中回滚事务
3 四种事物隔离级别:
1)READ UNCOMMITTED:读其他事务未提交的数据,会出现脏读、不可重复读和幻读的问题。
2) READ COMMITED:只允许事物读其他事务已提交的数据(Orable默认),但有不可重复读和幻读的问题。
3) REPEATABLE READ:可重复读(Mysql默认):确保事物可以多次从一个字段中读取相同的值,在这个事物的持续访问期间,禁止其他事务对这个字段进行更新。但会有幻读的问题。
4) SERIALIZABLE:串行化。确保食物可以从一个表中读取相同的行,执行期间禁止其他事务进行插入、更新和删除操作。所有并发问题都可避免。
public class JdbcTools { //处理数据库的事物 public static void commit(Connection conn){ try { conn.commit(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public static void rollback(Connection conn){ try { conn.rollback(); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public static void beginTx(Connection conn){ try { conn.setAutoCommit(false); } catch (SQLException e) { // TODO Auto-generated catch block e.printStackTrace(); } }
package lianxi1; import java.sql.Connection; import java.sql.PreparedStatement; import java.util.Random; import org.junit.Test; //计算向数据库中添加10000条数据的时间 public class TestBatch { @Test public void test1(){ Connection conn = null; PreparedStatement ps = null; try { conn = JdbcTools.getConnection(); //System.out.print(conn); JdbcTools.beginTx(conn); String sql = "INSERT INTO STORE(SID,SNAME,SPRICE) VALUES(?,?,?)"; ps = conn.prepareStatement(sql); long begin = System.currentTimeMillis(); for(int i=0;i<10000;i++){ ps.setInt(1,i+1); ps.setString(2,"item_"+i); ps.setInt(3, new Random().nextInt(1000)); ps.addBatch(); if((i+1)%300==0){ ps.executeBatch(); ps.clearBatch(); } } if((10000%300)!=0){ ps.executeBatch(); ps.clearBatch(); } long end = System.currentTimeMillis(); System.out.println("time="+(end-begin)); JdbcTools.commit(conn); } catch (Exception e) { JdbcTools.rollback(conn); e.printStackTrace(); } finally{ JdbcTools.release(null, ps, conn); } } }