zoukankan      html  css  js  c++  java
  • mybatis学习(九)——动态sql

    MyBatis 的强大特性之一便是它的动态 SQL。可以根据不同条件拼接 SQL 语句。

    动态 SQL 元素和使用 JSTL 或其他类似基于 XML 的文本处理器相似。主要由以下几种元素。

    • if
    • where
    • trim 
    • choose (when, otherwise)
    • set
    • foreach
    • bind

    1、if  (判断)

    实例:根据条件查询酒店列表

    hotelMapper接口

    package com.pjf.mybatis.dao;
    
    import java.util.List;
    import com.pjf.mybatis.po.Hotel; public interface HotelMapper { public List<Hotel> getHotel(Hotel hotel); }

    hotelMapper.xml

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
    <mapper namespace="com.pjf.mybatis.dao.HotelMapper">
    
        <resultMap type="com.pjf.mybatis.po.Hotel" id="myHotel">
            <id column="id" property="id" jdbcType="INTEGER" />
            <result column="hotel_name" property="hotelName" jdbcType="VARCHAR" />
            <result column="hotel_address" property="hotelAddress"
                jdbcType="VARCHAR" />
            <result column="price" property="price" jdbcType="INTEGER" />
        </resultMap>
    
        <!-- resultMap使用 -->
        <select id="getHotel" resultMap="myHotel">
            select*
            from hotel
            where
                <if test="id!=null">
                    id=#{id} 
                </if>
                <if test="hotelName!=null &amp;&amp; hotelName!=&quot;&quot;">
                    and hotel_name like concat('%',#{hotelName},'%') 
                </if>
                <if test="price!=null">
                    and price> #{price}
                </if>
        </select>
    </mapper>

    测试类

    package com.pjf.mybatis;
    
    import java.io.IOException;
    import java.io.InputStream;
    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.Test;
    
    import com.pjf.mybatis.dao.HotelMapper;import com.pjf.mybatis.po.Hotel;
    
    public class TestHotel {
    
        public SqlSessionFactory sqlSessionFactory() throws IOException {
            // mybatis的配置文件
            String resource = "mybatis_config.xml";
            // 使用类加载器加载mybatis的配置文件(它也加载关联的映射文件)TestHotel.class.getClassLoader()
            InputStream is = Resources.getResourceAsStream(resource);
            // 构建sqlSession的工厂
            SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(is);
            return sessionFactory;
        }
    
        @Test
        public void getHotel() throws IOException {
    
            SqlSessionFactory sessionFactory = sqlSessionFactory();
            SqlSession session = sessionFactory.openSession();
            HotelMapper hotelMapper = session.getMapper(HotelMapper.class);
            System.out.println(hotelMapper.getClass());
            Hotel hotel = new Hotel(1001, "南京", "", 800);
            List<Hotel> list = hotelMapper.getHotel(hotel);
            for (Hotel hotel1 : list) {
                System.out.println(hotel1);
            }
            session.close();
        }
    }

    查看结果

    需要注意的是特殊字符需要转义,

    <if test="hotelName!=null &amp;&amp; hotelName!=&quot;&quot;">

    常用的有以下字符

    2、where

    对于上面的查询条件,如果在测试类中

    Hotel hotel = new Hotel(1001, "南京", "", 800);改成 Hotel hotel = new Hotel(null,"南京","", 800);
    结果会怎么样

     

    sql多了一个and

    解决:

    a、增加默认条件1=1

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
    <mapper namespace="com.pjf.mybatis.dao.HotelMapper">
    
        <resultMap type="com.pjf.mybatis.po.Hotel" id="myHotel">
            <id column="id" property="id" jdbcType="INTEGER" />
            <result column="hotel_name" property="hotelName" jdbcType="VARCHAR" />
            <result column="hotel_address" property="hotelAddress"
                jdbcType="VARCHAR" />
            <result column="price" property="price" jdbcType="INTEGER" />
        </resultMap>
    
        <!-- resultMap使用 -->
        <select id="getHotel" resultMap="myHotel">
            select*
            from hotel
            where 1=1
                <if test="id!=null">
                    id=#{id} 
                </if>
                <if test="hotelName!=null &amp;&amp; hotelName!=&quot;&quot;">
                    and hotel_name like concat('%',#{hotelName},'%') 
                </if>
                <if test="price!=null">
                    and price> #{price}
                </if>
        </select>
    </mapper>

     结果

    b、增加where元素

     将所有的元素放在where标签内,where元素会自动去除首位的and或or。注意是首位的and或者or。

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
    <mapper namespace="com.pjf.mybatis.dao.HotelMapper">
    
        <resultMap type="com.pjf.mybatis.po.Hotel" id="myHotel">
            <id column="id" property="id" jdbcType="INTEGER" />
            <result column="hotel_name" property="hotelName" jdbcType="VARCHAR" />
            <result column="hotel_address" property="hotelAddress"
                jdbcType="VARCHAR" />
            <result column="price" property="price" jdbcType="INTEGER" />
        </resultMap>
    
        <!-- resultMap使用 -->
        <select id="getHotel" resultMap="myHotel">
            select*
            from hotel
            <where>
                <if test="id!=null">
                    id=#{id}
                </if>
                <if test="hotelName!=null &amp;&amp; hotelName!=&quot;&quot;">
                    and hotel_name like concat('%',#{hotelName},'%')
                </if>
                <if test="price!=null">
                    and price> #{price}
                </if>
            </where>
        </select>
    </mapper>

    3、trim  (字符串截取)

    如果and写在语句的末尾,该怎么解决呢

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
    <mapper namespace="com.pjf.mybatis.dao.HotelMapper">
    
        <resultMap type="com.pjf.mybatis.po.Hotel" id="myHotel">
            <id column="id" property="id" jdbcType="INTEGER" />
            <result column="hotel_name" property="hotelName" jdbcType="VARCHAR" />
            <result column="hotel_address" property="hotelAddress"
                jdbcType="VARCHAR" />
            <result column="price" property="price" jdbcType="INTEGER" />
        </resultMap>
    
        <!-- resultMap使用 -->
        <select id="getHotel" resultMap="myHotel">
            select*
            from hotel
            <where>
                <if test="id!=null">
                    id=#{id} and
                </if>
                <if test="hotelName!=null &amp;&amp; hotelName!=&quot;&quot;">
                     hotel_name like concat('%',#{hotelName},'%') and
                </if>
                <if test="price!=null">
                     price> #{price}
                </if>
            </where>
        </select>
    </mapper>

    测试类

    package com.pjf.mybatis;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.List;
    import java.util.Map;
    
    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.Test;
    
    import com.pjf.mybatis.dao.HotelMapper;
    import com.pjf.mybatis.po.City;
    import com.pjf.mybatis.po.Hotel;
    
    public class TestHotel {
    
        public SqlSessionFactory sqlSessionFactory() throws IOException {
            // mybatis的配置文件
            String resource = "mybatis_config.xml";
            // 使用类加载器加载mybatis的配置文件(它也加载关联的映射文件)TestHotel.class.getClassLoader()
            InputStream is = Resources.getResourceAsStream(resource);
            // 构建sqlSession的工厂
            SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(is);
            return sessionFactory;
        }
    
        @Test
        public void getHotel() throws IOException {
    
            SqlSessionFactory sessionFactory = sqlSessionFactory();
            SqlSession session = sessionFactory.openSession();
            HotelMapper hotelMapper = session.getMapper(HotelMapper.class);
            Hotel hotel = new Hotel(1001,"南京","",null);
            System.out.println(hotel);
            List<Hotel> list = hotelMapper.getHotel(hotel);
            for (Hotel hotel1 : list) {
                System.out.println(hotel1);
            }
            session.close();
        }
    }

    结果:末尾就会多一个and

    这时候就可以通过trim标签来解决:

     trim 对trim标签体中拼接后的字符串进行操作

       prefix       对拼接后的字符串加前缀
       prefixOverrides   对拼接后的字符串去前缀
       suffix  对拼接后的字符串加后缀
       suffixOverrides   对拼接后的字符串去后缀
    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
    <mapper namespace="com.pjf.mybatis.dao.HotelMapper">
    
        <resultMap type="com.pjf.mybatis.po.Hotel" id="myHotel">
            <id column="id" property="id" jdbcType="INTEGER" />
            <result column="hotel_name" property="hotelName" jdbcType="VARCHAR" />
            <result column="hotel_address" property="hotelAddress"
                jdbcType="VARCHAR" />
            <result column="price" property="price" jdbcType="INTEGER" />
        </resultMap>
    
        <select id="getHotel" resultMap="myHotel">
            select*
            from hotel
            <!-- trim  对trim标签体中拼接后的字符串进行操作
                   prefix       对拼接后的字符串加前缀
                   prefixOverrides   对拼接后的字符串去前缀
                   suffix  对拼接后的字符串加后缀
                   suffixOverrides   对拼接后的字符串去后缀
             -->
            <trim prefix="where" prefixOverrides="" suffix="" suffixOverrides="and">
                <if test="id!=null">
                    id=#{id} and
                </if>
                <if test="hotelName!=null &amp;&amp; hotelName!=&quot;&quot;">
                    hotel_name like concat('%',#{hotelName},'%') and
                </if>
                <if test="price!=null">
                    price> #{price}
                </if>
            </trim>
        </select>
    </mapper>

    这样就解决了

    4、choose (分支选择)

    MyBatis 提供了 choose 元素,它有点像 Java 中的 switch 语句。,但不同的是mybatis进入了一个分支后就不再进入其他分支。

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
    <mapper namespace="com.pjf.mybatis.dao.HotelMapper">
    
        <resultMap type="com.pjf.mybatis.po.Hotel" id="myHotel">
            <id column="id" property="id" jdbcType="INTEGER" />
            <result column="hotel_name" property="hotelName" jdbcType="VARCHAR" />
            <result column="hotel_address" property="hotelAddress"
                jdbcType="VARCHAR" />
            <result column="price" property="price" jdbcType="INTEGER" />
        </resultMap>
        <select id="getHotel" resultMap="myHotel">
            select*
            from hotel
            <where>
                <choose>
                    <when test="id!=null">
                        id=#{id}
                    </when>
                    <when test="hotelName!=null &amp;&amp; hotelName!=&quot;&quot;">
                        hotel_name like concat('%',#{hotelName},'%')
                    </when>
                    <when test="hotelAddress!=null &amp;&amp; hotelAddress!=&quot;&quot;">
                        hotel_address=#{hotelAddress}
                    </when>
                    <when test="price!=null">
                        price>#{price}
                    </when>
                    <otherwise>
                        1=1
                    </otherwise>
                </choose>
            </where>
        </select>
    </mapper>

    5、set

    前面我们使用update可以进行全字段更新,但是如果是带了什么字段就更新什么字段,该怎么做呢。

    可是使用set和if的结合,此外,set标签能自动删除末尾多余的逗号。

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
    <mapper namespace="com.pjf.mybatis.dao.HotelMapper">
    
        <resultMap type="com.pjf.mybatis.po.Hotel" id="myHotel">
            <id column="id" property="id" jdbcType="INTEGER" />
            <result column="hotel_name" property="hotelName" jdbcType="VARCHAR" />
            <result column="hotel_address" property="hotelAddress"
                jdbcType="VARCHAR" />
            <result column="price" property="price" jdbcType="INTEGER" />
        </resultMap>
    
        <update id="updateHotel">
            update hotel
            <set>
            <if test="hotelName!=null">
                hotel_name=#{hotelName},
            </if>
            <if test="price!=null">
                price=#{price}
            </if>
            </set>
            <where>
                id=#{id}
            </where>
        </update>
    </mapper>

    6、foreach

    用来对集合进行遍历

    <?xml version="1.0" encoding="UTF-8" ?>
    <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
    <mapper namespace="com.pjf.mybatis.dao.HotelMapper">
    
        <resultMap type="com.pjf.mybatis.po.Hotel" id="myHotel">
            <id column="id" property="id" jdbcType="INTEGER" />
            <result column="hotel_name" property="hotelName" jdbcType="VARCHAR" />
            <result column="hotel_address" property="hotelAddress"
                jdbcType="VARCHAR" />
            <result column="price" property="price" jdbcType="INTEGER" />
        </resultMap>
    
        <!-- resultMap使用 -->
        <select id="getHotel" resultMap="myHotel">
            select*
            from hotel where id in 
            <!-- collection 指要遍历的集合    1. 如果传入的是单参数且参数类型是一个List的时候,collection属性值为list
                                            2. 如果传入的是单参数且参数类型是一个array数组的时候,collection的属性值为array
                                            3. 如果传入的参数是多个的时候,我们就需要把它们封装成一个Map了,当然单参数也可以封装成map,map的key就是参数名,所以这个时候collection属性值就是传入的List或array对象在自己封装的map里面的key 
                     item 将遍历出的元素赋值给指定的变量
                     separator  每个元素之间的分隔符
                     open 遍历出的结果拼接出一个开始符
                     close 遍历出的结果拼接一个结束符
                     index 索引
             -->
            <foreach collection="list" item="ids" separator="," open="(" close=")">
            #{ids}
            </foreach>
        </select>
    </mapper>

    测试类

    package com.pjf.mybatis;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.Map;
    
    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.Test;
    
    import com.pjf.mybatis.dao.HotelMapper;
    import com.pjf.mybatis.po.City;
    import com.pjf.mybatis.po.Hotel;
    
    public class TestHotel {
    
        public SqlSessionFactory sqlSessionFactory() throws IOException {
            // mybatis的配置文件
            String resource = "mybatis_config.xml";
            // 使用类加载器加载mybatis的配置文件(它也加载关联的映射文件)TestHotel.class.getClassLoader()
            InputStream is = Resources.getResourceAsStream(resource);
            // 构建sqlSession的工厂
            SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(is);
            return sessionFactory;
        }
    
        @Test
        public void getHotel() throws IOException {
    
            SqlSessionFactory sessionFactory = sqlSessionFactory();
            SqlSession session = sessionFactory.openSession(true);
            HotelMapper hotelMapper = session.getMapper(HotelMapper.class);
            List<Integer> id =new ArrayList<Integer>();
            id.add(1001);
            id.add(1002);
            id.add(1003);
            List<Hotel> list= hotelMapper.getHotel(id);
            for (Hotel hotel : list) {
                System.out.println(hotel);
            }
            session.close();
        }
    }

    7、bind

    bind 元素可以从 OGNL 表达式中创建一个变量并将其绑定到上下文。

    <select id="getHotel" resultMap="myHotel">
      <bind name="_hotelName" value="'%' + hotelName + '%'" />
      SELECT * FROM hotel
      WHERE hotel_name LIKE #{_hotelName}
    </select>
  • 相关阅读:
    Python日志采集(详细)
    Python+Appium自动化测试(15)-使用Android模拟器(详细)
    Python+Appium自动化测试(14)-yaml配置Desired capabilities
    Python基础笔记2-ruamel.yaml读写yaml文件
    LoaRunner性能测试系统学习教程:SQL Server等待类型
    LoaRunner性能测试系统学习教程:CPU瓶颈
    LoaRunner性能测试系统学习教程:SQL监控与调优
    LoaRunner性能测试系统学习教程:垃圾回收器(12)
    LoaRunner性能测试系统学习教程:垃圾收集算法(11)
    LoadRunner性能测试系统学习教程:GC回收机制(10)
  • 原文地址:https://www.cnblogs.com/pjfmeng/p/7700700.html
Copyright © 2011-2022 走看看