标签:sql 数组参数 key postgresq tsql reac parameter 赋值 动态插入
在XML 中支持的几种标签: ? if ? choose、when、otherwise ? where ? set ? trim ? foreach
OGNL 表达式
1. el or e2
2. el and e2
3. el == e2 或 el eq e2
4. el != e2 或 el neq e2
5. el lt e2 :小于
6. el lte e2 :小于等于,其他表示为gt(大于)、gte(大于等于)
7. el + e2 、el - e2 、e1 * e2 、e 1 / e2 、el % e2
8. !e 或 not e :非,取反
9. e.method(args) : 调用对象方法
JO. e.property: 对象属性值
11. el[e2]:按索引取值(List、数组和Map)
12. @class@method(args):调用类的静态方法
13. @class@field:调用类的静态字段值
map[‘userName‘]或map.userName来获取map中key为userName的值。
< if test= "@tk.mybatis.util.StringUtil@isNotEmpty(userName)">
and user_name like concat(‘%‘, #{userName}, ‘%‘)
</if>
其中StringUtil 类如下:
public class StringUtil {
public static boolean isEmpty(String str) {
return str == null || str.length() == 0;
}
public static boolean isNotEmpty(String str) {
return !isEmpty(str) ;
}
}
if 标签有一个必填的属性test, test 的属性值是一个符合OGNL 要求的判断表达式,表达式的结果可以是true 或false ,除此之外所有的非0 值都为true ,只有0 为false。
条件查询
1、判断条件property != null 或property == null,适用于任何类型的字段,用于判断属性值是否为空。
2、判断条件property != ‘‘ 或 property == ‘‘, 仅适用于String 类型的宇段,用于判断是否为空字符串。
3、判断条件list != null and list.size()>0,判断一个集合是否为空。
4、当有多个判断条件时,使用and 或or 进行连接,嵌套的判断可以使用小括号分组,and 相当于Java 中的与(&&),or 相当于Java 中的或(||)。
条件查询
<select id="">
select * from sys_user where 1 = 1
<if test= "userName != null and userName != ‘‘ ">
and user_name like concat(‘%‘, #{userName}, ‘%‘)
</if>
<if test = "userEmail != null and userEmail !=‘‘ " >
and user_email = #{userEmail}
</if>
</select>
1 = 1 有两个作用,作用1:防止报错;作用2:全表查询。
条件更新
现在要实现这样一个需求,只更新有变化的字段。更新的时候不能将原来有值但没有发生变化的字段更新为空或null。通过if标签可以实现这种动态列更新。
<update id="">
update sys_user set
<if test="userName != null and userName !=‘‘ ">
user_name= #{userName},
</if>
<if test="userPassword != null and userPassword !=‘‘ ">
user_password= #{userPassword},
</if>
<if test="userEmail != null and userEmail != ‘‘ ">
user_email = #{userEmail},
</if>
id = #{id}
where id = #{id}
</update>
注意:where 关键字前面的id = #{id},防止报错。
1、如果全部条件都为空或null,sql就是 --> update sys_user set where id = #{id}。
2、查询条件只有一个不是null 也不是空(假设是userName),sql就是 --> update sys_user set user_name= #{userName}, where id= #{id}
条件插入
在数据库表中插入数据的时候,如果某一列的参数值不为空,就使用传入的值,如果传入参数为空,就使用数据库中的默认值,而不使用传入的空值。使用if也可以实现这种动态插入列的功能。
<insert id="" useGeneratedKeys="" keyProperty="">
insert into sys_user(
user_name, user_password,
<if test ="userEmail != null and userEmail !=‘‘ ">
user_email,
</if>
user_info, head_img, create_time)
values(
#{userName}, #{userPassword},
<if test="userEmail != null and userEmail !=‘‘ ">
#{userEmail},
</if>
#{userInfo}, #{headImg,jdbcType=BLOB},
#{createTime, jdbcType = TIMESTAMP})
</insert>
if标签提供了基本的条件判断,但是它无法实现if...else if...else...的逻辑,要想实现这样的逻辑,就需要用到choose when otherwise标签。choose元素中包含when和otherwise两个标签,一个choose中至少有一个when,有0个或者l个otherwise。
choose when when when 是if...else if...else if的关系,只会走其中的一条路,假如第一个when返回true,那么即使第二个第三个都为true,条件里也不会有第二个和第三个。
choose when 和下面的where 相比,没有剔除第一个条件前面的and或or的功能。
<select id= "" resultType="test.mybatis.simple.model.SysUser">
select id , user_name, user_password , user_email, user_info, head_img, create_time
from sys_user
where 1 = 1
<choose>
<when test = "id != null">
and id= #{id}
</when>
<when test= "userName != null and userName !=‘‘ ">
and user_name = #{userName}
</when>
<otherwise>
and 1 = 2
</otherwise>
</choose>
</select>
where标签的作用:
1、当if条件都不满足的时候,where元素中没有内容,SQL中不会出现where;
2、紧跟在where元素后面的第一个查询条件前面如果以and 或 or开头,那么剔除;
3、where 标签,或where if 标签组合,没有给条件前面添加and 或 or 的功能,所以and或or一定要自己手动添加。
set标签的作用:
1、如果该标签包含的元素中有内容,就插入一个set,如果set元素中没有内容,不插入set标签,出现SQL错误,所以为了避免错误产生,类似id=#{id}这样必然存在的赋值仍然有保留的必要。从这一点来看,set标签并没有解决全部的问题,使用时仍然需要注意。
2、如果最后一个条件以逗号结尾,就将这个逗号剔除;其它条件的逗号不会加也不会减。
trim 标签
where和set标签的功能都可以用trim标签来实现,并且在底层就是通过TrimSqlNode实现的。
where标签对应trim的实现如下:
<trim prefix="WHERE" prefixOverrides="AND |OR " >
...
</trim>
这里的AND和OR后面的空格不能省略,为了避免匹配到andes、orders等单词。实际的prefixeOverrides 包含"AND"、"OR"、"AND\n"、"OR\n "、"AND\r"、"OR\r"、"AND\t"、"OR\t",不仅仅是上面提到的两个带空格的前缀。
set标签对应的trim实现如下。
<trim prefix="SET" suffixOverrides="," >
...
</trim>
trim 标签有如下属性。
prefix:当trim 元素内包含内容时,会给内容增加prefix 指定的前缀。
suffix:当trim 元素内包含内容时,会给内容增加suffix 指定的后缀。
prefixOverrides:当trim 元素内包含内容时,会把内容中匹配的前缀字符串去掉。
suffixOverrides:当trim 元素内包含内容时,会把内容中匹配的后缀字符串去掉。
foreach
foreach可以对数组、Map或实现了iterable接口(如List、Set)的对象进行遍历。数组在处理时会转换为List对象,因此foreach遍历的对象可以分为两大类:Iterable类型和Map类型。
collection:必填,值为要迭代循环的属性名。这个属性值的情况有很多。
item:变量名,值为从迭代对象中取出的每一个值,当迭代的对象是Map类型时,这个值为Map的value。
index:索引的属性名,在集合数组情况下值为当前索引值,当迭代的对象是Map类型时,这个值为Map的key。
open:整个循环内容开头的字符串。
close:整个循环内容结尾的字符串。
separator:每次循环的分隔符。
collection的属性设置方法:
以下代码是DefaultSqlSession 中的方法,也是默认情况下的处理逻辑:
private Object wrapCollection(final Object object) {
if (object instanceof Collection) {
StrictMap<Object> map = new StrictMap<Object>();
map.put("collection", object);
if (object instanceof List) {
map.put("list", object);
return map;
}
} else if (object != null && object.getClass().isArray()) {
StrictMap<Object> map = new StrictMap<Object>();
map.put("array", object);
return map;
}
return object;
}
当参数类型为集合的时候,默认会转换为Map 类型,并添加一个key 为"collection",如果参数类型是List 集合,那么就继续添加一个key 为"list",这样,当collection="list"时,就能得到这个集合,并对它进行循环操作。
当参数类型为数组的时候,也会转换成Map类型,默认的key为"array",使用数组参数时,就需要把foreach标签中的collection属性值设置为array。
List --> list 或者 collection
set --> collection
数组 --> array
map --> _parameter
推荐使用@Param 来指定参数的名字,这时collection 就设置为通过@Param 注解指定的名字。
SQL语句中有时会使用IN关键字,例如idin(1,2,3)。可以使用${ids}方式直接获取值,但这种写法不能防止SQL注入,想避免SQL注入就需要用#{}的方式,这时就要配合使用foreach标签来满足需求。
foreach 实现in 集合或数组
List<SysUser> selectByIdList(List<Long> idList);
<select id= "selectByIdList" resultType= "test.mybatis.simple.model.SysUser">
select id,user_name,user_password,user_email,user_Info,head_img,create_time
from sys_user
where id in
<foreach collection= "list" open="(" close=")" separator= "," item= "id" index = "index">
#{id}
</foreach>
</select>
foreach 实现批量插入
如果数据库支持批量插入,就可以通过foreach 来实现。批量插入是SQL-92 新增的特性,目前支持的数据库有DB2, SQL Server 2008 及以上版本、PostgreSQL8.2及以上版本、MySQL、SQLite 3.7.11及以上版本、H2 。批量插入的语法如下。
INSERT INTO tablename (column-a, [column-b, ... ])
VALUES (‘value-la‘, [‘value-lb‘, ...]),
(‘value-2a‘, [‘value-2b‘, ...]),
...
int insertList(List<SysUser> userList);
<insert id="insertList">
insert into sys_user(
user_name , user_password, user_email, user_info, head_img, create_time)
values
<foreach collection ="list" item= "user" separator=",">
(
#{user.userName}, #{user.userPassword}, #{user.userEmail},
#{user.userlnfo}, #{user.headlmg, jdbcType=BLOB} ,
#{user.createTime, jdbcType=TIMESTAMP})
)
</foreach>
</insert>
MyBatis支持批量新增回写主键值的功能(该功能由本书作者提交),这个功能首先要求数据库主键值为自增类型, 同时还要求该数据库提供的JDBC 驱动可以支持返回批量插入的主键值(JDBC 提供了接口,但并不是所有数据库都完美实现了该接口),因此到目前为止,可以完美支持该功能的仅有MySQL 数据库。由于SQLServer 数据库
官方提供的JDBC只能返回最后一个插入数据的主键值,所以不能支持该功能。如果要在MySQL 中实现批量插入返回自增主键值, 只需要在原来代码基础上进行如下修改即可。注意,mybatis版本要是3.3.1或以上。
<insert id= "insertList" useGeneratedKeys ="true" keyProperty="id">
foreach 实现动态UPDATE
int updateByMap(Map<String, Object> map);
<update id="">
update sys_user
set
<foreach collection="_parameter" item="val" index="key" separator=",">
${key} = #{val}
</foreach>
where id = #{id}
</update>
标签:sql 数组参数 key postgresq tsql reac parameter 赋值 动态插入
原文地址:https://www.cnblogs.com/BaiLaowu/p/9348961.html