mybatis--动态sql
2016-03-09 11:44
447 查看
原生sql好不好,当然好,因为可以直接去修改来面对我业务的变化,一般有一两年开发经验的人,又是最基本JDBC开发的人,对于sql语句的热爱可谓是喜形于色,而说到一些持久层框架,面对复杂的业务变化的时候,就会感到头更,因为我不会用啊。面向对象用不好啊,而mybatis就很好的解决了这个问题。那么今天我们将一下在mybatis中如何动态拼接sql。
mybatis对于我们的变化封装了if判空,where 条件,foreach循环拼接和对于代码块的封装的sql片段。
这样假如有一个他们的参数都不为空,那么他生成的语句就是
如果有一个参数为空,那么是如下
都为空
这样的话他会自动为我们的用户表后边加上where
这两种本身没有什么问题,但是我们用mybatis如何实现上边的效果,如下。
上边的代码大家已经了解最基本的语法功能,ids是传入的参数的一个List集合,item=”user_id”是一个别名,open=”“是表示开始拼接的字符串,close”“表示结束的字符串,separator=”“表示中间的字符串,客户端代码如下
生成的sql语句如下
定义了他的id,以后其他的地方要用的话,只需要引用一下即可以。如下:
这里大家可能有疑问,为什么上边的sql片段不加上where,而要在statement中写上where,这里就要说名的是,我可能在我的statement中引用的不止一个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 oracle BLOB类型字段保存与读取
- MyBatis MapperProvider MessageFormat拼接批量SQL语句执行报错的原因分析及解决办法
- oracle+mybatis 使用动态Sql当插入字段不确定的情况下实现批量insert
- MyBatis学习笔记(二)之关联关系
- 浅析Mybatis 在CS程序中的应用
- Java Mybatis框架入门基础教程
- Java简单实现SpringMVC+MyBatis分页插件
- MyBatis批量添加、修改和删除
- MyBatis与Hibernate的比较
- 浅析mybatis和spring整合的实现过程
- mybatis的动态sql详解(精)
- Mybatis实现增删改查及分页查询的方法
- MyBatis入门学习教程(一)-MyBatis快速入门
- Spring与Mybatis的整合方法有哪些
- 详解MyBatis直接执行SQL查询及数据批量插入
- 解决springmvc+mybatis+mysql中文乱码问题
- Spring3.1.1+MyBatis3.1.1的增、删、查、改以及分页和事务管理
- Spring+Mybatis+Mysql搭建分布式数据库访问框架的方法
- Mybatis实战教程之入门到精通(经典)
- Mybatis与Hibernate的区别