<foreach>标签动态增删改查
mybatis<foreach>
有的时候在项目中需要查询某个列表时,可能会在代码中进行嵌套循环再取值,其实mybatis提供了这么一个标签,可以在SQL中进行循环(是不是很酸爽)
先来了解一下foreach这个标签有哪些元素:
-
item
:表示集合中每一个元素进行迭代时的别名 -
index
:指定一个名字,用于表示在迭代过程中,每次迭代到的位置 -
open
:表示该语句以什么开始 -
separator
:表示在每次进行迭代之间以什么符号作为分隔符 -
close
:表示以什么结束 -
collection
:被循环的集合或者数组
注意:
在使用foreach的时候最关键的也是最容易出错的就是collection属性,该属性是必须指定的,但是在不同情况下,该属性的值是不一样的,主要有一下3种情况:
- 如果传入的是单参数且参数类型是一个List的时候,collection属性值为list
- 如果传入的是单参数且参数类型是一个array数组的时候,collection的属性值为array
- 如果传入的参数是多个的时候,我们就需要把它们封装成一个Map或者Object。
实战
话不多说,看代码,首先是mybatis的XML如何写,拿动态创建表为例子,什么是动态创建表,就是可以随便生成表名,字段是传入进来的集合数组,根据这个数组内容来创建字段
1
2
3
4
5
6
7
8
9
10
11
12
|
< update id = "createTable" parameterType = "java.util.HashMap" > CREATE TABLE IF NOT EXISTS ed_temp_${tableName}( id VARCHAR(32) NOT NULL, log_id VARCHAR(32), state INT, message VARCHAR(255) < foreach collection = "list" item = "column" open = "," separator = "VARCHAR(255)," close = "VARCHAR(255), PRIMARY KEY (id)" > ${column.name} </ foreach > ) ENGINE = InnoDB DEFAULT CHARSET = utf8; </ update > |
这个<foreach>看出,我传入的叫一个list的集合,别名叫column,从,开始,因为上面message少个逗号,中间用VARCHAR(255),做分隔符,已什么为结束都定义好了。
看Mapper类
1
2
3
4
|
/** * 动态创建表 */ void createTable(HashMap<String , Object> map); |
看实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
/** * 创建表 * @param templateId 模板id */ private void createTable(String templateId){ List<EdTemplateField> fields = edTemplateFieldMapper.findByTemplate(templateId); List<EdFieldColumns> columns = new ArrayList<>(); HashMap<String,Object> map = new HashMap<>( 16 ); map.put( "tableName" ,templateId); for (EdTemplateField field : fields) { columns.add(edFieldColumnsMapper.findByField(field.getId()).get( 0 )); } map.put( "list" ,columns); edTemplateMapper.createTable(map); } |
逻辑是这样的,通过传入的ID,去寻找所需要的值,再创建一个List和一个Map,将表名放进来,在将需要的数组放进来,调用mapper的方法,最后就能成功创建一张动态表
往这个动态表里插入数据的方式也用到了<foreach>,应该说不得不用,不然怎么插入,又不知道表名又没有实体类
XML
1
2
3
4
5
6
7
8
9
10
11
12
|
< insert id = "tableInsert" parameterType = "java.util.HashMap" > INSERT INTO ed_temp_${tableName}( id,log_id,state,message < foreach collection = "columns" item = "column" open = "," separator = "," > ${column.name} </ foreach > )VALUES( < foreach collection = "values" item = "value" open = "REPLACE(UUID(),'-','')," separator = "," > #{value} </ foreach > ) </ insert > |
两个<foreach>标签,一个是字段,刚刚那个动态建表的字段,一个是值
mapper类
1
2
3
4
5
|
/** * 动态插入 * @param map */ void tableInsert(HashMap<String,Object> map); |
实现方法
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
/** * 保存数据到临时表 * @param templateId 模板id * @param list 数据集合 * @param hearTitle 数据对应的字段 */ private void tableInsert(String templateId,List<String> list,List<String> hearTitle){ List<EdFieldColumns> columns = new ArrayList<>(); HashMap<String,Object> map = new HashMap<>( 16 ); map.put( "tableName" ,templateId); for (String s : hearTitle) { columns.add(edFieldColumnsMapper.findByTemplateIdAndName(s,templateId)); } map.put( "columns" ,columns); map.put( "values" ,list); edTemplateMapper.tableInsert(map); } |
说明
其余的类代码就不贴了,逻辑是这样的,创建一个放字段的集合和传入的map,集合的值必须要和字段对应的上,不然插错字段值那就很尴尬,所以必须要通过动态创建的字段和值的顺序是一样的,比如第一个创建了name那插入的第一个就是name,这个意思,所以这里是根据顺序,先排好了字段,放入map里,再将要放入动态表的值放进来,进行mapper操作
有了建表以及插入,当然少不了删除和更新
删除表的xml
1
2
3
4
5
6
7
8
9
10
|
< update id = "deleteTable" parameterType = "java.lang.String" > DROP TABLE ${tempTable} </ update > < delete id = "deleteTemporary" > DELETE FROM ${tableName} WHERE id = #{id} </ delete > |
用于来删除不需要的表,以及删除数据
1
2
3
|
void deleteTable( @param (value = "tempTable" ) String tempTable); void deleteTemporary( @Param ( "tableName" ) String tableName, @Param ( "id" ) String id); |
这是mapper接口的写法,传入要删除的表名就可以
更新的XML
1
2
3
4
5
6
7
8
9
|
< update id = "updateTemporary" > UPDATE ${tableName} SET < foreach collection = "dataMap" index = "key" item = "value" separator = "," > ${key} = #{value} </ foreach > WHERE id = #{id} </ update > |
对应的mapper接口
1
2
3
|
void updateTemporary(@Param("tableName") String tableName, @Param("id") String id, @Param("dataMap") HashMap dataMap); |
mapper.xml中<foreach>标签使用
循环参数内容,还具备在内容的前后添加内容,还具备添加分隔符功能。
适用场景
in 查询.批量新增中(mybatis 中 foreach 效率比较低)
1 如果希望批量新增,SQL 命令
1
|
insert into tableName VALUES ( default ,1,2,3),( default ,4,5,6),( default ,7,8,9) |
2 openSession()必须指定底层 JDBC 的
1
2
|
PreparedStatement.addBatch(); factory.openSession(ExecutorType.BATCH); |
以上为个人经验,希望能给大家一个参考,也希望大家多多支持服务器之家。
原文链接:https://blog.csdn.net/m0_37701381/article/details/80254901