概述
文章目录
- >Mybatis传入参数为List对象时(foreach的用法/批量插入)
- >关于mybatis的三种批量插入以及效率比较
- 第一种:普通for循环插入
- 第二种:mybatis BATCH模式插入
- 第三种:foreach方式插入
- 项目实例:
>Mybatis传入参数为List对象时(foreach的用法/批量插入)
- 场景复现
首先有如下一张表:
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. 解决方案
直接贴出来解决方案如下所示:
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。
还有批量插入:
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>
结果:
- 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,)这样。该参数可选。 |
open | foreach代码的开始符号,一般是(和close=")"合用。常用在in(),values()时。该参数可选。 |
close | foreach代码的关闭符号,一般是)和open="("合用。常用在in(),values()时。该参数可选。 |
index | 在list和数组中,index是元素的序号,在map中,index是元素的key,该参数可选。 |
- foreach的几种用法
(1) select count(*) from users id in (x1,x2,x3,…)
<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 = ?
<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 ?
<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.表结构
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配置
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配置
<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类
@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配置
<insert id="insert">
INSERT INTO t_user (id, name, del_flag)
VALUES(#{id}, #{name}, #{delFlag})
</insert>
第二种:mybatis BATCH模式插入
①junit类
@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类
@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配置
<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")
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条 | 7742 | 7388 | 622 |
1000条 | 15290 | 15078 | 746 |
5000条 | 78011 | 177350 | 1172 |
10000条 | 397472 | 201180 | 1205 |
项目实例:
service:
/**
* DatePermission 表数据服务层接口
*/
public interface DatePermissionService {
/**
* 新增用户所具有的仓库
*/
void save(Long userId,List<Long> list);
}
serviceimpl:
@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:
public interface DatePermissionMapper extends BaseMapper<DatePermissionEntity> {
void insertBatch(List<DatePermissionEntity> list);
}
xml:
<?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>
实体类:
@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的用法/批量插入)>Mybatis传入参数为List对象时(foreach的用法/批量插入)>关于mybatis的三种批量插入以及效率比较所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复