文章目录
MyBatis学习记录(3)之动态SQL
一、符号
在 mapper 的动态 SQL 中若出现大于号(>)、小于号(<)、大于等于号(>=),小于等于号(<=)等
符号,最好将其转换为实体符号。否则, XML 可能会出现解析出错问题。
实体符号表:
符号 | 符号名称 | 实体符号 |
---|---|---|
< | 小于 | < |
> | 大于 | > |
>= | 大于等于 | >= |
<= | 小于等于 | <= |
二、动态SQL之if
- 如果传进来的不是简单类型的参数,在
if
的test
中直接使用类中的属性名即可(要有getter)
注意:where
后面要加入1=1
,否则会拼接错误
<select id="selectStudentIf" resultType="com.bjpowernode.domain.Student">
select id,name, email, age from student
where 1=1
<if test="name !=null and name !=''">
and name = #{name}
</if>
<if test="age != null ">
and age = #{age}
</if>
</select>
传入简单类型参数
- 如果传进来的是简单类型的参数,则在
if
的test
属性中要使用_parameter
下面例子中,传进来一个String
字符串name
,进行模糊查询
<select id="getAllActivityListByName" resultType="Activity">
select name from tbl_activity
<where>
<if test="_parameter != null and _parameter != ''">
name like "%" #{name} "%"
</if>
</where>
</select>
传入枚举类型
List<Map<String,Object>> searchTest(@Param("flag") EnumType flag);
<select id="searchTest" resultType="java.util.Map">
select * from t_test
where DATE_FORMAT( push_data_time ,'%m-%d-%Y') = DATE_FORMAT(NOW(),'%m-%d-%Y')
<!--枚举对象的引用路径-->
<if test="flag == @com.zyx.test.enums.EnumType@B_FLAG">
and b_flg=0
</if>
<if test="flag == @com.zyx.test.enums.EnumType@A_FLAG">
and a_flg=0
</if>
</select>
枚举对象:
@Getter
public enum EnumType {
A_FLAG("a"),
B_FLAG("b"),
;
private String name;
EnumCityType(String name) {
this.name = name;
}
}
三、动态SQL之where
用来解决<if>的拼接问题
<select id="selectStudentWhere" resultType="com.bjpowernode.domain.Student">
select id,name, email, age from student
<where>
<if test="name !=null and name !=''">
name = #{name}
</if>
<if test="age != null ">
and age < #{age}
</if>
</where>
</select>
注意:使用<where/>
标签, 在有查询条件时, 可以自动添加上 where
子句;没有查询条件时,不会添加where
子句。需要注意的是,第一个<if/>
标签中的 SQL 片断,可以不包含 and。不过,写上 and 也不错,系统会将多出的 and 去掉。但其它<if/>
中 SQL 片断的 and,必须要求写上。否则 SQL 语句将拼接出错
四、动态 SQL 之foreach
<foreach/>标签用于实现对于数组与集合的遍历。对其使用,需要注意:
collection
表示要遍历的集合类型,list , array 等。open
、close
、separator
为对遍历内容的 SQL 拼接。
语法:
<foreach collection="集合类型"
open="开始的字符"
close="结束的字符"
item="集合中的成员"
separator="集合成员之间的分隔符">
#{item 的值}
</foreach>
例如:取出表中id为:1002,1003,1005的数据
List<Integer> idlist = new ArrayList<>();
idlist.add(1002);
idlist.add(1003);
idlist.add(1005);
List<Student> students = studentDao.selectStudentForeachList(idlist);
<select id="selectStudentForeachList" resultType="com.bjpowernode.domain.Student">
select id,name, email, age from student
where id in
<foreach collection="list" open="(" close=")" item="sid" separator=",">
#{sid}
</foreach>
</select>
相当于java中的字符串拼接:
List<Integer> idlist = new ArrayList<>();
idlist.add(1002);
idlist.add(1003);
idlist.add(1005);
// (1002,1003,1005)
StringBuffer s = new StringBuffer();
s.append("(");
for (Integer id : idlist) {
s.append(id).append(",");
}
int pos = s.lastIndexOf(",");
s.deleteCharAt(pos);
s.append(")");
五、代码片断
在mapper文件中,<sql/>
标签用于定义 SQL 片断,以便其它 SQL 标签复用
<sql id="studentField">
select id,name, email, age from student
</sql>
<select id="selectStudentIf" resultType="com.bjpowernode.domain.Student">
<include refid="studentField"/>where id=1005;
</select>
六、resultMap
resultMap是Mybatis最强大的元素,它可以将查询到的复杂数据(比如查询到几个表中数据)映射到一个结果集当中。
<!--column属性不做限制,可以为任意表的字段,而property须为type 定义的实体类属性-->
<resultMap id="唯一的标识" type="映射的pojo对象">
<id column="表的主键字段,或者可以为查询语句中的别名字段" jdbcType="字段类型" property="映射实体类对象的主键属性" />
<result column="表的一个字段(可以为任意表的一个字段)" jdbcType="字段类型" property="映射到实体类对象的一个属性(须为type定义的实体类对象中的一个属性)"/>
<association property="实体类的一个对象属性" javaType="实体类关联的实体类对象">
<id column="关联实体类对象对应表的主键字段" jdbcType="字段类型" property="关联实体类对象的主席属性"/>
<result column="任意表的字段" jdbcType="字段类型" property="关联实体类对象的属性"/>
</association>
<!-- 集合中的property须为oftype定义的pojo对象的属性-->
<collection property="实体类的集合属性" ofType="集合中的实体类对象">
<id column="集合中实体类对象对应的表的主键字段" jdbcType="字段类型" property="集合中实体类对象的主键属性" />
<result column="可以为任意表的字段" jdbcType="字段类型" property="集合中的实体类对象的属性" />
</collection>
</resultMap>
例如:
<resultMap id="BaseResultMap" type="com.wkcto.springboot.model.Student">
<id column="id" jdbcType="INTEGER" property="id"/>
<result column="name" jdbcType="VARCHAR" property="name"/>
<result column="age" jdbcType="INTEGER" property="age"/>
<association property="classRoom" javaType="com.wkcto.springboot.model.ClassRoom">
<id column="id" jdbcType="INTEGER" property="id"/>
<result column="name" jdbcType="VARCHAR" property="name"/>
</association>
</resultMap>
注意:上面会有两个 id
值,可能会出现 mybatis
混淆两个 id
的值,所以最好是将其中一个 id
用 as
取别名代替。
七、trim标签
trim标签一般用于去除sql语句中多余的and关键字,逗号,或者给sql语句前拼接 “where“、“set“以及“values(“ 等前缀,或者添加“)“等后缀,可用于选择性插入、更新、删除或者条件查询等操作。
<trim prefix="给sql语句拼接的前缀"
suffix="给sql语句拼接的后缀"
suffixOverrides="去除sql语句前面的关键字或者字符,当sql语句的开头为指定的字符时,trim标签将会去除该字符"
prefixOverrides="去除sql语句前面的关键字或者字符">
</trim>
一个选择性插入的小例子:
<insert id="insertSelective" parameterType="com.wkcto.springboot.model.Student">
insert into t_student
<trim prefix="(" suffix=")" suffixOverrides=",">
<if test="id != null">
id,
</if>
<if test="name != null">
name,
</if>
<if test="age != null">
age,
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="id != null">
#{id,jdbcType=INTEGER},
</if>
<if test="name != null">
#{name,jdbcType=VARCHAR},
</if>
<if test="age != null">
#{age,jdbcType=INTEGER},
</if>
</trim>
</insert>
八、bind 标签
<bind>
标签的作用实质就是建立新的映射关系
<bind name="将value中计算后的值绑定到name给定的字段上"
value="处理方法"/>
<!--使用bind进行页码计算-->
<select id="queryPage" resultMap="Result"
parameterType="com.dto.EcouponMemberDto">
select * from t_student
<!--前端传的page是页码,使用bind标签转换成Limit的第一个参数-->
<bind name="page" value="(page-1)*size"></bind>
limit #{page,jdbcType=INTEGER},#{size,jdbcType=INTEGER}
</select>
<!--使用bind元素进行模糊查询-->
<select id="selectUserByBind" resultType="com.po.MyUser" parameterType= "com.po.MyUser">
<!-- bind 中的 uname 是 com.po.MyUser 的属性名-->
<bind name="paran_uname" value="'%' + uname + '%'"/>
select * from user where uname like #{paran_uname}
</select>