前言
業務中多條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語句後執行
補充說明:下面是關於自己編寫的獲取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形式)
[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對象都插入後數據庫纔有相應的值出現)
補充說明:除了上面的方式外,我們還可以直接在xml映射的配置文件中直接寫多條sql語句在一個方法中進行實現。不過我們在編寫數據庫連接的url時得加上支持多條sql操作的參數 allowMultiQueries=true