深入MyBatis开发之动态SQL

    MyBatis3官方文档:http://www.mybatis.org/mybatis-3/zh/configuration.html

    本blog实例代码:https://github.com/JeeLearner/learning-ssmr   chapter06

一、if元素

1.举例:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ssmr.chapter06.mapper.RoleMapper">

	<resultMap id="roleResultMap" type="com.ssmr.chapter06.pojo.Role">
		<id column="roleNo" property="role_no" />
		<id column="role_name" property="roleName" />
		<id column="note" property="note" />
	</resultMap>

	<select id="findRoles1" parameterType="string" resultMap="roleResultMap">
		SELECT id,role_name,note
		FROM t_role
		WHERE 1=1
		<if test="roleName != null and roleName != ''">
			AND role_name LIKE concat('%', #{roleName}, '%')
		</if>
	</select>
</mapper>

二、choose、when、otherwise元素

1.举例:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ssmr.chapter06.mapper.RoleMapper">

	<resultMap id="roleResultMap" type="com.ssmr.chapter06.pojo.Role">
		<id column="id" property="id" />
		<id column="role_name" property="roleName" />
		<id column="note" property="note" />
	</resultMap>
	<select id="findRoles2" parameterType="role" resultMap="roleResultMap">
		SELECT id,role_name,note
		FROM t_role
		WHERE 1=1
		<choose>
			<when test="id != null and id != ''">
				AND id = #{id}
			</when>
			<when test="roleName != null and roleName != ''">
				AND role_name LIKE concat('%', #{roleName}, '%')
			</when>
			<otherwise>
				AND note is not null
			</otherwise>
		</choose>
	</select>
</mapper>

三、trim、where、set元素

1.where元素

     在前面的语句中我们看到where 1=1,这里的1=1如果不加入就会是where and id=........,显然是错误的,但是加上1=1很奇怪。所以我们可以用where来处理。

当where元素里面的条件成立时,才会接入where这个SQL关键字。

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ssmr.chapter06.mapper.RoleMapper">

	<resultMap id="roleResultMap" type="com.ssmr.chapter06.pojo.Role">
		<id column="id" property="id" />
		<id column="role_name" property="roleName" />
		<id column="note" property="note" />
	</resultMap>
	<select id="findRoles3" parameterType="role" resultMap="roleResultMap">
		SELECT id,role_name,note
		FROM t_role
		<where>
			<if test="roleName != null and roleName != ''">
				AND role_name LIKE concat('%', #{roleName}, '%')
			</if>
			<if test="note != null and note != ''">
				AND note LIKE concat('%', #{note}, '%')
			</if>
		</where>
	</select>
</mapper>
2.trim元素

    有时候要去掉的是一些特殊的SQL语法,比如常见的and、or。而使用trim元素也可以达到预期效果。如下:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ssmr.chapter06.mapper.RoleMapper">

	<resultMap id="roleResultMap" type="com.ssmr.chapter06.pojo.Role">
		<id column="id" property="id" />
		<id column="role_name" property="roleName" />
		<id column="note" property="note" />
	</resultMap>
	<select id="findRoles4" parameterType="string" resultMap="roleResultMap">
		SELECT id,role_name,note
		FROM t_role
		<trim prefix="where" prefixOverrides="and">
			<if test="roleName != null and roleName != ''">
				AND role_name LIKE concat('%', #{roleName}, '%')
			</if>
		</trim>
	</select>
</mapper>
说明:trim元素意味着要去掉一些特殊的字符串,当时prefix代表的是语句的前缀,而prefixOverrides代表的是需要去掉哪种字符串。上面的写法基本与where是等效的。

3.set元素

   Hiberate更新对象时要把所有字段发送给持久对象,来避免发多条SQL的问题,这也会使不需要更新的字段也发送给SQL,显然冗余

MyBatis采用set元素来避免这样的问题:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ssmr.chapter06.mapper.RoleMapper">

	<update id="updateRole" parameterType="role">
		update t_role
		<set>
			<if test="roleName != null and roleName != ''">
				role_name = #{roleName},
			</if>
			<if test="note != null and note != ''">
				note = #{note}
			</if>
		</set>
	</update>
</mapper>
set元素遇到逗号,它就会把对应的逗号去掉。

当然也可以将它改造成用trim元素来完成:<trim prefix="SET" suffixOverrides","......</trim>


四、foreach元素

往往用于SQL中的in关键字。

public List<Role> findRolesByIds(@Param("idList") List<String> idList);

<select id="findRolesByIds" resultType="role">
	SELECT *
	FROM t_role
	WHERE id IN
	<foreach collection="idList" item="id" index="index" open ="(" separator="," close =")">
		#{id}
	</foreach>
</select>
collection:传递进来的参数名称,可以是数组、LIist、Set等集合。

item:循环中当前的元素。

index:当前元素在集合的位置下标。

open/close:以什么符号将这些集合元素包装起来。

separator:各个元素的间隔符。

注意:在SQL中常常用到in语句,但是对于大量数据的in语句要特别注意,它会消耗大量性能,而且一些数据库的SQL对执行的SQL长度有限制,所以使用它时要预估一下collection对象的长度


五、用test的属性判断字符串

1.对于字符串的判断,可以通过加入toString()的方法进行比较;它可以判断数值型的参数;对于枚举而言,取决于使用何种typeHandler。

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.ssmr.chapter06.mapper.RoleMapper">

    <resultMap id="roleResultMap" type="com.ssmr.chapter06.pojo.Role">
        <id column="id" property="id"/>
        <id column="role_name" property="roleName"/>
        <id column="note" property="note"/>
    </resultMap>
    <select id="getRoleTest" parameterType="string" resultMap="roleResultMap">
        select id, role_name, note 
        from t_role
        <if test="type == 'Y'.toString()">
            where 1=1
        </if>
    </select>

</mapper>
在实践中你会发现判断字符串还有一种方法,如下:( 注意单双引号
<select id="getRoleTest" parameterType="string" resultMap="roleResultMap">
    select id, role_name, note
    from t_role
    <if test='type == Y" '>
        where 1=1
    </if>
</select>

六、bind元素

bind元素的作用是通过OGNL表达式去自定义一个上下文变量,这样更方便使用。提高了代码的可移植性

1.场景:在模糊查询时,MySql数据库常常用到concat,用“%”和参数相连;而在Oracle数据库中则没有,而是使用连接符号“||”。这样Sql就需要两种形式去实现。

    bind元素可以不必使用数据库的语言,而是使用MyBatis的动态SQL即可完成。

如下:

public List<Role> findRoles5(String roleName);
<select id="findRoles5" parameterType="string" resultType="com.ssmr.chapter06.pojo.Role">
  <bind name="pattern" value="'%' + _parameter + '%'"/>
    SELECT id,role_name AS roleName,note
    FROM t_role
    WHERE role_name like #{pattern}
</select>
_parameter:代表传递进来的参数。


2.Mybatis支持多个参数使用bind元素,如下:

public List<Role> findRoles6(@Param("roleName") String roleName, @Param("note") String note);
<select id="findRoles6" resultType="com.ssmr.chapter06.pojo.Role">
    <bind name="pattern_roleName" value="'%' + roleName + '%'"/>
    <bind name="pattern_note" value="'%' + note + '%'"/>
    SELECT id,role_name AS roleName,note
    FROM t_role
    WHERE role_name like #{pattern_roleName}
      AND note LIKE #{pattern_note}
</select>
3.MyBatis支持对象的传递使用bind元素,如下:
public List<Role> findRoles7(Role role);
<select id="findRoles7" parameterType="com.ssmr.chapter06.pojo.Role" resultMap="roleResultMap">
    SELECT id,role_name AS roleName,note
    <bind name="pattern_roleName" value="'%' + _parameter.getRoleName() + '%'"/>
    <bind name="pattern_note" value="'%' + _parameter.getNote() + '%'"/>
    FROM t_role
    <where>
        <if test="roleName != null and roleName != ''">
            AND role_name LIKE #{pattern_roleName}
        </if>
        <if test="note != null and note != ''">
            AND note LIKE #{pattern_note}
        </if>
    </where>
</select>
注意:使用bind绑定的元素属性值不可以为null,否则会报异常,但是可以为空字符串。为null的话可以在前台自行抛出异常,如果业务中允许为null,则不能使用bind元素。













  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值