我是靠谱客的博主 文静诺言,这篇文章主要介绍Mybatis传入参数为List对象时(foreach的用法/批量插入)>Mybatis传入参数为List对象时(foreach的用法/批量插入)>关于mybatis的三种批量插入以及效率比较,现在分享给大家,希望可以做个参考。

文章目录

  • >Mybatis传入参数为List对象时(foreach的用法/批量插入)
  • >关于mybatis的三种批量插入以及效率比较
    • 第一种:普通for循环插入
    • 第二种:mybatis BATCH模式插入
    • 第三种:foreach方式插入
    • 项目实例:

>Mybatis传入参数为List对象时(foreach的用法/批量插入)

  1. 场景复现
    首先有如下一张表:
复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
MySQL [test]> select * from t_entry_resource; +----+-------------+------+----------+--------+--------+---------------------+ | id | resource_id | type | title | banner | icon | add_date | +----+-------------+------+----------+--------+--------+---------------------+ | 11 | 6 | 14 | 分类 | 1.jpg | 2.jpg | 2017-11-17 11:22:30 | | 12 | 3 | 1 | 测试12 | 3.jpg | 4.jpg | 2017-11-17 11:22:30 | | 13 | 653 | 1 | 测试34 | 5.jpg | 6.jpg | 2017-11-20 02:32:26 | | 14 | 1 | 1 | 测试5 | 7.jpg | 8.jpg | 2017-11-20 02:32:51 | | 15 | 3942 | 3 | 测试6 | 9.jpg | 10.jpg | 2017-11-20 02:34:27 | +----+-------------+------+----------+--------+--------+---------------------+ 5 rows in set (0.01 sec)

如果要根据resource_id和type来批量查询记录,该如何编写Mybatis语句?
2. 解决方案
直接贴出来解决方案如下所示:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
Dao层接口: List<EntryResource> findByRidAndType(List<EntryResource> entryResources); XML语句: <select id="findByRidAndType" resultMap="entryResource" parameterType="list"> SELECT * FROM t_entry_resource a WHERE <foreach collection="list" index="index" item="entryResources" open="(" close=")" separator="or"> ( `type`=#{entryResources.type} and resource_id=#{entryResources.resourceId} ) </foreach> </select>

该语句利用了mybatis的foreach动态拼接SQL。

还有批量插入:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
int insertBatch(@Param("list") List<AlarmDispose> disposeList); <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="com.boot.reservation.mapper.AlarmDisposeMapper"> <sql id="tableName"> alarm_dispose </sql> <sql id="baseColumn"> id,alarm_inform_id,dispose_opinion,dispose_explain,dispose_person,accessory,picture,dispose_time,valid </sql> <insert id="insertBatch"> INSERT INTO alarm_dispose (alarm_inform_id,dispose_opinion,dispose_explain,dispose_person,accessory,picture,dispose_time,valid) VALUES <foreach collection ="list" item="alarmDispose" separator =","> (#{alarmDispose.alarmInformId}, #{alarmDispose.disposeOpinion}, #{alarmDispose.disposeExplain}, #{alarmDispose.disposePerson}, #{alarmDispose.accessory}, #{alarmDispose.picture}, #{alarmDispose.disposeTime}, #{alarmDispose.valid}) </foreach > </insert> </mapper>

结果:
在这里插入图片描述

  1. foreach属性
属性描述
item循环体中的具体对象。支持属性的点路径访问,如item.age,item.info.details。具体说明:在list和数组中是其中的对象,在map中是value。该参数为必选。
collection要做foreach的对象,作为入参时,List<?>对象默认用list代替作为键,数组对象有array代替作为键,Map对象用map代替作为键。当然在作为入参时可以使用@Param(“keyName”)来设置键,设置keyName后,list,array,map将会失效。 除了入参这种情况外,还有一种作为参数对象的某个字段的时候。举个例子:如果User有属性List ids。入参是User对象,那么这个collection = "ids"如果User有属性Ids ids;其中Ids是个对象,Ids有个属性List id;入参是User对象,那么collection = "ids.id"上面只是举例,具体collection等于什么,就看你想对那个元素做循环。该参数为必选。
separator元素之间的分隔符,例如在in()的时候,separator=","会自动在元素中间用“,“隔开,避免手动输入逗号导致sql错误,如in(1,2,)这样。该参数可选。
openforeach代码的开始符号,一般是(和close=")"合用。常用在in(),values()时。该参数可选。
closeforeach代码的关闭符号,一般是)和open="("合用。常用在in(),values()时。该参数可选。
index在list和数组中,index是元素的序号,在map中,index是元素的key,该参数可选。
  1. foreach的几种用法
    (1) select count(*) from users id in (x1,x2,x3,…)
复制代码
1
2
3
4
5
6
7
8
9
10
<select id="countByUserList" resultType="int" parameterType="list"> select count(*) from users <where> id in <foreach item="item" collection="list" separator="," open="(" close=")" index=""> #{item.id, jdbcType=NUMERIC} </foreach> </where> </select>

(2) select count(*) from key_cols where col_a = ? AND col_b = ?

复制代码
1
2
3
4
5
6
7
8
<select id="sel_key_cols" resultType="int"> select count(*) from key_cols where <foreach item="item" index="key" collection="map" open="" separator="AND" close=""> ${key} = #{item} </foreach> </select>

(3) select * from t_news n where n.tags like ? or n.tags like ?

复制代码
1
2
3
4
5
6
7
8
<select id="selectTestForEach" parameterType="News" resultMap="NewsResultMapper"> select * from t_news n where <foreach collection="listTag" index="index" item="tag" open="" separator="or" close=""> n.tags like '%'||#{tag}||'%' </foreach> <select>

转载地址:https://www.cnblogs.com/coderzhw/p/11094300.html

>关于mybatis的三种批量插入以及效率比较

1.表结构

复制代码
1
2
3
4
5
6
7
CREATE TABLE `t_user` ( `id` varchar(32) CHARACTER SET utf8 NOT NULL COMMENT '主键', `name` varchar(50) CHARACTER SET utf8 DEFAULT NULL COMMENT '用户名', `del_flag` char(1) CHARACTER SET utf8 DEFAULT NULL COMMENT '删除标示', PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1;

2.1 jdbc.properties配置

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
mysql.driver=com.mysql.jdbc.Driver mysql.url=jdbc:mysql://127.0.0.1:3306/ssm mysql.username=root mysql.password=admin #定义初始连接数 mysql.initialSize=1 #定义最大连接数 mysql.maxActive=20 #定义最大空闲 mysql.maxIdle=20 #定义最小空闲 mysql.minIdle=1 #定义最长等待时间 mysql.maxWait=60000

2.2 spring-mybatis.xml配置

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
<context:component-scan base-package="com.win.ssm"/> <context:property-placeholder location="classpath:jdbc.properties"/> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="${mysql.driver}"/> <property name="url" value="${mysql.url}"/> <property name="username" value="${mysql.username}"/> <property name="password" value="${mysql.password}"/> <!-- 初始化链接大小--> <property name="initialSize" value="${mysql.initialSize}"/> <!-- 连接池最大数量--> <property name="maxActive" value="${mysql.maxActive}"/> <!-- 连接池最大空闲--> <property name="maxIdle" value="${mysql.maxIdle}"/> <!-- 连接池最小空闲 --> <property name="minIdle" value="${mysql.minIdle}"></property> <!-- 获取连接最大等待时间--> <property name="maxWait" value="${mysql.maxWait}"/> </bean> <!-- spring与mybatis整合类 --> <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean"> <property name="dataSource" ref="dataSource"/> <!-- 查找接口的别名 --> <property name="typeAliasesPackage" value="com.win"/> <!-- 自动扫描mapping.xml文件--> <property name="mapperLocations" value="classpath:/mapping/*.xml"/> </bean> <bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate"> <constructor-arg index="0" ref="sqlSessionFactory" /> <!--<constructor-arg index="1" value="BATCH" />--> </bean> <!-- 扫描DAO接口 --> <bean id="mapperScannerConfigurer" class="org.mybatis.spring.mapper.MapperScannerConfigurer"> <property name="basePackage" value="com.win.ssm.dao"/> <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory"/> </bean> <!-- 事务管理 --> <bean class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean>

第一种:普通for循环插入

①junit类

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@Test public void testInsertBatch2() throws Exception { long start = System.currentTimeMillis(); User user; SqlSession sqlSession = sqlSessionTemplate.getSqlSessionFactory().openSession(false); UserDao mapper = sqlSession.getMapper(UserDao.class); for (int i = 0; i < 500; i++) { user = new User(); user.setId("test" + i); user.setName("name" + i); user.setDelFlag("0"); mapper.insert(user); } sqlSession.commit(); long end = System.currentTimeMillis(); System.out.println("---------------" + (start - end) + "---------------"); }

②xml配置

复制代码
1
2
3
4
5
<insert id="insert"> INSERT INTO t_user (id, name, del_flag) VALUES(#{id}, #{name}, #{delFlag}) </insert>

第二种:mybatis BATCH模式插入

①junit类

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@Test public void testInsertBatch2() throws Exception { long start = System.currentTimeMillis(); User user; SqlSession sqlSession = sqlSessionTemplate.getSqlSessionFactory().openSession(ExecutorType.BATCH, false);//跟上述sql区别 UserDao mapper = sqlSession.getMapper(UserDao.class); for (int i = 0; i < 500; i++) { user = new User(); user.setId("test" + i); user.setName("name" + i); user.setDelFlag("0"); mapper.insert(user); } sqlSession.commit(); long end = System.currentTimeMillis(); System.out.println("---------------" + (start - end) + "---------------"); }

②xml配置与第一种②中使用相同

第三种:foreach方式插入

①junit类

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@Test public void testInsertBatch() throws Exception { long start = System.currentTimeMillis(); List<User> list = new ArrayList<>(); User user; for (int i = 0; i < 10000; i++) { user = new User(); user.setId("test" + i); user.setName("name" + i); user.setDelFlag("0"); list.add(user); } userService.insertBatch(list); long end = System.currentTimeMillis(); System.out.println("---------------" + (start - end) + "---------------"); }

②xml配置

复制代码
1
2
3
4
5
6
7
8
9
<insert id="insertBatch"> INSERT INTO t_user (id, name, del_flag) VALUES <foreach collection ="list" item="user" separator =","> (#{user.id}, #{user.name}, #{user.delFlag}) </foreach > </insert>

特别注意:mysql默认接受sql的大小是1048576(1M),即第三种方式若数据量超过1M会报如下异常:(可通过调整MySQL安装目录下的my.ini文件中[mysqld]段的"max_allowed_packet = 1M")

复制代码
1
2
3
nested exception is com.mysql.jdbc.PacketTooBigException: Packet for query is too large (5677854 > 1048576). You can change this value on the server by setting the max_allowed_packet' variable.

结果对比:

第一种第二种第二种
500条77427388622
1000条1529015078746
5000条780111773501172
10000条3974722011801205

项目实例:

service:

复制代码
1
2
3
4
5
6
7
8
9
10
/** * DatePermission 表数据服务层接口 */ public interface DatePermissionService { /** * 新增用户所具有的仓库 */ void save(Long userId,List<Long> list); }

serviceimpl:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@Slf4j @Service public class DatePermissionServiceImpl implements DatePermissionService { @Autowired private DatePermissionMapper datePermissionMapper; @Override public void save(Long userId, List<Long> list) { List<DatePermissionEntity> entityList = new ArrayList<>(); for (Long aLong : list) { DatePermissionEntity entity = new DatePermissionEntity(); entity.setUserId(userId); entity.setWarehousesId(aLong); entityList.add(entity); } datePermissionMapper.insertBatch(entityList); } }

mapper:

复制代码
1
2
3
4
public interface DatePermissionMapper extends BaseMapper<DatePermissionEntity> { void insertBatch(List<DatePermissionEntity> list); }

xml:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"> <mapper namespace="xxx.DatePermissionMapper"> <insert id="insertBatch"> INSERT INTO user_warehouses (user_id, warehouses_id) VALUES <foreach collection ="list" item="datePermissionEntity" separator =","> (#{datePermissionEntity.userId}, #{datePermissionEntity.warehousesId}) </foreach > </insert> </mapper>

实体类:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
@TableName(value = "user_warehouses") public class DatePermissionEntity extends BaseEntity { @TableField(exist = false) private static final long serialVersionUID = 1L; /** * 主键 */ @TableId(type = IdType.AUTO) private Long id; /** * 用户Id */ private Long userId; /** * 仓库Id */ private Long warehousesId; get/set()

表字段:
在这里插入图片描述
测试结果:
在这里插入图片描述

最后

以上就是文静诺言最近收集整理的关于Mybatis传入参数为List对象时(foreach的用法/批量插入)>Mybatis传入参数为List对象时(foreach的用法/批量插入)>关于mybatis的三种批量插入以及效率比较的全部内容,更多相关Mybatis传入参数为List对象时(foreach内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(70)

评论列表共有 0 条评论

立即
投稿
返回
顶部