写点什么

MyBatis- 技术专题 - 动态 SQL

发布于: 2020 年 10 月 23 日
MyBatis-技术专题-动态SQL

在讲 MyBatis 动态 SQL 之前,先教大家怎么通过 MyBatis 插件自动生成 mapper 对应的文件和对应的 bean 文件。使用起来非常简单。

       第一步,在 pom.xml 文件里面添加 plugin。这里要注意 configurationFile 部分这个字段指明 generatorConfig.xml 文件的位置。generatorConfig.xml 在第二步会教大家怎么配置。这里我们指定的目录是 resources/generator 文件夹下面,大家根据自己的实际情况来指定。

            <plugin>                <groupId>org.mybatis.generator</groupId>                <artifactId>mybatis-generator-maven-plugin</artifactId>                <version>1.3.2</version>                <dependencies>                    <dependency>                        <groupId>mysql</groupId>                        <artifactId>mysql-connector-java</artifactId>                        <version>5.1.35</version>                    </dependency>                </dependencies>                <configuration>                    <!--配置文件的路径-->                    <configurationFile>${basedir}/src/main/resources/generatorConfig.xml</configurationFile>                    <overwrite>true</overwrite>                </configuration>            </plugin>
复制代码

       第二步,generatorConfig.xml 文件的配置,主要改的地方就是 jdbcConnection 字段里面数据库相关的信息。以及 javaModelGenerator,sqlMapGenerator,javaClientGenerator 字段目标文件的位置。和 table 字段里面改成自己的表格。关于这些东西 generatorConfig.xml 文件里面咱们也注释的很清楚。

<?xml version="1.0" encoding="UTF-8"?><!DOCTYPE generatorConfiguration        PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"        "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd"><generatorConfiguration>    <!--执行命令 mvn mybatis-generator:generate-->    <context id="test" targetRuntime="MyBatis3">        <plugin type="org.mybatis.generator.plugins.EqualsHashCodePlugin"></plugin>        <plugin type="org.mybatis.generator.plugins.SerializablePlugin"></plugin>        <plugin type="org.mybatis.generator.plugins.ToStringPlugin"></plugin>        <commentGenerator>            <!-- 这个元素用来去除指定生成的注释中是否包含生成的日期 false:表示保护 -->            <!-- 如果生成日期,会造成即使修改一个字段,整个实体类所有属性都会发生变化,不利于版本控制,所以设置为true -->            <property name="suppressDate" value="true"/>            <!-- 是否去除自动生成的注释 true:是 : false:否 -->            <property name="suppressAllComments" value="false"/>        </commentGenerator>        <!--数据库链接URL,用户名、密码 -->        <jdbcConnection driverClass="com.mysql.jdbc.Driver"                        connectionURL="jdbc:mysql://192.168.13.98/dcim" userId="root" password="123456">        </jdbcConnection>        <javaTypeResolver>            <!-- This property is used to specify whether MyBatis Generator should                force the use of java.math.BigDecimal for DECIMAL and NUMERIC fields, -->            <property name="forceBigDecimals" value="false"/>        </javaTypeResolver>        <!-- 生成模型的包名和位置 -->        <javaModelGenerator targetPackage="com.pilot.dcim.alarmmanage.entity.model"                            targetProject="src/main/java">            <property name="enableSubPackages" value="true"/>            <property name="trimStrings" value="true"/>        </javaModelGenerator>        <!-- 生成映射文件的包名和位置 -->        <sqlMapGenerator targetPackage="com.pilot.dcim.alarmmanage.mapper"                         targetProject="src/main/resources">            <property name="enableSubPackages" value="true"/>        </sqlMapGenerator>        <!-- 生成DAO的包名和位置 -->        <javaClientGenerator type="XMLMAPPER"                             targetPackage="com.pilot.dcim.alarmmanage.mapper"                             implementationPackage="com.pilot.dcim.alarmmanage.service.impl"                             targetProject="src/main/java">            <property name="enableSubPackages" value="true"/>        </javaClientGenerator>
<!-- 要生成哪些表 --> <table tableName="alarmgroup" domainObjectName="AlarmGroup" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"></table> <table tableName="alarmparam" domainObjectName="AlarmParam" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"></table> <table tableName="alarmsetting" domainObjectName="AlarmSetting" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"></table> <table tableName="faultevent" domainObjectName="FaultEvent" enableCountByExample="false" enableUpdateByExample="false" enableDeleteByExample="false" enableSelectByExample="false" selectByExampleQueryId="false"></table> </context> </generatorConfiguration>
复制代码

       第三步,上面两部都配置好之后,执行命令 mvn mybatis-generator:generate 就会在对应的目录下生成我们想要的文件。


       MyBatis 的动态 SQL 是基于 OGNL 的表达式的。它对 SQL 语句进行灵活的操作。通过表达式判断来实现对 SQL 灵活拼接、组装。我们着重讲说 MyBatis 动态 SQL 里面一些元素的使用。

一、MyBatis 动态 SQL 标签的学习

1.1、if 条件判断标签

       if 标签通用用于通过判断参数值来决定是否使用某个查询条件。

1.1.1、if 判断数字

       if 判断数字,大部分都是判断等于或者不等于某个数字。

<if test="filter == 1">    ...</if>
复制代码

1.1.2、if 判断字符串

       大部分情况下都是去判断传递过来的字符串是否为空。当然咱们也是可以添加别的条件限制的,比如以啥字符串开头,以啥字符串结尾。

1.1.2.1、判断字符串是否为空,或者字符串等于某个值

    <select id="selectUser" resultType="com.tuacy.mybatisdemo.model.User">        select * from user        <where>            <if test="user.name != null and user.name == '0'.toString()">                and name = #{user.name}            </if>        </where>    </select>
复制代码

1.1.2.2、判断字符串是否包含

    <select id="selectUser" resultType="com.tuacy.mybatisdemo.model.User">        select * from user        <where>            <if test=" user.name != null and user.name.contains('1'.toString())">                and name = #{user.name}            </if>        </where>    </select>
复制代码

1.1.2.3、判断是否以字符串开头

    <select id="selectUser" resultType="com.tuacy.mybatisdemo.model.User">        select * from user        <where>            <if test=" user.name != null and user.name.startsWith('1'.toString())">                and name = #{user.name}            </if>        </where>    </select>
复制代码

1.1.3、判断列表

       经常判断列表是否为 null,或者列表是否为空。列表判断也是很简单的直接 <if test=" nameList != null and nameList.size() > 0 "> 就搞定了。

一个简单的实例,通过用户名(list)查询用户

    List<User> selectUserByName(@Param("nameList") List<String> nameList);
复制代码


    <!-- 通过用户名查找用户 -->    <select id="selectUserByName" resultType="com.tuacy.mybatisdemo.model.User">        select * from user        <where>            <if test=" nameList != null and nameList.size() > 0 ">                <trim prefix=" name in ">                    <foreach collection="nameList" item="i" index="index" open="(" separator="," close=")">                        <if test="i != null">                            #{i}                        </if>                    </foreach>                </trim>            </if>        </where>    </select>
复制代码

1.2、choose,when,otherwise 标签(switch case)

        choose,when,otherwise 标签的作用类似与咱们 java 里面的 switch case 的作用。

<choose>    <when test="item.name != null">        #{item.name,jdbcType=VARCHAR},    </when>    <otherwise>        null,    </otherwise></choose>
复制代码

1.3、foreach 循环标签

       foreach 的主要用在构建 in 条件中,可以在 SQL 语句中进行迭代一个集合。大部分是对 list 进行循环。

       foreach 元素的属性主要有 item,index,collection,open,separator,close。

  在使用 foreach 的时候最关键的也是最容易出错的就是 collection 属性,该属性是必须指定的,但是在不同情况 下,该属性的值是不一样的,主要有一下 3 种情况:

  • 如果传入的是单参数且参数类型是一个 List 的时候,collection 属性值为 list。

  • 如果传入的是单参数且参数类型是一个 array 数组的时候,collection 的属性值为 array。

  • 如果传入的参数是多个的时候,我们就需要把它们封装成一个 Map 了,当然单参数也可以。

<select id="dynamicForeachTest" parameterType="java.util.List" resultType="Blog">          select * from t_blog where id in        <foreach collection="list" index="index" item="item" open="(" separator="," close=")">                #{item}               </foreach>    </select>
复制代码

array

<select id="dynamicForeach2Test" parameterType="java.util.ArrayList" resultType="Blog">     select * from t_blog where id in     <foreach collection="array" index="index" item="item" open="(" separator="," close=")">          #{item}     </foreach></select>   
复制代码

map

<select id="dynamicForeach3Test" parameterType="java.util.HashMap" resultType="Blog">         select * from t_blog where title like "%"#{title}"%" and id in          <foreach collection="ids" index="index" item="item" open="(" separator="," close=")">               #{item}          </foreach> </select>
复制代码

上面说的都是没有指定 @Param 的情况,如果指定了 @Param 则 collection 的属性值是 @Param 指定的名字。

1.4、trim 标签

trim 标记是一个格式化的标记,可以完成 set 或者是 where 标记的功能。


<trim prefix="WHERE" prefixOverrides="AND">    <if test="state != null">      state = #{state}    </if>     <if test="title != null">      AND title like #{title}    </if>    <if test="author != null and author.name != null">      AND author_name like #{author.name}    </if></trim>
复制代码

1.5、where 标签

    where 标签是非常有用的,他有两个作用:

  • 当 where 标签里面元素的元素都不满足条件的时候,不会插入 where 语句。

  • where 标签里面若语句的开头为“AND”或“OR”,where 元素也会将它们去除。

    <!-- 查找指定的用户 --><select id="selectUser" resultType="com.tuacy.mybatisdemo.model.User">        select * from user        <where>            <if test="user.pkid != null">                pkid = #{user.pkid}            </if>            <if test="user.name != null">                and name = #{user.name}            </if>            <if test="user.phone != null">                and phone = #{user.phone}            </if>            <if test="user.password != null">                and password = #{user.password}            </if>        </where></select>
复制代码

1.6、set 标签

       set 标签和 where 标签一样。会自动加上 set 关键字,并且去掉不必要的一些字符。

<set>       <if test="userId !=null and userId !=''">            A.userId = #{userId,jdbcType=CHAR},      </if>        <if test="userName !=null and userName !=''">            A.userName = #{userName,jdbcType=CHAR}        </if>   </set> 
复制代码

1.7、bind 标签

       bind 标签可以使用 OGNL 表达式创建一个变量井将其绑定到上下文中。咱就可以简单的认为是声明了一个变量。

这个例子里面,我纯粹的是把 user.name 替换成了 user.name 了。

    <select id="selectUser" resultType="com.tuacy.mybatisdemo.model.User">        select * from user        <where>            <bind name="userName" value="user.name"/>            <if test=" userName != null ">                and name = #{userName}            </if>        </where>    </select>
复制代码

这例子里面咱用 bind 标签声明了一个模糊查询的变量

    <select id="selectUser" resultType="com.tuacy.mybatisdemo.model.User">        select * from user        <where>            <bind name="patternName" value="'%' + user.name + '%'" />            <if test=" user.name != null ">                and name like #{patternName}            </if>        </where>    </select>
复制代码

二、MyBatis 动态 SQL 实例

       最后我们根据今天所学到的内容,给出两个比较复杂的 MyBats 动态 SQL。

2.1、批量插入并且更新主键

    <!-- 批量插入并且更新主键 -->    <insert id="insertUserBatch" parameterType="java.util.List" useGeneratedKeys="true" keyProperty="pkid">        insert into user (name, password, phone)        values        <foreach collection="list" item="item" index="index" separator=",">            <trim prefix="(" suffix=")" suffixOverrides=",">                <choose>                    <when test="item.name != null">                        #{item.name,jdbcType=VARCHAR},                    </when>                    <otherwise>                        null,                    </otherwise>                </choose>                <choose>                    <when test="item.password != null">                        #{item.password,jdbcType=VARCHAR},                    </when>                    <otherwise>                        null,                    </otherwise>                </choose>                <choose>                    <when test="item.phone != null">                        #{item.phone,jdbcType=VARCHAR},                    </when>                    <otherwise>                        null,                    </otherwise>                </choose>            </trim>        </foreach>    </insert>
复制代码

2.2、批量更新

   <!-- 批量更新 -->    <update id="updateUserBatch" parameterType="java.util.List">        update user        <trim prefix="set" suffixOverrides=",">            <trim prefix="name =case" suffix="end,">                <foreach collection="list" item="i" index="index">                    <if test="i.name!=null">                        when pkid=#{i.pkid} then #{i.name}                    </if>                </foreach>            </trim>            <trim prefix=" password =case" suffix="end,">                <foreach collection="list" item="i" index="index">                    <if test="i.password!=null">                        when pkid=#{i.pkid} then #{i.password}                    </if>                </foreach>            </trim>            <trim prefix="phone =case" suffix="end,">                <foreach collection="list" item="i" index="index">                    <if test="i.phone!=null">                        when pkid=#{i.pkid} then #{i.phone}                    </if>                </foreach>            </trim>        </trim>        where        <foreach collection="list" separator="or" item="i" index="index">            pkid=#{i.pkid}        </foreach>    </update>
复制代码


用户头像

我们始于迷惘,终于更高的迷惘。 2020.03.25 加入

一个酷爱计算机技术、健身运动、悬疑推理的极客狂人,大力推荐安利Java官方文档:https://docs.oracle.com/javase/specs/index.html

评论

发布
暂无评论
MyBatis-技术专题-动态SQL