动态SQL和SQL片段

88 阅读2分钟

简介

  1. 动态SQL就是根据不同的条件生成不同的SQL语句
  2. 本质上还是SQL语句
  3. 其实也是实现SQL语句的拼接。
  4. 动态SQL包括:
if
choose (when, otherwise)
trim (where, set)
foreach

案例分析动态SQL

我们现在有一个Blog的数据库,数据库里面有以下这些信息

image.png

我们现在要使用动态SQL对这个数据库进行操作!

前期的准备工作:

  1. 创建一个项目,构建好项目结构

image.png

  1. 搭配环境

常用的资源:db.properties log4j.properties mybatis-config.xml MybatisUtils(工具类)

配置pom.xml,引入需要的依赖,比如说lomboklog4j

image.png

  1. 实体类Blog:

image.png

解决方法:根据MyBatis的中文文档找到,可以在mybatis-config.xml中通过settingmapUnderscoreToCamelCase设置为true

image.png

mybatis-config.xml的内容:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
        PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
        "http://mybatis.org/dtd/mybatis-3-config.dtd">

<!--configuration核心配置文件-->
<configuration>
    <properties resource="db.properties"/>

    <settings>
        <setting name="logImpl" value="Log4j"/>
        <setting name="mapUnderscoreToCamelCase" value="true"/>
    </settings>

    <typeAliases>
        <typeAlias type="com.wu.pojo.blog" alias="blog"/>
    </typeAliases>


    <environments default="development">
        <environment id="development">
            <transactionManager type="JDBC"/>
            <dataSource type="POOLED">
                <property name="driver" value="${driver}"/>
                <property name="url" value="${url}"/>
                <property name="username" value="${username}"/>
                <property name="password" value="${password}"/>
            </dataSource>
        </environment>
    </environments>

    <mappers>
        <mapper resource="com/wu/dao/BlogMapper.xml"/>
    </mappers>

</configuration>

  1. 写BlogMapper接口和BlogMapper接口的配置文件(BlogMapper.xml)
  2. 测试

其中这里编写的 4 和 5 就可以让我们来体验一下动态SQL

if where

BlogMapper接口

    List<blog> queryBlogIF(Map map);

BlogMapper.xml

    <select id="queryBlogIF" parameterType="map" resultType="blog">
        select * from mybatis.blog
        <where>
            <if test="title != null">
                and title = #{title}
            </if>
            <if test="author != null">
                and author = #{author}
            </if>
        </where>
    </select>

注意: image.png

细心的人应该也发现了,这里除了if标签,我还用了where标签,这是为什么呢?

很简单,在上面的动态SQL中,主要有一下这几种情行:

  1. title==null author==null 对应的SQL语句:select * from mybatis.blog 没有where
  2. title!=null author==null 对应的SQL语句:select * from mybatis.blog where title=#{title} 有where 没有and
  3. title==null author!=null 对应的SQL语句:select * from mybatis.blog where author=#{author} 有where 没有and
  4. title!=null author!=null 对应的SQL语句:select * from mybatis.blog where title=#{title} and author=#{author} 有where 有and ----> where标签就是用来处理第一种情况,即没有where的情况。

----> if标签就是用来处理2 3 4的情况,连接where之后的语句。

foreach

BlogMapper接口

    List<blog> queryBlogForEach(Map map);

BlogMapper.xml

    <select id="queryBlogForEach" resultType="blog" parameterType="map">
        select * from mybatis.blog
        <where>
            <foreach collection="ids" item="id" open="(" close=")" separator="or">
                id = #{id}
            </foreach>
        </where>

    </select>

image.png 测试文件:

        Map map = new HashMap();
        ArrayList<Integer> ids = new ArrayList<Integer>();
        ids.add(1);
        ids.add(2);
        map.put("ids",ids);

        List<blog> blogs = mapper.queryBlogForEach(map);

        for (blog blog : blogs) {
            System.out.println(blog);
        }

使用动态SQL查询,拼接后SQL语句:

image.png

在这里,我只介绍了if where`` foreach,因为这些比较重要,其他的可以在mybatis官网上自学,方法类似。

SQL片段

SQL片段就是提取相同功能的SQL语句,然后通过inclde语句来引用。就拿上面的if案例来说,

    <if test="title!=null">
        title = #{title}
    </if>
    <if test="author!=null">
        and author = #{author}
    </if>

在很多地方用的到,我们就可以先提取出来,然后在通过include引用。

  1. 在mapper.xml文件中使用<sql></sql>进行提取:
<sql id="ifsql">
    <if test="title!=null">
        title = #{title}
    </if>
    <if test="author!=null">
        and author = #{author}
    </if>
</sql>
  1. 在mapper.xml文件中使用<sql></sql>进行引用:
 <select id="queryBlogIF" parameterType="map" resultType="blog">
        select * from mybatis.blog
        <where>
            <include refid="ifsql"></include>
        </where>
 </select>
  1. 查询结果:

image.png

注意事项:

  1. 最好基于单表来定义SQL片段,连表查询不建议使用SQL片段。
  2. 不要存在where标签。