在MySQL中事务是将多个dml语句当作一个整体进行处理
-- 开始事务
START TRANSACTION
-- 设置保存点1
SAVEPOINT a
-- 执行dml操作
INSERT INTO test1 VALUES(1,'tom')
-- 设置保存点2
SAVEPOINT b
INSERT INTO test1 VALUES(2,'smith')
-- 回滚事务
ROLLBACK TO b
ROLLBACK TO a
commit -- 提交事务所有的操作生效,不能回退
注意细节
1.如果不开始事务,他会自动提交
2.如果没有创建保存点,rollback会回退到事务开始的状态
JDBC中当一个Connection对象创建时,默认情况下是自动提交事务,每次执行一个sql语句,如果执行成功,就会向数据库自动提交,而不能回滚
1.调用setAutoCommit(false)可以取消自动提交事务
2.所有sql语句执行完后,调用commit()方法进行提交
3.在其中某个操作失败时,调用rollback()进行回滚
try {
connection = JDBCUtils.getConnection(); // 在默认情况下,connection是默认自动提交
//将 connection 设置为不自动提交
connection.setAutoCommit(false); //开启了事务
preparedStatement = connection.prepareStatement(sql);
preparedStatement.executeUpdate(); // 执行第1条sql
int i = 1 / 0; //假如这里出现异常会走到catch中去
preparedStatement = connection.prepareStatement(sql2);
preparedStatement.executeUpdate(); // 执行第3条sql
//这里提交事务
connection.commit();
} catch (Exception e) {
//这里我们可以进行回滚,即撤销执行的SQL
//默认回滚到事务开始的状态.
System.out.println("执行发生了异常,撤销执行的sql");
try {
connection.rollback();
} catch (SQLException throwables) {
throwables.printStackTrace();
}
e.printStackTrace();
}
当需要成批插入或更新记录时,可以使用Java的批处理更新机制,通常情况下比单独处理更有效率
1.addBatch()添加需要处理的sql语句或者参数
2.executeBatch():执行语句
3.clearBatch()清空批处理语句
4.在url中加入参数
rewriteBatchedStatements = true
public void batch() throws Exception {
Connection connection = JDBCUtils.getConnection();
String sql = "insert into admin2 values(null, ?, ?)";
PreparedStatement preparedStatement = connection.prepareStatement(sql);
System.out.println("开始执行");
long start = System.currentTimeMillis();//开始时间
for (int i = 0; i < 5000; i++) {//5000执行
preparedStatement.setString(1, "jack" + i);
preparedStatement.setString(2, "111");
preparedStatement.addBatch();
//当有1000条记录时,在批量执行
if((i + 1) % 1000 == 0) {//满1000条sql
preparedStatement.executeBatch();
//清空一把
preparedStatement.clearBatch();
}
}
long end = System.currentTimeMillis();
System.out.println("批量方式 耗时=" + (end - start));//批量方式 耗时=108
//关闭连接
JDBCUtils.close(null, preparedStatement, connection);
}
public void noBatch() throws Exception {
Connection connection = JDBCUtils.getConnection();
String sql = "insert into admin2 values(null, ?, ?)";
PreparedStatement preparedStatement = connection.prepareStatement(sql);
System.out.println("开始执行");
long start = System.currentTimeMillis();//开始时间
for (int i = 0; i < 5000; i++) {//5000执行
preparedStatement.setString(1, "jack" + i);
preparedStatement.setString(2, "666");
preparedStatement.executeUpdate();
}
long end = System.currentTimeMillis();
System.out.println("传统的方式 耗时=" + (end - start));//传统的方式 耗时=10702
//关闭连接
JDBCUtils.close(null, preparedStatement, connection);
}
模拟了传统方法和预处理之间的时间消耗差异
1. 创建 ArrayList - elementData => Object[]
2. elementData => Object[] 就会存放我们预处理的sql语句
3. 当elementData满后,就按照1.5扩容
4. 当添加到指定的值后,就executeBatch
5. 批量处理会减少我们发送sql语句的网络开销,而且减少编译次数,因此效率提高
public void addBatch() throws SQLException {
synchronized(this.checkClosed().getConnectionMutex()) {
if (this.batchedArgs == null) {
this.batchedArgs = new ArrayList();
}
for(int i = 0; i < this.parameterValues.length; ++i) {
this.checkAllParametersSet(this.parameterValues[i], this.parameterStreams[i], i);
}
this.batchedArgs.add(new PreparedStatement.BatchParams(this.parameterValues, this.parameterStreams, this.isStream, this.streamLengths, this.isNull));
}
}