开启事务的关键代码是conn.setAutoCommit(false),表示关闭自动提交。提交事务的代码在执行完指定的若干条SQL语句后,调用conn.commit()。要注意事务不是总能成功,如果事务提交失败,会抛出SQL异常(也可能在执行SQL语句的时候就抛出了),此时我们必须捕获并调用conn.rollback()回滚事务。最后,在finally中通过conn.setAutoCommit(true)把Connection对象的状态恢复到初始值。
实际上,默认情况下,我们获取到Connection连接后,总是处于“自动提交”模式,也就是每执行一条SQL都是作为事务自动执行的,这也是为什么前面几节我们的更新操作总能成功的原因:因为默认有这种“隐式事务”。只要关闭了Connection的autoCommit,那么就可以在一个事务中执行多条语句,事务以commit()方法结束。
JDBC事务使用案例:
/**
* 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);
}
}
}
多条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);
}