JDBC批处理
什么是批处理
- 一次性执行多条Sql语句,允许多条语句一次性提交给数据库批量处理
- 比单独提交处理要效率高
批处理方法
addBatch(String)
添加需要批处理的sql语句
executeBatch()
执批处理
支持情况
- mysql默认情况下是不支持批处理的
- 从5.1.13开始,添加了一个
rewriteBatchedStatements
参数
之前插入10条数据要17.4秒
从5.1.13开始提高到了1.6秒
package com.iris.jdbc.test;
import java.sql.Connection;
import java.sql.PreparedStatement;
import com.iris.jdbc.util.JDBCUtil;
public class BatchTest {
public static void main(String[] args) throws Exception {
Connection conn = JDBCUtil.getConn();
String sql = "insert into student (name,age) values (?,?)";
PreparedStatement ps = conn.prepareStatement(sql);
long begin = System.currentTimeMillis();
for (int i=0;i < 100; i++) {
ps.setString(1, "zs");
ps.setInt(2, 10);
//添加批处理
ps.addBatch();
}
//执行批处理
ps.executeBatch();
long end = System.currentTimeMillis();
long time = end -begin;
System.out.println(time);
JDBCUtil.close(conn, ps, null);
}
}
什么都不添加执行100此循环的时间
添加 addBatch(String)
和 executeBatch()
执批处理 执行100此循环的时间
添加 rewriteBatchedStatements=True
参数后执行100次循环的时间
JDBC事务问题
建立一张个人账户表
zs 和 ls 进行转账
- 检查zs账户余额
- 减少zs账户1000
- 增加ls账户1000
package com.iris.jdbc.test;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import com.iris.jdbc.util.JDBCUtil;
public class TransactionTest {
public static void main(String[] args) throws SQLException {
//1. 检查zs账户余额
//2. 减少zs账户1000
//3. 增加ls账户1000
Connection conn = JDBCUtil.getConn();
String sql = "select * from account where name = ? and money >?";
//创建语句
PreparedStatement ps = conn.prepareStatement(sql);
ps.setString(1, "zs");
ps.setInt(2, 1000);
ResultSet res = ps.executeQuery();
if(!res.next()) {
throw new RuntimeException("没钱了");
}
//2. 减少zs账户1000
sql = "update account set money = money - ? where name = ?";
ps = conn.prepareStatement(sql);
ps.setDouble(1, 1000);
ps.setString(2, "zs");
ps.executeUpdate();
//3. 增加ls账户1000
sql = "update account set money = money + ? where name = ?";
ps = conn.prepareStatement(sql);
ps.setDouble(1, 1000);
ps.setString(2, "ls");
ps.executeUpdate();
JDBCUtil.close(conn, ps, res);
System.out.println("完成");
}
}
多次转账之后报异常
出现异常情况
在第2步和第3步之间弄一个异常 int a = 1 / 0;
一个人的账户减少,另一个没有加
处理事务
默认情况下, 事务是自动提交的
要设置为手动提交
处理事务过程
关闭自动提交conn.setAutoCommit(false);
没有问题时,提交事务 conn.commit();
出现异常时,进行回滚操作conn.rollback()
回滚之后,事务结束。释放资源
出现异常,没有提交,也不会更新数据库,但是会占用资源
所以要出现异常时,进行回滚操作
只有增、册、改才需要事务,查询不需要事务
以后发现自己写的代码是正确的,测试也成功,但是数据库当中的数据不变(事务没有提交)
InnoDB
才支持外键和事务。MyISAM
不支持外键和事务
设置事务的隔离级别
conn.setTransactionIsolation(Connection.TRANSACTION_REPATABLE_READ)
package com.iris.jdbc.test;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import com.iris.jdbc.util.JDBCUtil;
public class TransactionTest {
public static void main(String[] args) throws SQLException {
//1. 检查zs账户余额
//2. 减少zs账户1000
//3. 增加ls账户1000
Connection conn = JDBCUtil.getConn();
String sql = "select * from account where name = ? and money >?";
//创建语句
PreparedStatement ps = conn.prepareStatement(sql);
ps.setString(1, "zs");
ps.setInt(2, 1000);
ResultSet res = ps.executeQuery();
if(!res.next()) {
throw new RuntimeException("没钱了");
}
try {
// 开启事务
conn.setAutoCommit(false);
//2. 减少zs账户1000
sql = "update account set money = money - ? where name = ?";
ps = conn.prepareStatement(sql);
ps.setDouble(1, 1000);
ps.setString(2, "zs");
ps.executeUpdate();
//3. 增加ls账户1000
sql = "update account set money = money + ? where name = ?";
ps = conn.prepareStatement(sql);
ps.setDouble(1, 1000);
ps.setString(2, "ls");
ps.executeUpdate();
//提交事务
conn.commit();
}catch(Exception e) {
e.printStackTrace();
conn.rollback();
}finally {
JDBCUtil.close(conn, ps, res);
}
System.out.println("完成");
}
}