[置顶] 【mybatis深度历险系列】mybatis中的动态sql

时间:2021-01-06 05:06:29

最近一直做项目,博文很长时间没有更新了,今天抽空,学习了一下mybatis,并且总结一下。在前面的博文中,小编主要简单的介绍了mybatis中的输入和输出映射,并且通过demo简单的介绍了输入映射和输出映射,今天这篇博文,小编主要来简单的介绍一下mybatis中的动态sql,有的小伙伴会问,既然有动态sql,那是不是也应该存在静态sql,答案是肯定的。那么什么是静态sql呢,静态sql语句一般用于嵌入式sql应用中,在程序运行之前,sql语句必须是确定的,例如sql语句中涉及的列名和表名必须是存在的,静态sql语句的编译是在应用程序运行前进行的,编译的结果会存储在数据库内容,而后程序进行时,数据库将直接执行编译好的sql语句,降低运行时的开销。所谓的动态sql,是在应用程序运行时被编译和执行的,例如使用DB2的交互式工具CLP访问数据库时,用户输入的sql语句是不确定的,因此sql语句只能被动态的编译,动态的sql的应用较多,常见的CLIJDBC应用程序都使用动态sql。这篇博文小编主要分三个部分来分别进行介绍,动态sqlsql片段和foreach

一、动态sql

1.1定义

mybatis核心对sql语句进行灵活操作,通过表达式进行判断,对sql进行灵活拼接,组装。

1.2案例需求

用户信息综合查询列表这个statment的定义使用动态sql,对查询条件进行判断,如果输入参数不为空进行查询拼接。

1.3UserMapper.xml

<!-- 用户信息综合查询 
#{userCustom.sex}:取出pojo包装对象中性别值
${userCustom.username}:取出pojo对象中用户名称
-->
<select id="findUserList" parameterType="com.mybatis.entity.UserQueryVo"
resultType="com.mybatis.entity.UserCustom">
select * from t_user
<!-- 动态sql查询:where可以自动去掉第一个and -->
<where>
<if test="userCustom!=null">
<if test="userCustom.sex!=null and userCustom.sex!='' ">
and sex=#{userCustom.sex}
</if>
<if test="userCustom.username!=null and userCustom.username!='' ">
and username=#{userCustom.username}
</if>
</if>
</where>
<!-- where sex=#{userCustom.sex} and username LIKE '%${userCustom.username}%' -->
</select>

1.4测试代码

@Test    public void testFindUserList() {        SqlSession sqlSession = sqlSessionFactory.openSession();        //创造查询条件        UserQueryVo userQueryVo = new UserQueryVo();        UserCustom userCustom = new UserCustom();//        userCustom.setSex("2");        //这里使用动态sql,如果不设置某个值,条件不会拼接sql中        userCustom.setUsername("小");        userQueryVo.setUserCustom(userCustom);        // 创建Usermapper对象,mybatis自动生成mapper代理对象        UserMapper mapper = sqlSession.getMapper(UserMapper.class);        List<UserCustom>list=mapper.findUserList(userQueryVo);        //测试动态sql,属性的非空判断测试//        List<UserCustom>list=mapper.findUserList(null);        System.out.println(list);        sqlSession.commit();        sqlSession.close();    }
二、sql片段

2.1需求

将上边的动态sql判断代码抽取出来,组成一个sql片段,其她的statment中就可以引用sql片段,方便开发。

2.2定义sql片段

<!-- 定义sql片段,Id是唯一标识         建议:是基于单表来定义sql片段,这样的话sql片段的可重用性才高,在sql片段中不要包含where     -->    <sql id="query_user_where" >        <if test="userCustom!=null">                <if test="userCustom.sex!=null and userCustom.sex!='' ">                    and sex=#{userCustom.sex}                </if>               <if test="userCustom.username!=null and userCustom.username!='' ">                    and username=#{userCustom.username}                </if>            </if>    </sql>
2.3mapper.xml中定义的statment中引用sql片段
<!-- 用户信息综合查询     #{userCustom.sex}:取出pojo包装对象中性别值    ${userCustom.username}:取出pojo对象中用户名称-->    <select id="findUserList" parameterType="com.mybatis.entity.UserQueryVo"     resultType="com.mybatis.entity.UserCustom">        select * from t_user         <!-- 动态sql查询:where可以自动去掉第一个and -->        <where>        <!-- 引用sql片段的id,如果refid指定的不在本mapper.xml中,需要前边加namespace -->            <include refid="query_user_where"></include>            <!-- 这里可以引用其它的sql片段 -->        </where>    </select>
三、foreach

作用:向sql传递数据或者listmybatis使用foreach解析,在用户查询列表和查询总数的statment中增加多个id输入查询。

3.1需求:sql语句如下,两种方法:

SELECT * FROM t_user WHERE id=1 OR id=10 OR id=16

SELECT * FROM t_user WHERE id IN(1,10,16)

3.2在输入参数包装类型中添加List<Integer>ids传入多个id

package com.mybatis.entity;import java.util.List;/** *  * @ClassName: UserQueryVo * @Description: TODO(包装类型) * @author 丁国华 *  */public class UserQueryVo {    public List<Integer> ids;    public List<Integer> getIds() {        return ids;    }    public void setIds(List<Integer> ids) {        this.ids = ids;    }}

3.3mapper.xml代码

<!-- 实现下边的sql拼接            select * from t_user where id=1 OR id=2 OR id=3    -->    <select id="findUserByIds" parameterType="com.mybatis.entity.UserQueryVo"     resultType="com.mybatis.entity.User">            select * from t_user        <where>                <if test="ids!=null">                <!-- 使用foreach遍历ids                    collection:指定输入对象的集合属性                    item:每个遍历生成对象中                    open:开始遍历时拼接的串                    close:技术遍历时拼接的串                    separator:遍历的两个对象中需要拼接的串                 -->                <foreach collection="ids" item="user_id" open="AND (" close=")" separator="or">                    id=#{user_id}                </foreach>            </if>        </where>    </select>

select *from t_user where id in(1,2,3)的mapper.xml配置

<select id="findUserByIds" parameterType="com.mybatis.entity.UserQueryVo"     resultType="com.mybatis.entity.User">            select * from t_user        <where>                <if test="ids!=null">                <!--                     使用foreach遍历ids                    collection:指定输入对象的集合属性                    item:每个遍历生成对象中                    open:开始遍历时拼接的串                    close:技术遍历时拼接的串                    separator:遍历的两个对象中需要拼接的串                 -->                <!-- 实现“ select * from t_user where  id in(1,2,3)”拼接 -->                <foreach collection="ids" item="user_id" open="AND id in ("  close=")" separator=",">                    id=#{user_id}                </foreach>            </if>        </where>    </select>userMapper.java代码 public interface UserMapper {    //ids查询用户数据     public List<User> findUserByIds(UserQueryVo userQueryVo); }
Junit测试代码

@Test public void findUserByIdsTest() { SqlSession sqlSession = sqlSessionFactory.openSession(); // 创建Usermapper对象,mybatis自动生成mapper代理对象 UserMapper mapper = sqlSession.getMapper(UserMapper.class); //创造查询条件 UserQueryVo userQueryVo = new UserQueryVo(); //传入多个id List<Integer> ids=new ArrayList<Integer>(); ids.add(1); ids.add(2); ids.add(3); //将ids通过userQueryVo传入statement中 userQueryVo.setIds(ids); //调用userMapper的代码 List<UserCustom> userList= mapper.findUserList(userQueryVo); System.out.println(userList); sqlSession.close(); }
小编寄语:该博文小编主要简单的介绍了mybatis中的动态sqlMyBatis的一个强大的特性之一通常是它的动态 SQL 能力。如果你有使用 JDBC 或其他相似框架的经验,你就明白条件地串联 SQL字符串在一起是多么的痛苦,确保不能忘了空 格或在列表的最后省略逗号。动态 SQL可以彻底处理这种痛苦。通常使用动态SQL不可能是独立的一部分,MyBatis当然使用一种强大的动态SQL语言来改进这种情形,这种语言可以被用在任意映射的SQL语句中。

动态SQL元素和使用JSTL或其他相似的基于XML的文本处理器相似。在MyBatis之前的版本中,有很多的元素需要来了解。MyBatis3大大提升了它们,现在用不到原先一半的元素就能工作了。MyBatis采用功能强大的基于OGNL的表达式来消除其他元素。 小编博文,小编将继续介绍mybatis的相关知识,敬请期待`(*_*)