- PreparedStatement还可以操作大数据类型的数据,Statement不行
- PreparedStatement可实现批量操作
User表新加一个MediumBlob数据类型,存储大型文件
- TinyBlob 255b 字节
- Blob 65kb
- MediumBlob 16mb
- LongBlob 4gb
使用我们的JDBC执行插入SQL
注意如果手动注入参数,字段的索引从1开始
输入流对象读取文件的位置
@Test public void blobTest() throws FileNotFoundException { // 插入 、删除、修改、是一样的 String sql = "insert into user(user_name,user_password,user_img) values(?,?,?);"; InputStream inputStream = new FileInputStream(new File("1.jpg")); Object[] args = new Object[]{"废品同调士","333666",inputStream}; // preparedStatement = setBlob(column,inputStream); JdbcUtil.update(sql,args); }
执行查询操作
@Test public void blobTest2() throws Exception { Connection connection = JdbcUtil.getConnection(); String sql = "Select * from user where user_id = 6"; PreparedStatement preparedStatement = connection.prepareStatement(sql); ResultSet resultSet = preparedStatement.executeQuery(); User user = new User(); InputStream binaryStream = null; // 因为只有一个记录,所以不用循环了 if (resultSet.next()){ user.setUser_id( (Integer) resultSet.getObject(1) ); user.setUser_name( (String) resultSet.getObject(2) ); user.setUser_password( (String) resultSet.getObject(3) ); Blob blob = resultSet.getBlob(5); // 返回Blob 大文件对象 binaryStream = blob.getBinaryStream(); // Blob对象返回一个二进制流对象 System.out.println(user); } OutputStream outputStream = new FileOutputStream("2.jpg"); //创建输出流对象 byte[] bytesBuffer = new byte[1024]; // 缓冲数组 int len; while ( (len = binaryStream.read(bytesBuffer)) != -1 ){ outputStream.write(bytesBuffer,0,len); // 输出写入 } resultSet.close(); JdbcUtil.closeResource(connection,preparedStatement); }
图片也读取出来了
如果是插入超过2M大小的图片可能报异常错误了
但是我测试的添加和查询的结果没有报错,演示不了错误异常
我这里直接Eclipse的报错异常好了
文件过大异常
处理方法也很简单:
修改最大可存储字节 max_allowed_packet=16M
8.0貌似默认4M,但是我6M的图片上传读取都没问题。。。
保存修改之后重启MySQL的服务
再执行一遍就可以了
PreparedStatement实现批量操作
- 批量插入
@Test public void blobTest3() throws FileNotFoundException, SQLException { // 批量插入 String sql = "insert into user(user_name,user_password) values(?,?);"; // 预编译SQL对象执行后保留有SQL缓存,多次注入只需要参数即可, Connection connection = JdbcUtil.getConnection(); PreparedStatement preparedStatement = connection.prepareStatement(sql); for (int i = 0; i < 100 ; i++) { preparedStatement.setObject(1,"演示批量操作"+i); preparedStatement.setObject(2,"123"+i); preparedStatement.execute(); } JdbcUtil.closeResource(connection,preparedStatement); }
- 批量操作2
@Test public void blobTest3() throws SQLException { String sql = "insert into user(user_name,user_password) values(?,?)"; //批量操作不要在SQL语句加冒号结束 Connection connection = JdbcUtil.getConnection(); PreparedStatement preparedStatement = connection.prepareStatement(sql); for (int i = 0; i < 100 ; i++) { // addBatch(),executeBatch(),clearBatch(); preparedStatement.setObject(1,"演示批量操作"+i); preparedStatement.setObject(2,"123"+i); preparedStatement.addBatch();// 累积SQL if ((i % 50 == 0 && i!= 0) || i == 99) { preparedStatement.executeBatch(); // 到50个执行或者最后一个 preparedStatement.clearBatch(); // 清空Batch } } JdbcUtil.closeResource(connection,preparedStatement); }
在jdbc.properties 开启批处理操作支持,我试了不加这个开启也能使用
# 驱动 driverClass = com.mysql.cj.jdbc.Driver # 连接 url = jdbc:mysql://localhost:3306/jdbc_db?serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true # 用户 user = root # 密码 password = 123456 # 开启批处理支持 rewriteBatchedStatements=true # 5.1.7驱动依赖不支持批处理,降低版本或者提升版本? # truncate table user;清空数据表
批量操作方式3 关闭自动提交,等全都执行成功了再提交,多次提交影响SQL的性能,这个操作还能在提高一些
@Test public void blobTest3() throws SQLException { String sql = "insert into user(user_name,user_password) values(?,?)"; //批量操作不要在SQL语句加冒号结束 Connection connection = JdbcUtil.getConnection(); connection.setAutoCommit(false); // 关闭事务的自动提交 PreparedStatement preparedStatement = connection.prepareStatement(sql); for (int i = 0; i < 100 ; i++) { // addBatch(),executeBatch(),clearBatch(); preparedStatement.setObject(1,"演示批量操作"+i); preparedStatement.setObject(2,"123"+i); preparedStatement.addBatch();// 累积SQL if ((i % 50 == 0 && i!= 0) || i == 99) { preparedStatement.executeBatch(); // 到50个执行或者最后一个 preparedStatement.clearBatch(); // 清空Batch } } connection.commit(); // 执行提交 JdbcUtil.closeResource(connection,preparedStatement); }