Mybatis-动态sql

来源:互联网 发布:苏州2017打车软件 编辑:程序博客网 时间:2024/05/18 01:49

动态sql在Mybatis中是很重要的东西,通过动态sql,我们可以更直观的进行编程,同时,对于修改代码也要相对简捷

一些;动态sql主要包括:sql片段、IF、Where、foreach等内容,下面通过实例进行讲解。


Sql片段

在Mybatis中进行sql的编写时,我们习惯于将sql不加任何条件的写在一起,即完成一天单纯的Sql语句。如下所示:

<!-- 用户信息的综合查询#{userCustom.sex}:取出pojo包装对象中sex的数据${userCustom.username}:取出包装对象中用户的名称 --><select id="findUserList" parameterType="com.sw.po.UserQueryVo" resultType="com.sw.po.UserCustom">select *from user user.sex=#{userCustom.sex} and user.username like '%${userCustom.username}%'</select>

但是在实际开发中,这并不适用,因为在sql语句中存在的一些变量,我们并没有做任何规范以及判断就进行sql的执行,这是不正确的;所以我们

需要对sql语句中的一些变量以及字段做出一定的规范与判断,如下所示:

<!-- 用户信息的综合查询#{userCustom.sex}:取出pojo包装对象中sex的数据${userCustom.username}:取出包装对象中用户的名称 --><select id="findUserList" parameterType="com.sw.po.UserQueryVo" resultType="com.sw.po.UserCustom">select *from user<!-- where可以自动去掉条件中的第一个and --><where><!-- 使用动态sql,当输入参数不为空时才执行sql --><if test="userCustom!=null"><!-- 判断userCustom.sex --><if test="userCustom.sex!=null and userCustom.sex!=''">and user.sex=#{userCustom.sex}</if><!-- 判断userCustom.username --><if test="userCustom.username!=null and userCustom.username!=''">and user.username like '%${userCustom.username}%'</if></if></where></select>

经过改进,我们在sql语句中加入了IF与where判断,但是经过观察不难发现,这样的Sql未免太过于繁杂,同时,这些IF也会存在于其他Sql语句中,于是Mybatis为我们提供了Sql片段抽出与Sql引用;我们可以将相同的Sql代码抽取出来,进而在其他Sql语句中继续引用,如下所示:

抽取Sql:

<!-- 定义sql片段id:sql片段的唯一标识注意:一般定义sql片段是定义单表定义的,这样可增加sql片段的可重用性在sql片段中建议不包括where条件 --><sql id="query_user_where"><!-- 使用动态sql,当输入参数不为空时才执行sql --><if test="userCustom!=null"><!-- 判断userCustom.sex --><if test="userCustom.sex!=null and userCustom.sex!=''">and user.sex=#{userCustom.sex}</if><!-- 判断userCustom.username --><if test="userCustom.username!=null and userCustom.username!=''">and user.username like '%${userCustom.username}%'</if></if></sql>

引用Sql片段:

<!-- 用户信息的综合查询#{userCustom.sex}:取出pojo包装对象中sex的数据${userCustom.username}:取出包装对象中用户的名称 --><select id="findUserList" parameterType="com.sw.po.UserQueryVo" resultType="com.sw.po.UserCustom">select *from user<!-- where可以自动去掉条件中的第一个and --><where><!-- 使用动态sql,当输入参数不为空时才执行sql --><!-- 引用sql代码片段 --><include refid="query_user_where"/></where></select>


foreach标签

在Mybatis开发中,我们常常需要向Sql传入集合(List)或者是数组,那么这就需要用到foreach标签,如下Sql语句:

SELECT * FROM USERS WHERE username LIKE '%王%' AND (id =10 OR id =89 OR id=16)SELECT * FROM USERS WHERE username LIKE '%王%'  id IN (10,89,16)

如上Sql所示,我们需要向Sql中传入一些列Id的值,集合或者是数组,接下来通过下面实例进一步了解:

在这里,我们可以将其分为:通过pojo传入list、传递单个list、传递单个数组(数组中包含pojo)、传递单个数组(数组中为字符串类型)

下面我们进行分别讲解:

通过pojo传递list

(1)定义pojo对象用于存放List(多个用户id)

package com.sw.po;import java.util.List;/* *@Author swxctx *@time 2016年12月2日 *@Explain:包装所需要的查询条件(亦可包装其他对象的查询信息)-包装类型 */public class UserQueryVo {//传入多个idprivate 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;}}

其他pojo:

package com.sw.po;/* *@Author swxctx *@time 2016年12月2日 *@Explain:User类的扩展类 */public class UserCustom extends User{//可以扩展用户的信息}

用户表的pojo对象这里不做介绍。

(2)配置mapper.xml文件

<!-- 用户信息的综合查询#{userCustom.sex}:取出pojo包装对象中sex的数据${userCustom.username}:取出包装对象中用户的名称 --><select id="findUserList" parameterType="com.sw.po.UserQueryVo" resultType="com.sw.po.UserCustom">select *from user<!-- where可以自动去掉条件中的第一个and --><where><!-- 使用动态sql,当输入参数不为空时才执行sql --><!-- 引用sql代码片段 --><include refid="query_user_where"/><if test="ids!=null"><!-- (id=27 OR id=32 OR id=34)使用foreah遍历传入的多个id(条件值)collection:指定输入对象中的集合属性item:每个遍历对象名open:开始遍历时需要拼接的字符串close:结束遍历时需要拼接的字符串separator:遍历的两个对象中间需要拼接的串 --><foreach collection="ids" item="user_id" open="and (" close=")" separator="or"><!-- 每个遍历需要拼接的串 -->id=#{user_id}</foreach></if></where></select>

(3)测试代码

package com.sw.mapper.test;import java.io.InputStream;import java.util.ArrayList;import java.util.Date;import java.util.List;import org.apache.ibatis.io.Resources;import org.apache.ibatis.session.SqlSession;import org.apache.ibatis.session.SqlSessionFactory;import org.apache.ibatis.session.SqlSessionFactoryBuilder;import org.junit.Before;import org.junit.Test;import com.sw.mapper.UserMapper;import com.sw.po.User;import com.sw.po.UserCustom;import com.sw.po.UserQueryVo;/* *@Author swxctx *@time 2016年12月1日 *@Explain: */public class UserMapperTest { private SqlSessionFactory sqlSessionFactory;@Beforepublic void setUpBefore() throws Exception {//执行其他方法前需要创建SqlSessionFactory// mybatis配置文件String resource = "SqlMapConfig.xml";// 得到配置文件流InputStream inputStream = Resources.getResourceAsStream(resource);// 创建会话工厂,传入mybatis的配置文件信息sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);}       //用户信息的综合查询    @Test    public void testFindUserList() throws Exception{        SqlSession sqlSession = sqlSessionFactory.openSession();        //创建UserMapper对象,mybatis自动生成mapper代理对象        UserMapper userMapper = sqlSession.getMapper(UserMapper.class);                //创建包装对象,设置查询条件        UserQueryVo userQueryVo = new UserQueryVo();        UserCustom userCustom = new UserCustom();                //传入多个id        List<Integer> ids = new ArrayList<Integer>();        ids.add(30);        ids.add(33);        ids.add(34);                userCustom.setSex("1");        userCustom.setUsername("王");        //将ids传入statement        userQueryVo.setIds(ids);        userQueryVo.setUserCustom(userCustom);                //调用UserMapper方法        List<UserCustom> list = userMapper.findUserList(userQueryVo);        sqlSession.close();                System.out.println(list);    }}

传递单个List

在上面通过pojo传递list的讲解中,我们知道,我们需要在pojo中定义List用于存放需要传递的值;但是在这里,则仅仅只是有这一点差别,传递单个List并不需要我们在pojo对象中对齐进行定义,只需要在mapper.xml中将collection的值设置为list即可。回顾一下,在上面的例子中,我们传入的是ids(即pojo对象中定义的List)。那么很显然的,他们的区别也就展现出来了,这里自己观察进行理解,即可掌握两种传递方式。

那么下面我们通过具体的例子来看一下:

(1)Mapper.xml文件配置

<select id="selectUserByList" parameterType="java.util.List" resultType="user">select * from user <where><!-- 传递List,List中是pojo --><if test="list!=null"><foreach collection="list" item="item" open="and id in("separator=","close=")">    #{item.id} </foreach></if></where></select>

(2)测试代码
Public void testselectUserByList()throws Exception{//获取sessionSqlSession session = sqlSessionFactory.openSession();//获取mapper接口实例UserMapper userMapper = session.getMapper(UserMapper.class);//查询条件ListList<User> userlist = new ArrayList<User>();User user = new User();user.setId(1);userlist.add(user);user = new User();user.setId(2);userlist.add(user); //传递userlist列表查询用户列表List<User>list = userMapper.selectUserByList(userlist);//释放资源session.close();}


传递单个数组

其实善于观察的同学可以发现,数组(array)与集合(List)其实在开发方式使一样的,只是在这里我们将多个传入的值定义为一个数组。

下面通过例子进行理解:

(1)mapper.xml配置文件的配置

<!-- 传递数组综合查询用户信息 --><select id="selectUserByArray" parameterType="Object[]" resultType="user">select * from user <where><!-- 传递数组 --><if test="array!=null"><foreach collection="array" index="index" item="item" open="and id in("separator=","close=")">    #{item.id} </foreach></if></where></select>

针对上面的一些标签做出说明:

sql只接收一个数组参数,这时sql解析参数的名称mybatis固定为array,如果数组是通过一个pojo传递到sql则参数的名称为pojo中的属性名。index:为数组的下标。item:为数组每个元素的名称,名称随意定义open:循环开始close:循环结束separator:中间分隔输出

(2)测试类

Public void testselectUserByArray()throws Exception{//获取sessionSqlSession session = sqlSessionFactory.openSession();//获取mapper接口实例UserMapper userMapper = session.getMapper(UserMapper.class);//查询条件ListObject[] userlist = new Object[2];User user = new User();user.setId(1);userlist[0]=user;user = new User();user.setId(2);userlist[1]=user;//传递user对象查询用户列表List<User>list = userMapper.selectUserByArray(userlist);//释放资源session.close();}

同样的,数组与List有着相似之处,现在的数组是直接传入的,那么同样也可以将其定义在pojo对象中,这里不做讲解,克通过上述三个例子对数组进行进一步的学习。

同时,这里有很多细节没有注意,例如定义mapper接口等,这里忽略了这些细节,旨在讲解foreach的配置。


如有雷同,纯属巧合,请多多指教。

0 0