您的位置:首页 > 数据库

mybatis--动态sql

2016-03-09 11:44 447 查看
原生sql好不好,当然好,因为可以直接去修改来面对我业务的变化,一般有一两年开发经验的人,又是最基本JDBC开发的人,对于sql语句的热爱可谓是喜形于色,而说到一些持久层框架,面对复杂的业务变化的时候,就会感到头更,因为我不会用啊。面向对象用不好啊,而mybatis就很好的解决了这个问题。那么今天我们将一下在mybatis中如何动态拼接sql。

mybatis对于我们的变化封装了if判空,where 条件,foreach循环拼接和对于代码块的封装的sql片段。

if语句

例如我们在动态拼接sql的时候,判断我们拼接的串是不是一个可以让sql语句成功执行的串,一般的操作是判断我们传入的参数是不是为空。而mybatis就很好的做到了这些。

<select id="findUserList" parameterType="user" resultType="user">
select * from user
where 1=1
<if test="id!=null and id!=''">
and id=#{id}
</if>
<if test="username!=null and username!=''">
and username like '%${username}%'
</if>
</select>


这样假如有一个他们的参数都不为空,那么他生成的语句就是

select * from user where 1=1 and id=1 and username like '%孟%'


如果有一个参数为空,那么是如下

select * from user where 1=1 and id=1


都为空

select * from user where 1=1


where

大家看到在我们上边的代码是有一个where 1=1 这么一句话,就是说如果我的参数传入为空,我们的sql语句也不会变成 select * from user where,但是还有一种办法,比上边的办法更好,用mybatis的where

<select id="findUserList" parameterType="user" resultType="user">
select * from user
<where>
<if test="id!=null and id!=''">
and id=#{id}
</if>
<if test="username!=null and username!=''">
and username like '%${username}%'
</if>
</where>
</select>


这样的话他会自动为我们的用户表后边加上where

foreach

想必大家都有这么用过,加入我要查询一个id,而这个id只有在某个集合中就可以,这个时候大家会这么做。

传统sql

select * from username where id=12 or id=13 or id=14


select * from username where id in (12,13,14)


这两种本身没有什么问题,但是我们用mybatis如何实现上边的效果,如下。

mybatis生成

加入我们传入的参数有一个是id的集合为ids。

UserQueryVo.java

public class UserQueryVo {

private List<Integer> ids;
private UserCustom userCustom;
public UserCustom getUserCustom() {
return userCustom;
}
public void setUserCustom(UserCustom userCustom) {
this.userCustom = userCustom;
}
public List<Integer> getIds() {
return ids;
}
public void setIds(List<Integer> ids) {
this.ids = ids;
}
}


mapper.xml

id=1 or id = 2

<if test="ids!=null">
<foreach collection="ids" item="user_id" open="and id in ("close=")" separator=",">
#{user_id}
</foreach>
/if>


in (1,2,3)

<if test="ids!=null">
<foreach collection="ids" item="user_id" open="and(" close=")" separator="or">
id=#{user_id}
</foreach>
</if>


上边的代码大家已经了解最基本的语法功能,ids是传入的参数的一个List集合,item=”user_id”是一个别名,open=”“是表示开始拼接的字符串,close”“表示结束的字符串,separator=”“表示中间的字符串,客户端代码如下

客户端

@Test
public void testUserList() throws Exception {
SqlSession sqlSession = sqlSessionFactory.openSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
UserQueryVo userQueryVo = new UserQueryVo();
UserCustom userCustom = new UserCustom();
userCustom.setUsername("王五");
List<Integer> ids = new ArrayList<Integer>();
ids.add(1);
ids.add(10);
ids.add(16);
userQueryVo.setUserCustom(userCustom);
userQueryVo.setIds(ids);
List<UserCustom> list = userMapper.findUserList(userQueryVo);

System.out.println(list.get(0));
}


生成的sql语句如下



sql片段

因为我们对于一个实体的增删改可能不止一个地方用的到,所以我们用的无论是if,where,或者foreach,我们最好是把他们封装起来,这样就可以实现重用了。利用代码如下:

<!-- 定义sql片段 id:sql片段的唯一标识符 经验:基于单表定义sql片段,这样可用性更高 -->
<sql id="query_user_where">
<if test="userCustom!=null">
<if test="userCustom.username!=null and userCustom.username!=''">
and user.username LIKE '%${userCustom.username}%'
</if>

<if test="userCustom.sex!=null and userCustom.sex!=''">
and user.sex=#{userCustom.sex}
</if>

<!-- 使用foreach collection:置顶输入对象中的集合属性 item:每个遍历生成的属性名 and:开始的字符串 end:结束的串
separator:遍历中间需要的串 -->
<if test="ids!=null">
<foreach collection="ids" item="user_id" open="and(" close=")"
separator="or">
id=#{user_id}
</foreach>

<!-- and id in(1,2,3) -->
<!-- <foreach collection="ids" item="user_id" open="and id in (" close=")"
separator=","> -->
<!-- #{user_id} -->
<!-- </foreach> -->
</if>
</if>
</sql>


定义了他的id,以后其他的地方要用的话,只需要引用一下即可以。如下:

<!-- 用户的综合查询 #{userCustom.sex}取出来包装类的性别的值 -->
<select id="findUserList" parameterType="cn.itcast.mybatis.po.UserQueryVo"
resultType="cn.itcast.mybatis.po.UserCustom">
SELECT id,username,birthday,address FROM USER

<where>

<!-- 如果有其他xml中的sql片段,需要加namespace -->
<include refid="query_user_where"></include>
</where>

</select>


这里大家可能有疑问,为什么上边的sql片段不加上where,而要在statement中写上where,这里就要说名的是,我可能在我的statement中引用的不止一个sql,所以大家明白了吗。

完整mapper.xml

<?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">

<!-- 命名空间,作用:对sql进行分类话的管理,sql的隔离 注意,如果使用mapper代理开发,他代表mapper接口的地址 -->
<mapper namespace="cn.itcast.mybatis.mapper.UserMapper">

<!-- 定义sql片段 id:sql片段的唯一标识符 经验:基于单表定义sql片段,这样可用性更高 -->
<sql id="query_user_where">
<if test="userCustom!=null">
<if test="userCustom.username!=null and userCustom.username!=''">
and user.username LIKE '%${userCustom.username}%'
</if>

<if test="userCustom.sex!=null and userCustom.sex!=''">
and user.sex=#{userCustom.sex}
</if>

<!-- 使用foreach collection:置顶输入对象中的集合属性 item:每个遍历生成的属性名 and:开始的字符串 end:结束的串
separator:遍历中间需要的串 -->
<if test="ids!=null">
<foreach collection="ids" item="user_id" open="and(" close=")"
separator="or">
id=#{user_id}
</foreach>

<!-- and id in(1,2,3) -->
<!-- <foreach collection="ids" item="user_id" open="and id in (" close=")"
separator=","> -->
<!-- #{user_id} -->
<!-- </foreach> -->
</if>
</if>
</sql>

<!-- 用户的综合查询 #{userCustom.sex}取出来包装类的性别的值 --> <select id="findUserList" parameterType="cn.itcast.mybatis.po.UserQueryVo" resultType="cn.itcast.mybatis.po.UserCustom"> SELECT id,username,birthday,address FROM USER <where> <!-- 如果有其他xml中的sql片段,需要加namespace --> <include refid="query_user_where"></include> </where> </select>
<select id="findUserCount" parameterType="cn.itcast.mybatis.po.UserQueryVo"
resultType="int">
SELECT count(*) FROM USER

<where>
<if test="userCustom!=null">
<if test="userCustom.username!=null and userCustom.username!=''">
and user.username LIKE '%${userCustom.username}%'
</if>

<if test="userCustom.sex!=null and userCustom.sex!=''">
and user.sex=#{userCustom.sex}
</if>
</if>
</where>

</select>

</mapper>


小结

对于sql片段的应用,可能才是咱们对于mybatis运用最常用的功能了,因为他才是对于业务变化的最集中的地方,所以如果需要用mybatis,不妨好好的练习和运用一下咱们的sql片段。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  mybatis 持久层框架