本文共 5802 字,大约阅读时间需要 19 分钟。
文章目录
一、@Param注解
@Param
是MyBatis所提供的作为Dao层的注解,作用是用于传递参数,从而可以与SQL中的的字段名相对应。
首先需要明确一下@Param
和@RequestParam
虽然看起来有那么一点相似,但其实是没有任何关系的,就像鱼香茄子
和鱼
一样。
注解 | 来源 |
---|---|
@Param | org.apache.ibatis.annotations.Param |
@RequestParam | org.springframework.web.bind.annotation.RequestParam |
@RequestParam作用于Controller层,作用是为获取前端参数,解决的是前后端参数不一致的问题。@Param作用于Dao层,是为了传递多个参数,解决的是可读性和直观性;所以它们没有关系!
我们简单看一下使用:
ListselectBlogListByTypeId(@Param("typeId") Integer id);
上述@Param
作用其实就是将id
重命名为typeId
。因此,我们可以在xml中这样使用:
并且当参数来自于多个不同POJO时候,使用@Param后,Mybatis会自动检索参数类型,也就是不用再在xml中配置parameterType
属性了。
public ListfindRoleByMix(@Param("roleP") RoleParam role, @Param("permissionP") PermissionParam permission);
xml配置:
二、Mybatis动态SQL
以前在使用JDBC操作数据时,如果查询条件特别多,将条件串联成SQL字符串是一件痛苦的事情。通常的解决方法是写很多的if-else条件语句对字符串进行拼接,并确保不能忘了空格或在字段的最后省略逗号。MyBatis使用动态SQL来改善这种情形,动态SQL是基于OGNL的表达式,可方便我们在SQL语句中实现某些逻辑,简单说主要是为了解决参数不固定情况。用于实现动态SQL的元素如下。
if:利用if实现简单的条件选择choose(when,otherwise):相当于Java中的switch语句,通常与when和otherwise搭配使用set:解决动态更新语句trim:可以灵活的去除多余的关键字foreach:迭代一个集合,通常用于in条件
set 标签
使用set标签可以将动态的配置 SET 关键字,并剔除追加到条件末尾的任何不相关的逗号。使用 if+set 标签修改后,在进行表单更新的操作中,哪个字段中有值才去更新,如果某项为 null 则不进行更新,而是保持数据库原值。update user where id = #{id} name = #{name}, county = #{county},
大多数标签我们都是结合在一起使用的,常见主要是为了解决参数不固定情况。
2.1 if 和 where 标签
id, name,country,sex,birth,tel
<include refid="params"/>
其实就是你需要查询的sql字段,用一个sql标签封装起来,以后直接引用即可。
<where> <if>
标签来进行控制。where
标签会自动标识其标签内是否有返回值,若有,就插入一个where。 <where>
标签可以自动的将第一个满足的条件前面的逻辑运算符 (or ,and) 去掉,什么意思呢,我们简单看一下: 假设此时我们传入的参数为:id=0 name="童话" country="中国"
观察传入的参数,id传入0,此条件不会执行。name传入一个合法值,此时name条件成立,但是前面多了一个and关键字,此时<where>
标签会自动去掉这个and关键字。 当然,有的人可能会说,后面直接给个where 1=1
不就可以不用<where>
标签了么。如下所示: 当然,这样肯定是能实现你所想的功能的做法,但这个东西也会带来一个巨坑,但是这种做法有一个最大的弊端,如果表有索引的话,会导致数据表上的索引失效。这样查询得效率显然就会很低下,就像${}
和#{}
多数情况下可以通用,但是${}就是不能防止SQL注入问题。因此我们还是采用<where>
标签比较舒适。
如果 where 元素不能满足你的要求,你也可以通过自定义 trim 元素来定制 where 元素的功能。
2.2 trim和if标签
mybatis的trim标签一般用于去除sql语句中多余的and关键字,逗号,或者给sql语句前拼接 where
、set
以及values(
等前缀,或者添加“)“等后缀,可用于选择性插入、更新、删除或者条件查询等操作。
属性 | 描述 |
---|---|
prefix | 给sql语句拼接的前缀 |
suffix | 给sql语句拼接的后缀 |
prefixOverrides | 去除sql语句前面的关键字或者字符,该关键字或者字符由prefixOverrides属性指定,假设该属性指定为"AND",当sql语句的开头为"AND",trim标签将会去除该"AND" |
suffixOverrides | 去除sql语句后面的关键字或者字符,该关键字或者字符由suffixOverrides属性指定 |
举个栗子,和 where 元素等价的自定义 trim 元素为:
上面我们多添加了一个suffix="order by id"
来实现按照某种规则排序,下面再看一个稍微复杂一点的栗子。
insert into blog id, title, views, create_time, #{id,jdbcType=INTEGER}, #{title,jdbcType=VARCHAR}, #{views,jdbcType=INTEGER}, #{createTime,jdbcType=TIMESTAMP},
其中最重要的就是suffixOverrides=","
,表示去除sql语句结尾多余的逗号。
insert into blog(id,title,views,) values(1,"标题",22,)
此时插入将会失败。使用trim标签就可以轻松解决此问题。
2.3 foreach 标签
foreach标签主要有以下参数:
属性 | 描述 |
---|---|
item | 循环体中的具体对象。支持属性的点路径访问,如item.age,item.info.details,在list和数组中是其中的对象,在map中是value。 |
index | 在list和数组中,index是元素的序号,在map中,index是元素的key,该参数可选。 |
open | 表示该语句以什么开始 |
close | 表示该语句以什么结束 |
separator | 表示元素之间的分隔符,例如在in()的时候,separator=","会自动在元素中间用“,“隔开,避免手动输入逗号导致sql错误,如in(1,2,)这样。该参数可选。 |
栗子1:进行list批量插入
insert into users (name, age, county, date) values (#{user.name}, #{user.age}, #{user.county}, #{user.date})
特别注意:Mysql默认接受sql的大小是 1048576(1M), 即第三种方式若数据量超过1M会报如下异常:(可通过调整MySQL安装目录下的my.ini
文件中[mysqld]
段的max_allowed_packet = 1M
)
useGeneratedKeys="true" keyProperty="id"
是用于插入之后返回自增主键的id的,如果对这个没有了解,那么我已经给你准备好
“,”
逗号进行分割,separator=","
的作用就是如此。其中< foreach >
标签内部的属性务必加上item
.。与上面批量插入对应的mapper代码如下: int insert(ListuserList);
当然,其实说到批量插入,最粗暴方法就是for循环直接插入,但是数据量越多,耗费的时间将是巨大的。
借用其他玩家的结果图()记录条数 | 普通for循环 | Mybatis batch | foreach标签 |
---|---|---|---|
500条 | 7742 | 7388 | 622 |
1000条 | 15290 | 15078 | 746 |
5000条 | 78011 | 177350 | 1172 |
10000条 | 397472 | 201180 | 1205 |
栗子2:list集合参数
可以看出我们的 SQL 语句新增了:( ? , ? ) ,前后的括号由open="(" close=")"
进行控制,用“?”
占位符占位,并通过separator以:“,”隔开,内部两个循环遍历出的元素。 栗子3:map参数
< map>
标签需要结合MyBatis的参数注解 @Param()
来使用,需要告诉Mybatis配置文件中的collection="map"
里的map是一个参数: 2.4 choose、when、otherwise 标签
这三个标签需要组合在一起使用,类似于 Java 中的 switch、case、default。只有一个条件生效,也就是只执行满足的条件 when,没有满足的条件就执行 otherwise,表示默认条件。
即使同时添加name和county的值,最终的sql也只会添加第一个属性值。
三、总结
使用批量插入执行的SQL语句应该等价于:
insert into users(name, age, county, date) values (?,?,?,? ),(?,?,?,? ),(?,?,?,? ),(?,?,?,?)
在使用foreach的时候最关键的也是最容易出错的就是collection属性,该属性是必须指定的,但是在不同情况 下,该属性的值是不一样的,主要有一下3种情况:
- 1.如果传入的是单参数且参数类型是一个List的时候,collection属性值为list
- 2.如果传入的是单参数且参数类型是一个array数组的时候,collection的属性值为array
- 3.如果传入的参数是多个的时候,我们就需要把它们封装成一个Map了,当然单参数也可以封装成map
参考链接:
1、 2、 3、当然,更多姿势参见
转载地址:https://dh-butterfly.blog.csdn.net/article/details/109580240 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!