1.JDBC事务概述
开启事务的关键代码是conn.setAutoCommit(false),表示关闭自动提交。提交事务的代码在执行完指定的若干条SQL语句后,调用conn.commit()。要注意事务不是总能成功,如果事务提交失败,会抛出SQL异常(也可能在执行SQL语句的时候就抛出了),此时我们必须捕获并调用conn.rollback()回滚事务。最后,在finally中通过conn.setAutoCommit(true)把Connection对象的状态恢复到初始值。
实际上,默认情况下,我们获取到Connection连接后,总是处于“自动提交”模式,也就是每执行一条SQL都是作为事务自动执行的,这也是为什么前面几节我们的更新操作总能成功的原因:因为默认有这种“隐式事务”。只要关闭了Connection的autoCommit,那么就可以在一个事务中执行多条语句,事务以commit()方法结束。
2.JDBC事务的使用方案
JDBC事务使用案例:
import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; /** * JDBC事务演示 */ public class JdbcAffairs { public static void main(String[] args) { Connection connection = null; PreparedStatement preparedStatement = null; String sql = "update user set school = '东南大学' where id = 1"; String sql2 = "update user set school = '河海大学' where id = 2"; try { connection = JdbcUtils.getConnection(); // 将connection设置为不自动提交事务 connection.setAutoCommit(false); preparedStatement = connection.prepareStatement(sql); preparedStatement.executeUpdate(); PreparedStatement preparedStatement1 = connection.prepareStatement(sql2); preparedStatement1.executeUpdate(); // 提交事务 connection.commit(); } catch (SQLException e) { // 进行回滚 try { // 默认回滚到事务开始的状态 connection.rollback(); } catch (SQLException ex) { throw new RuntimeException(ex); } throw new RuntimeException(e); } finally { // 关闭连接 JdbcUtils.close(null, preparedStatement, connection); } } }
3.批处理
多条sql语句统一提交数据库执行,这会使效率更高🤞
普通方式使用for循环批量添加数据(效率低❌):
Connection connection = JdbcUtils.getConnection(); String sql = "insert into user values (?,?,?,?)"; PreparedStatement preparedStatement = connection.prepareStatement(sql); for (int i = 0; i < 50; i++) { preparedStatement.setInt(1, i + 7); preparedStatement.setString(2, "qy" + i); preparedStatement.setString(3, "adminadmin" + i); preparedStatement.setString(4, "中国大学" + i); preparedStatement.executeUpdate(); } JdbcUtils.close(null, preparedStatement, connection);
使用JDBC批处理机制添加数据(效率高√ 【减少发送sql语句的网络开销,减少编译次数】):
注意:使用JDBC批处理时,连接数据库的url请务必加入此参数:
rewriteBatchedStatements=true
可以使用executeBatch,执行当前批量更新缓存中的所有命令。返回一个记录数的数组,其中每一个元素都对应一条语句,如果其值非负,则表示受该语句影响的记录总数;如果其值为SUCCESS_NO_INFO,则表示该语句成功执行了,但没有记录数可用;如果其值为EXECUTE_FAILED,则表示该语句执行失败了
示例代码:
/** * JDBC批处理演示 * @throws Exception */ @Test public void batchProcessingMethod() throws Exception { Connection connection = JdbcUtils.getConnection(); String sql = "insert into user values (?,?,?,?)"; PreparedStatement preparedStatement = connection.prepareStatement(sql); for (int i = 0; i < 50; i++) { preparedStatement.setInt(1, i + 107); preparedStatement.setString(2, "qyee" + i); preparedStatement.setString(3, "ppp" + i); preparedStatement.setString(4, "北京大学" + i); // 将sql语句加入到批处理中 preparedStatement.addBatch(); // 当存在10条数据时,批量处理执行 if ((i + 1) % 10 == 0) { preparedStatement.executeBatch(); // 清空数据继续待添加 preparedStatement.clearBatch(); } } JdbcUtils.close(null, preparedStatement, connection); }