前言

业务中多条sql语句一起执行十分常见。今天我们介绍三种方式来完成批量操作sql语句。

1. 原生JDBC形式

在原生的JDBC中Statement,PreparedStatement可以通过addBatch() 添加多条sql语句,并通过executeBatch() 执行多条sql。
下面只是关于批量操作sql的代码(完整使用JDBC操作数据库的流程可以参考使用JDBC连接数据库)

//使用JDBC实现批量操作sql语句
    @Test
    public void TestBatch() throws Exception {
    	//数据库的配置
    	String driver = "com.mysql.jdbc.Driver";
		String url = "jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true";
 		String username = "root";
        
        Connection coon = null;
        Statement stm = null;

        // 1. 加载连接驱动
        Class.forName(driver);
        //2. 获取数据库连接
        coon = DriverManager.getConnection(url,username,"");
        //3.获取sql执行对象
        stm = coon.createStatement();

        //4.编写要批量执行的sql语句
        String sql1 = "insert into user1(name,pwd) values('b','bbb')";
        String sql2 = "insert into user1(name,pwd) values('c','ccc')";
        stm.addBatch(sql1);
        stm.addBatch(sql2);

        //5.执行要批量执行的sql语句(返回值为每条sql语句影响的行数)
        int[] ints = stm.executeBatch();

        for (int anInt : ints) {
            System.out.println("影响的行数为:"+anInt);
        }

        //6.关闭连接
        stm.close();
        coon.close();


    }
2.mybatis—通过forEach去动态拼接sql语句

说明:这里会省略掉mybatis连接数据库的操作,只是对forEach形式批量操作sql作说明。
[1] 编写数据库表user1对应的实体类
User.class (这里使用了lombok插件)

package com.gs.pojo;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@AllArgsConstructor
@NoArgsConstructor
public class User {
    private int id;
    private String name;
    private String pwd;
}

[2] 编写接口方法 insertUser
UserMapper.class

package com.gs.mapper;
import com.gs.pojo.User;
import java.util.List;

public interface UserMapper {
    /*批量sql操作*/
    public int insertUser(List<User> list);
}

[3] 编写xml文件
sql语句执行的原型

inssert into user1 values(xx,xx),(xxx,xxxx)

UserMapper.xml
<1> collection表示传入来的是一个List数组,item表示遍历的实体项,separator表示中间以 , 进行分割

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.gs.mapper.UserMapper">
   
    <insert id="insertUser" useGeneratedKeys="true" >
        insert into user1(name,pwd)
        values
        <foreach collection="list" separator="," item="user">
        (
           #{user.name},
           #{user.pwd}
        )
        </foreach>
    </insert>

</mapper>

[4] 编写测试方法
[1] MybatisUtil是自己编写的获取SqlSession 的工具类
[2] 通过list把两个对象添加后进行传参执行。

@Test
    public void insertUser(){
        SqlSession sqlSession = MybatisUtil.getSqlSession();
        UserMapper mapper = sqlSession.getMapper(UserMapper.class);

        User user1 = new User();
        user1.setName("ww");
        user1.setPwd("ww");

        User user2 = new User();
        user2.setName("zl");
        user2.setPwd("zl");

        List<User> list = new ArrayList<>();
        list.add(user1);
        list.add(user2);

        int i = mapper.insertUser(list);

        sqlSession.close();
    }

控制台相关的日志文件:

可以看到它只开启一次连接,把两个User对象拼装成了一条sql语句后执行

sql server 批量执行sql文件 怎么批量执行sql语句_sql


补充说明:下面是关于自己编写的获取SqlSession的工具类(可自行跳过)

MybatisUtil.class

package com.gs.utils;

import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;

import java.io.IOException;
import java.io.InputStream;


/**
 * @Auther: Gs
 * @Date: 2020/6/27
 * @Description: com.gs.utils
 * @version: 1.0
 */
public class MybatisUtil {

    private static SqlSessionFactory sqlSessionFactory;

    static {

        try {
        	//我们编写的mybatis核心配置文件
            String resource = "mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            //获得sqlSessionFactory 对象
            sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    //获取sqlSession对象
    public static SqlSession getSqlSession(){
        //这里可以实现自动提交
        return sqlSessionFactory.openSession(true);
    }
}
3. mybatis — 更改sqlSession的执行器

官方上对于执行器有如下述说(要完成业务我们可以使用BATCH形式)

sql server 批量执行sql文件 怎么批量执行sql语句_sql_02


[1] 更改sqlSession的执行器(这里我以上面的工具类为例子)

在获取sqlSession的方法中,通过ExecutorType改变执行器。

//获取sqlSession对象
public static SqlSession getSqlSession(){
      //开启批量操作
      return sqlSessionFactory.openSession(ExecutorType.BATCH,true);
  }

[2] 编写接口方法

/*ExecutorType层面上的批量操作*/
public int insertUser2(User user);

[3] 编写xml文件

<insert id="insertUser2" useGeneratedKeys="true" parameterType="user">
	  insert into user1
	  <trim prefix="(" suffix=")" suffixOverrides=",">
	      <if test="name!=null">name,</if>
	      <if test="pwd!=null">pwd,</if>
	  </trim>
	  <trim prefix="value(" suffix=")" suffixOverrides=",">
	      <if test="name!=null">#{name},</if>
	      <if test="pwd!=null">#{pwd},</if>
	  </trim>
</insert>

[4] 编写测试方法

@Test
 public void insertUser2(){
      SqlSession sqlSession = MybatisUtil.getSqlSession();
      UserMapper mapper = sqlSession.getMapper(UserMapper.class);

      User user1 = new User();
      user1.setName("ww1");
      //user1.setPwd("ww2");
      mapper.insertUser2(user1);

       User user2 = new User();
      user2.setName("zl");
      user2.setPwd("zl");
      mapper.insertUser2(user2);

      sqlSession.commit();
      sqlSession.close();
  }

控制台的日志

解释:这里我们可以看出它执行了两条sql语句后才关闭连接(若进行相关的debug调试,你会发现只有两个User对象都插入后数据库才有相应的值出现)

sql server 批量执行sql文件 怎么批量执行sql语句_User_03

补充说明:除了上面的方式外,我们还可以直接在xml映射的配置文件中直接写多条sql语句在一个方法中进行实现。不过我们在编写数据库连接的url时得加上支持多条sql操作的参数 allowMultiQueries=true