MyBatis之动态SQL

713 阅读2分钟

MyBatis之动态SQL

一、符号

在 mapper 的动态 SQL 中若出现大于号(>)、小于号(<)、大于等于号(>=),小于等于号(<=)等 符号,最好将其转换为实体符号。否则, XML 可能会出现解析出错问题。 实体符号表:

符号符号名称实体符号
<小于&lt;
大于&gt;
>=大于等于&gt;=
<=小于等于&lt;=

二、动态SQL之if

  • 如果传进来的不是简单类型的参数,在iftest中直接使用类中的属性名即可(要有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>
  • 如果传进来的是简单类型的参数,则在iftest属性中要使用_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>

三、动态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 &lt; #{age}
        </if>
    </where>
</select>

注意:使用<where/>标签, 在有查询条件时, 可以自动添加where 子句;没有查询条件时,不会添加where 子句。需要注意的是,第一个<if/>标签中的 SQL 片断,可以不包含 and。不过,写上 and 也不错,系统会将多出的 and 去掉。但其它<if/>中 SQL 片断的 and,必须要求写上。否则 SQL 语句将拼接出错

四、动态 SQL 之foreach

<foreach/>标签用于实现对于数组与集合的遍历。对其使用,需要注意

  • collection 表示要遍历的集合类型,list , array 等。
  • opencloseseparator 为对遍历内容的 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 的值,所以最好是将其中一个 idas 取别名代替==。

七、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>