zoukankan      html  css  js  c++  java
  • MyBatis-DynamicSQL 动态SQL

    MyBatis 的动态 SQL 使用 OGNL 表达式

    http://commons.apache.org/proper/commons-ognl/language-guide.html

    在 XML 中的一些特殊字符需要转义,参考 HTML ISO-8859-1 手册

    http://www.w3school.com.cn/tags/html_ref_entities.html

    一、IF

    https://www.cnblogs.com/jhxxb/p/10637219.html

    <select id="selectMyUserByIF" resultType="myUser" parameterType="myUser">
        select * from myuser where
        <if test="id != null">
          id = #{id}
        </if>
        <if test="name != null &amp;&amp; name != &quot;&quot;">
          and name like #{name}
        </if>
        <if test="age == 0 or age == 1">
          and age = #{age}
        </if>
    </select>

    入参没有ID属性时会报错,会拼接成 where and,解决:可以在 where 后添加一个恒成立,如 1=1。或者使用 where 标签,会自动去除 SQL 中多出来的 and 或 or

     

    二、WHERE

    <select id="selectMyUserByIF" resultType="myUser" parameterType="myUser">
        select * from myuser
        <where>
            <if test="id != null">
              id = #{id}
            </if>
            <if test="name != null and name != ''.toString()">
              and name like #{name}
            </if>
            <if test="age == 0 or age == 1">
              and age = #{age}
            </if>
        </where>
    </select>

    where 标签只能去除第一个 and 或 or,所以不能把条件符号写多个或写在后面

     

    三、SET

    <update id="updateMyUser" parameterType="myUser">
        update myuser
        <!-- 用作更新 -->
        <set>
            <if test="name != null">
              name = #{name},
            </if>
            <if test="age != null">
              age = #{age}
            </if>
        </set>
        where id = #{id}
    </update>

     

    四、TRIM

    <select id="selectMyUserByIF" resultType="myUser" parameterType="myUser">
        select * from myuser
        <!-- prefix:替换拼接后字符串的前缀,单独使用则为添加。prefixOverrides:想替换的前缀类容(条件),单独使用则为删除
            suffix:替换拼接后字符串的后缀,单独使用则为添加。suffixOverrides:想替换的后缀类容(条件),单独使用则为删除 -->
        <trim prefix="where" prefixOverrides="AND | OR" suffixOverrides="and">
            <if test="id != null">
                id = #{id} and
            </if>
            <if test="name != null and name.trim() != ''">
                name like #{name}
            </if>
        </trim>
    </select>

    trim 标签可以替代 where 标签

    <!-- 等效于 where 标签 -->
    <trim prefix="WHERE" prefixOverrides="AND |OR ">
        ...
    </trim>

    trim 标签也可以替代 set 标签

    <!-- 等效于 set 标签 -->
    <trim prefix="set" suffixOverrides=",">
      ...
    </trim>

     

    五、CHOOSE

    <select id="selectMyUserByIF" resultType="myUser" parameterType="myUser">
        select * from myuser
        <where>
            <!-- 类似于 if-else if-else 分支结构 -->
            <choose>
                <when test="id != null">
                  id = #{id}
                </when>
                <when test="name != null and name.trim() != ''">
                  name like #{name}
                </when>
                <otherwise>
                  age = 22
                </otherwise>
            </choose>
        </where>
    </select>

     

    六、FOREACH

    Map 入参

    <!--public List<MyUser> selectMyUserByArray(Map<String,Object> maps);-->
    <select id="selectMyUserByArray" resultType="myUser">
        select * from myuser where id in
        <!-- collection:指定要遍历的集合或数组(list 和 array 参数都会特殊处理封装在 Map 中,Map 的 key 默认为 list 或 array)
                入参为单个 list 或 array 时 collection 值默认为 list 或 array,若接口方法指定了 @Param 注解,则为 @Param 的值
                入参为多个参数可以封装为 Map,collection 值为 Map 中集合或数组对应的 key 的值(Map 的 key 最好为 String 类型)
            open:给结果拼接一个前缀
            close:给结果拼接一个后缀
            item:集合中每一个元素在迭代时的别名,#{item} 取出变量的值,也就是当前遍历出的元素
            separator:每个元素之间的分隔符
            index:索引
                遍历 list 或 arrays 时,index 是当前索引(下标),item 为索引对应的值
                遍历 map 时 index 表示 map 的 key,item 为 map 的 value -->
        <foreach collection="ids" item="item" index="index" separator="," open="(" close=")">
            #{item}
        </foreach>
    </select>

    测试代码

    public static void main(String[] args) {
        SqlSession session = null;
        try {
            InputStream inputStream = Resources.getResourceAsStream("mybatis-config.xml");
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
            session = sqlSessionFactory.openSession();
    
            MyUserMapper mapper = session.getMapper(MyUserMapper.class);
            Map<String,Object> ids = new HashMap<>(10);
            ids.put("ids",Arrays.asList(7,8,9,10));
            ids.put("b",8);
            System.out.println(mapper.selectMyUserByArray(ids));
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (session != null) {
                session.close();
            }
        }
    }

    List 入参

    <!--public List<MyUser> selectMyUserByArray(List<Integer> ids);-->
    <select id="selectMyUserByArray" resultType="myUser">
        select * from myuser where id in
        <foreach collection="list" item="item" index="index" separator="," open="(" close=")">
          #{item}
        </foreach>
    </select>

    Array 入参

    <!--public List<MyUser> selectMyUserByArray(Integer[] ids);-->
    <select id="selectMyUserByArray" resultType="myUser">
        select * from myuser
        <foreach collection="array" item="item" index="index" separator="," open="where id in (" close=",20)">
          #{item}
        </foreach>
    </select>

     

     

    七、内置参数

    <!-- 不只是方法传递过来的参数可以被用来判断和取值,mybatis 默认还有两个内置参数。
            _parameter:代表整个参数
                单个参数:_parameter 就是这个参数
                多个参数:参数会被封装为一个 map,_parameter 就代表这个 map
            _databaseId:如果配置了 databaseIdProvider 标签,_databaseId 代表当前数据库的别名 -->
    <select id="selectMyUserById" resultType="myUser">
        <if test="_databaseId == 'mysql'">
            select * from myuser
            <if test="_parameter != null">
                where id = #{_parameter}
            </if>
        </if>
        <if test="_databaseId == 'oracle'">
            select * from oracle_myuser
            <if test="_parameter != null">
                where name = #{_parameter.name}
            </if>
        </if>
    </select>

     

    八、BIND

    <select id="selectMyUserByNameLike" resultType="myUser" parameterType="string">
        select * from myuser where name like #{name}
    </select>

    例 SQL 映射想变为模糊查询有几种方式

    1.传入参数时加上 %

    2.改用 ${name} 来取值。name 取值会报错,用 _parameter 取值

    <select id="selectMyUserByNameLike" resultType="myUser">
        select * from myuser where name like '%${_parameter}%'
    </select>

    3.使用 bind 标签

    <select id="selectMyUserByNameLike" resultType="myUser">
      <!-- bind:可以将OGNL表达式的值绑定到一个变量中,方便后来引用这个变量的值 -->
        <bind name="_name" value="'%'+_parameter+'%'"/>
        select * from myuser where name like #{_name}
    </select>

     

    九、SQL 复用

    <!-- 抽取可重用的sql片段。方便后面引用,使用 include 标签来引用已经抽取的 sql
        include 中可以自定义一些 property,sql 标签内部就能使用自定义的属性
        include-property:取值用 ${prop}, 使用 #{prop} 不能取出,无法预编译 -->
    <sql id="columnNames">
        <if test="_databaseId=='mysql'">
            ${id},name,age
        </if>
        <if test="_databaseId=='oracle'">
            xxx,xxx,xxx
        </if>
    </sql>
    <select id="selectMyUserByNameLike" resultType="myUser" parameterType="string">
        select
        <include refid="columnNames">
          <property name="id" value="id"/>
        </include>
        from myuser where name like #{name}
    </select>

    可以使用其他语言来写动态 SQL:MyBatis-Velocity、MyBatis-FreeMarker 和自带的 XML

    http://www.mybatis.org/velocity-scripting/

    http://www.mybatis.org/freemarker-scripting/

    https://www.jianshu.com/p/cecc187410be

    MyBatis 动态 SQL 文档

  • 相关阅读:
    (二分查找 拓展) leetcode 69. Sqrt(x)
    (二分查找 拓展) leetcode 162. Find Peak Element && lintcode 75. Find Peak Element
    (链表) lintcode 219. Insert Node in Sorted Linked List
    (二分查找 拓展) leetcode 34. Find First and Last Position of Element in Sorted Array && lintcode 61. Search for a Range
    (最短路 Floyd) P2910 [USACO08OPEN]寻宝之路Clear And Present Danger 洛谷
    (字符串 数组 递归 双指针) leetcode 344. Reverse String
    (二叉树 DFS 递归) leetcode 112. Path Sum
    (二叉树 DFS 递归) leetcode 101. Symmetric Tree
    (二叉树 递归) leetcode 144. Binary Tree Preorder Traversal
    (二叉树 递归 DFS) leetcode 100. Same Tree
  • 原文地址:https://www.cnblogs.com/jhxxb/p/10493844.html
Copyright © 2011-2022 走看看