当前位置: 首页> 教育> 大学 > JDBC和Mybatis中的批处理

JDBC和Mybatis中的批处理

时间:2025/7/10 21:43:24来源:https://blog.csdn.net/tiantiantbtb/article/details/141690134 浏览次数:0次

src目录下创建jdbc.properties mysql驱动5.1.6之后,只需要配置url,username,password

mysql 5.1.6之后可以无需Class.forName("com.mysql.jdbc.Driver")
* 从jdk1.5之后可以通过配置文件来配置
* 会自动加载mysql驱动jar包下META-INF/services/java.sql.Driver文本中的类名去注册

JDBC工具类

package com.example;import java.io.FileInputStream;
import java.io.IOException;
import java.sql.*;
import java.util.Properties;/*** JDBC工具类* @author hrui* @date 2024/8/29 16:45*/
public class JDBCUtils {private static String url;private static String username;private static String password;private static Properties properties=new Properties();static{try {properties.load(new FileInputStream("src\\jdbc.properties"));url = properties.getProperty("url");username = properties.getProperty("username");password = properties.getProperty("password");}catch (IOException e){e.printStackTrace();//throw new RuntimeException(e);}}public static Connection getConnection() throws SQLException {//如果这样写,虽然不需要定义url,username,password,但是每次都要从properties获取url,username,password,效率不高 所以还是定义url,username,password 静态块里赋值//return DriverManager.getConnection(properties.getProperty("url"), properties.getProperty("username"), properties.getProperty("password"));return DriverManager.getConnection(url, username, password);}public static void closed(ResultSet rs, Statement stmt, Connection conn){try {if(rs!=null){rs.close();}if(stmt!=null){stmt.close();}if(conn!=null){conn.close();}}catch (SQLException e){e.printStackTrace();}}
}

 以下执行代码数据一多,执行非常慢

package com.example;import java.sql.Connection;
import java.sql.PreparedStatement;/*** @author hrui* @date 2024/8/29 17:51*/
public class BathDemo {/*** 批处理* JDBC的批处理语句包括下面方法:* addBatch():添加需要批量处理的sql语句或参数* executeBatch():执行批处理语句* clearBatch():清空批处理语句* JDBC连接MySQL时,如果要使用批处理功能,再url中加参数?rewriteBatchedStatements=true* 批处理往往和PreparedStatement一起搭配使用,可以减少编译次数,效率提高* @param args*/public static void main(String[] args) {Connection conn = null;PreparedStatement ps = null;long start = System.currentTimeMillis();System.out.println("开始批处理:"+start);try {conn = JDBCUtils.getConnection();//conn.setAutoCommit(false);String sql="insert into admin2 values(null,?,?)";ps = conn.prepareStatement(sql);for (int i = 0; i < 100000; i++) {ps.setObject(1,"hrui"+i);ps.setObject(2,"123456");ps.executeUpdate();}// conn.commit();long end = System.currentTimeMillis();System.out.println("结束批处理:"+end);}catch (Exception e){e.printStackTrace();
//            if(conn!=null){
//                try {
//                    conn.rollback();
//                } catch (Exception e1) {
//                    e1.printStackTrace();
//                }
//            }}finally {JDBCUtils.closed(null,ps,conn);}}
}

以下代码注意在url后面加

?rewriteBatchedStatements=true

JDBC中正确的批处理

package com.example;import java.sql.Connection;
import java.sql.PreparedStatement;/*** @author hrui* @date 2024/8/29 18:59*/
public class BathDemo2 {//正确的批处理方式public static void main(String[] args) {Connection conn = null;PreparedStatement ps = null;long start = System.currentTimeMillis();System.out.println("开始批处理:"+start);try {conn = JDBCUtils.getConnection();conn.setAutoCommit(false);String sql="insert into admin3 values(null,?,?)";ps = conn.prepareStatement(sql);//这里执行完  sql已经发送到DBMS进行编译for (int i = 0; i < 1000000; i++) {ps.setObject(1,"hrui"+i);ps.setObject(2,"123456");ps.addBatch();//循环一次 添加到批处理 添加的是参数if((i+1)%2000==0){ps.executeBatch();//满1000条执行一次ps.clearBatch();//执行完清空}}conn.commit();long end = System.currentTimeMillis();System.out.println("结束批处理:"+end);//所用时间秒  一般5000条这样数据大概耗时10秒System.out.println("所用时间:"+(end-start));}catch (Exception e){e.printStackTrace();
//            if(conn!=null){
//                try {
//                    conn.rollback();
//                } catch (Exception e1) {
//                    e1.printStackTrace();
//                }
//            }}finally {JDBCUtils.closed(null,ps,conn);}}
}

DataSource是扩展版就是企业用的,我们现在所有的连接都是从DataSource里拿的  那么像HikariCP,druid,C3P0等数据库连接池都是实现DataSource的  默认我们在使用SpringBoot时候 使用的是HikariCP数据库连接池,也就是说DataSource其实就是数据库连接池的接口,在使用SpringBoot的时候,如果非不想使用默认或者druid,就是不想使用连接池,那么必须要指定一个DataSource的实现类,否则无法连接,Spring提供了一个DriverManagerDataSource,另外一种方式是你自己实现DataSource  然后指定type为自定义的.获取连接之后  还是通过Statement或者PreparedStatement去执行sql

下次是使用连接池的,可以有多个数据库连接去执行SQL操作 因为内存中循环肯定很快

insert into admin(name,pwd) values(xxx,xxx),(xxx,xxx),(xxx,xxx),(xxx,xxx),(xxx,xxx),(xxx,xxx),(xxx,xxx),(xxx,xxx),(xxx,xxx),(xxx,xxx),(xxx,xxx),(xxx,xxx),(xxx,xxx),(xxx,xxx),(xxx,xxx),(xxx,xxx),(xxx,xxx),(xxx,xxx),(xxx,xxx),(xxx,xxx),(xxx,xxx),(xxx,xxx),(xxx,xxx),(xxx,xxx),(xxx,xxx),(xxx,xxx),(xxx,xxx),(xxx,xxx),(xxx,xxx),

那么如果批量操作的不是1000的整数倍呢

配置DriverManagerDataSource

那么再执行下面代码就是一个每次一个连接 insert into admin(name,pwd) values(xxx,xxx),(xxx,xxx),(xxx,xxx),(xxx,xxx),(xxx,xxx),(xxx,xxx),(xxx,xxx),(xxx,xxx),(xxx,xxx),(xxx,xxx),(xxx,xxx),(xxx,xxx),(xxx,xxx),(xxx,xxx),(xxx,xxx),(xxx,xxx),(xxx,xxx),(xxx,xxx),(xxx,xxx),(xxx,xxx),(xxx,xxx),(xxx,xxx),(xxx,xxx),(xxx,xxx),(xxx,xxx),(xxx,xxx),(xxx,xxx),(xxx,xxx),(xxx,xxx)  执行完关闭conn,

然后再打开 再执行 每次都只有一个连接在处理

速度会慢很多

另外 mybatis的这种执行方式 对于?rewriteBatchedStatements=true好像并没有多大作用,不过有应该是好的

<foreach>标签的影响

  • 不需要设置rewriteBatchedStatements=true:因为你使用的是MyBatis的<foreach>标签,这种方式本质上已经生成了一条带有多个值对的SQL语句,类似INSERT INTO admin (name, pwd) VALUES ('name1', 'pwd1'), ('name2', 'pwd2'), ...,这与rewriteBatchedStatements=true的效果类似。
  • 因此,在这种情况下,加上rewriteBatchedStatements=true对性能提升不会有显著作用。
关键字:JDBC和Mybatis中的批处理

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

责任编辑: