JDBC事务
事务(Transaction) :数据库中保证交易可靠的机制。
计算机中使用到原子,基本是指某项不能在分或打开的。即不可再分的。例如:交易操作,即借钱中,一个账户的扣除和另一个账户的增加必须同时进行,这中间操作不可再分了。
隔离性演示:
如数据库未执行完,并未进行commit,那么对于同一影响的数据就不能够被操作,会在执行过程中类似于卡住,这是因为数据进行了加锁。(oracle数据库)
事务API
conn.setAutoCommit(false);//开启事务 conn.commit();//提交事务 conn.rollback();//回滚事务
交易测试案例
public class test { public static void main(String[] args) { pay("bob","cindy",100); pay("alice","bob",-100); } public static void pay(String from ,String to,double money ){ String sql1="update k set balance=balance+ ? where name=? "; String sql2="select balance from k where name= ? "; Connection conn=null; try{ conn=DBUtils.getConnection(); conn.setAutoCommit(false); PreparedStatement ps=conn.prepareStatement(sql1); ps.setDouble(1,-money); ps.setString(2,from); int n=ps.executeUpdate(); if (n!=1){ throw new Exception("error"); } //加余额 ps.setDouble(1,money); ps.setString(2,to); n=ps.executeUpdate(); if (n!=1){ throw new Exception("ok"); } ps.close(); //检查 ps=conn.prepareStatement(sql2); ps.setString(1,from); ResultSet resultSet=ps.executeQuery(); while (resultSet.next()){ double balance=resultSet.getDouble(1); if (balance<0){ throw new Exception("nonono"); } } conn.commit(); }catch (Exception e){ e.printStackTrace(); try { conn.rollback(); } catch (SQLException ex) { ex.printStackTrace(); } }finally { DBUtils.close(conn); } } }
JDBC批量处理
一个批处理是被发送到数据库以作为单个单元执行的一组更新语句。
批处理API
executeBatch()
int[] executeBatch() throws SQLException;
数组值可能是以下之一:
- 大于或等于零的数字,表示命令已成功处理,并且是更新计数,给出了数据库中受命令影响的行数执行
- SUCCESS_NO_INFO ( -2)的值,表示命令为处理成功,但受影响的行数为未知
- 如果批量更新中的命令之一无法正确执行,此方法引发BatchUpdateException,JDBC driver可能会也可能不会继续处理剩余的命令。但是driver的行为是与特定的DBMS绑定的,要么总是继续处理命令,要么从不继续处理命令。如果驱动程序继续处理,方法将返回 EXECUTE_FAILED(-3)。
批量执行SQL语句
public class ddl { public static void main(String[] args){ String sql1="create table log_1 (id int(8),msg varchar(100))"; String sql2="create table log_2 (id int(8),msg varchar(100))"; Connection conn=null; try { conn= DBUtils.getConnection(); Statement st=conn.createStatement(); st.addBatch(sql1); st.addBatch(sql2); //执行一批SQL语句 int [] ary=st.executeBatch(); System.out.println(Arrays.toString(ary)); System.out.println("ok"); }catch (Exception e){ e.printStackTrace(); }finally { DBUtils.close(conn); } } }
批量参数处理
import test.DBUtils; import java.sql.Connection; import java.sql.PreparedStatement; import java.util.Arrays; public class test { public static void main(String[] args){ String sql="insert into k (name,age,balance) values(?,?,?)"; Connection conn=null; try { conn= DBUtils.getConnection(); PreparedStatement ps=conn.prepareStatement(sql); for (int i=0;i<5;i++){ //替换参数 ps.setString(1,"doc"); ps.setInt(2,25+i); ps.setInt(3,800); //将参数添加到ps缓存区 ps.addBatch(); } //批量执行 int [] ary=ps.executeBatch(); System.out.println(Arrays.toString(ary)); }catch (Exception e){ e.printStackTrace(); }finally { DBUtils.close(conn); } } }
防止OutOfMemory错误
如果Preparedstatement 对象中的SQL列表包含过多的待处理SQL语句可能会产生OutOfMemory错误。
可以采取分批次执行,可以避免内存溢出问题
if ((i+1)%4==0){ ps.executeBatch(); ps.clearBatch(); } }