MyBatis_记录(四)

Posted 小企鹅推雪球!

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了MyBatis_记录(四)相关的知识,希望对你有一定的参考价值。


文章目录Java Java

MyBatis foreach标签

  1. 对于一些 SQL 语句中含有 in 条件,需要迭代条件集合来生成的情况,可以使用 foreach 来实现 SQL 条件的迭代。
  2. Mybatis foreach 标签用于循环语句,支持了数据和 List、set 接口的集合,并对此提供遍历的功能
<foreach item="item" index="index" collection="list|array|map key" open="(" separator="," close=")">
    参数值
</foreach>
  1. foreach 标签的属性
    1. item:表示集合中每一个元素进行迭代时的别名。
    2. index:指定一个名字,表示在迭代过程中每次迭代到的位置。
    3. open:表示该语句以什么开始(既然是 in 条件语句,所以必然以(开始)。
    4. separator:表示在每次进行迭代之间以什么符号作为分隔符(既然是 in 条件语句,所以必然以,作为分隔符)。
    5. close:表示该语句以什么结束(既然是 in 条件语句,所以必然以)开始)。
  2. 使用 foreach 标签时,最关键、最容易出错的是 collection 属性,该属性是必选的
  3. collection 主要有三种情况
    1. 如果传入的是单参数且参数类型是一个 List,collection 属性值为 list。
    2. 如果传入的是单参数且参数类型是一个 array 数组,collection 的属性值为 array。
    3. 如果传入的参数是多个,需要把它们封装成一个 Map,当然单参数也可以封装成 Map。Map 的 key 是参数名,collection 属性值是传入的 List 或 array 对象在自己封装的 Map 中的 key。

MyBatis foreach标签样例

  1. WebsiteMapper.xml
<select id="selectWebsite"
    parameterType="net.biancheng.po.Website"
    resultType="net.biancheng.po.Website">
    SELECT id,name,url,age,country
    FROM website WHERE age in
    <foreach item="age" index="index" collection="list" open="("
        separator="," close=")">
        #{age}
    </foreach>
</select>
  1. WebsiteMapper 类中相应方法
public List<Website> selectWebsite(List<Integer> ageList);
  1. 测试代码
public class Test {
    public static void main(String[] args) throws IOException {
        // 读取配置文件mybatis-config.xml
        InputStream config = Resources.getResourceAsStream("mybatis-config.xml"); // 根据配置文件构建
        SqlSessionFactory ssf = new SqlSessionFactoryBuilder().build(config);
        // 通过SqlSessionFactory创建SqlSession
        SqlSession ss = ssf.openSession();
        List<Integer> ageList = new ArrayList<Integer>();
        ageList.add(10);
        ageList.add(12);
        List<Website> siteList = ss.selectList("net.biancheng.mapper.WebsiteMapper.selectWebsite", ageList);
        for (Website ws : siteList) {
            System.out.println(ws);
        }
    }
}
  1. 在使用 foreach 标签时,应提前预估一下 collection 对象的长度。因为大量数据的 in 语句会影响性能,且还有一些数据库会限制执行的 SQL 语句长度。

MyBatis bind标签

  1. 每个数据库的拼接函数或连接符号都不同,例如 mysql 的 concat 函数、Oracle 的连接符号“||”等。SQL 映射文件就需要根据不同的数据库提供不同的实现,显然比较麻烦,且不利于代码的移植
  2. MyBatis 提供了 bind 标签来解决这一问题。
  3. bind 标签可以通过 OGNL 表达式自定义一个上下文变量。
  4. 按照网站名称进行模糊查询,SQL 映射文件如下
<select id="selectWebsite" resultType="net.biancheng.po.Website">
    <bind name="pattern" value="'%'+_parameter+'%'" />
    SELECT id,name,url,age,country
    FROM website
    WHERE name like #{pattern}
</select>
  1. bind元素属性:
    1. value:对应传入实体类的某个字段,可以进行字符串拼接等特殊处理。
    2. name:给对应参数取的别名。
  2. “_parameter”代表传递进来的参数,它和通配符连接后,赋给了 pattern,然后就可以在 select 语句中使用这个变量进行模糊查询

MyBatis bind标签样例

  1. WebsiteMapper 类中方法
public List<Website> selectWebsite(Website site);
  1. SQL 映射文件代码
<select id="selectWebsite" resultType="net.biancheng.po.Website">
    <bind name="pattern_name" value="'%'+name+'%'" />
    <bind name="pattern_url" value="'%'+url+'%'" />
    SELECT id,name,url,age,country
    FROM website
    WHERE name like #{pattern_name}
    AND url like #{pattern_url}
</select>
  1. 测试代码
public class Test {
    public static void main(String[] args) throws IOException {
        // 读取配置文件mybatis-config.xml
        InputStream config = Resources.getResourceAsStream("mybatis-config.xml"); // 根据配置文件构建
        SqlSessionFactory ssf = new SqlSessionFactoryBuilder().build(config);
        // 通过SqlSessionFactory创建SqlSession
        SqlSession ss = ssf.openSession();
        Website site = new Website();
        site.setname("编程");
        site.setUrl("http");
        List<Website> siteList = ss.selectList("net.biancheng.mapper.WebsiteMapper.selectWebsite", site);
        for (Website ws : siteList) {
            System.out.println(ws);
        }
    }
}

MyBatis trim标签

  1. trim 一般用于去除 SQL 语句中多余的 AND 关键字、逗号,或者给 SQL 语句前拼接 where、set 等后缀,可用于选择性插入、更新、删除或者条件查询等操作
  2. trim 语法格式如下:
<trim prefix="前缀" suffix="后缀" prefixOverrides="忽略前缀字符" suffixOverrides="忽略后缀字符">
    SQL语句
</trim>
  1. trim 中属性如下:
    1. prefix:给SQL语句拼接的前缀,为 trim 包含的内容加上前缀
    2. suffix:给SQL语句拼接的后缀,为 trim 包含的内容加上后缀
    3. prefixOverrides:去除 SQL 语句前面的关键字或字符,该关键字或者字符由 prefixOverrides 属性指定。
    4. suffixOverrides:去除 SQL 语句后面的关键字或者字符,该关键字或者字符由 suffixOverrides 属性指定。

MyBatis trim标签样例

  1. WebsiteMapper.xml
<select id="selectWebsite" resultType="net.biancheng.po.Website">
    SELECT id,name,url,age,country
    FROM website
    <trim prefix="where" prefixOverrides="and">
        <if test="name != null and name !=''">
            AND name LIKE CONCAT ('%',#{name},'%')
        </if>
        <if test="url!= null">
            AND url like concat ('%',#{url},'%')
        </if>
    </trim>
</select>
  1. WebsiteMapper 类中方法
public List<Website> selectWebsite(Website website);
  1. 测试类代码
public class Test {
    public static void main(String[] args) throws IOException {
        // 读取配置文件mybatis-config.xml
        InputStream config = Resources.getResourceAsStream("mybatis-config.xml"); // 根据配置文件构建
        SqlSessionFactory ssf = new SqlSessionFactoryBuilder().build(config);
        // 通过SqlSessionFactory创建SqlSession
        SqlSession ss = ssf.openSession();
        Website site = new Website();
        site.setname("编程");
        site.setUrl("http");
        List<Website> siteList = ss.selectList("net.biancheng.mapper.WebsiteMapper.selectWebsite", site);
        for (Website ws : siteList) {
            System.out.println(ws);
        }
    }
}

MyBatis分页功能

  1. MyBatis 的分页功能是基于内存的分页,即先查询出所有记录,再按起始位置和页面容量取出结果。
  2. WebsiteMapper 中方法
/**
*
* @param site
* @param currentPageNo 起始位置
* @param pageSize      页面容量
* @return
*/
public List<Website> selectWebsite(@Param("site") Website site, @Param("from") Integer currentPageNo,
        @Param("pageSize") Integer pageSize);
  1. 相比原来的 selectWebsite 方法,增加了两个参数,起始位置(from)和页面容量(pageSize),用于实现分页查询。
  2. 修改 WebsiteMapper.xml 的查询语句,增加 limit 关键字,SQL 映射代码
<select id="selectWebsite" resultType="net.biancheng.po.Website">
    SELECT id,name,url,age,country
    FROM website
    <trim prefix="where" prefixOverrides="and">
        <if test="site.name != null and site.name !=''">
            AND name LIKE CONCAT ('%',#{site.name},'%')
        </if>
        <if test="site.url!= null and site.url !=''">
            AND url LIKE CONCAT ('%',#{site.url},'%')
        </if>
        ORDER BY id limit #{from},#{pageSize}
    </trim>
</select>
  1. 测试类代码
public static void main(String[] args) throws IOException {
    // 读取配置文件mybatis-config.xml
    InputStream config = Resources.getResourceAsStream("mybatis-config.xml");
    // 根据配置文件构建
    SqlSessionFactory ssf = new SqlSessionFactoryBuilder().build(config);
    // 通过SqlSessionFactory创建SqlSession
    SqlSession ss = ssf.openSession();
    Website site = new Website();
    // site.setname("编程");
    site.setUrl("http");
    Integer pageSize = 3;
    Integer currentPageNo = 0;
    List<Website> siteList = new ArrayList<Website>();
    siteList = ss.getMapper(WebsiteMapper.class).selectWebsite(site, currentPageNo, pageSize);
    for (Website ws : siteList) {
        System.out.println(ws);
    }
}
  1. MyBatis 实现分页查询属于 DAO 层操作,由于 DAO 层不牵涉任何业务实现,所以实现分页的方法中第一个参数为 limit 的起始位置(下标从 0 开始),而不是用户输入的真正页码(页码从1开始)

MyBatis缓存

  1. 缓存可以将数据保存在内存中,目前流行的缓存服务器有 MongoDB、Redis、Ehcache 等。
  2. 缓存是在计算机内存上保存的数据,读取时无需再从磁盘读入,因此具备快速读取和使用的特点。
  3. MyBatis 提供了一级缓存和二级缓存的支持。默认情况下,MyBatis 只开启一级缓存

MyBatis一级缓存

  1. 一级缓存是基于 PerpetualCache(MyBatis自带)的 HashMap 本地缓存,作用范围为 session 域内
  2. 当 session flush(刷新)或者 close(关闭)之后,该 session 中所有的 cache(缓存)就会被清空。
  3. 在参数和 SQL 完全一样的情况下,我们使用同一个 SqlSession 对象调用同一个 mapper 的方法,往往只执行一次 SQL。。因为使用 SqlSession 第一次查询后,MyBatis 会将其放在缓存中,再次查询时,如果没有刷新,并且缓存没有超时的情况下,SqlSession 会取出当前缓存的数据,而不会再次发送 SQL 到数据库
  4. SqlSession 是相互隔离的,如果使用不同的 SqlSession 对象,即使调用相同的 Mapper、参数和方法,MyBatis 还是会再次发送 SQL 到数据库执行,返回结果。

MyBatis二级缓存

  1. 二级缓存是全局缓存,作用域超出 session 范围之外,可以被所有 SqlSession 共享。
  2. 一级缓存缓存的是 SQL 语句,二级缓存缓存的是结果对象。

二级缓存的配置

  1. MyBatis 的全局缓存配置需要在 mybatis-config.xml 的 settings 元素中设置
<settings>
    <setting name="cacheEnabled" value="true" />
</settings>
  1. 在 mapper 文件(如 WebMapper.xml)中设置缓存,默认不开启缓存。需要注意的是,二级缓存的作用域是针对 mapper 的 namescape 而言,即只有再次在 namescape 内(net.biancheng.WebsiteMapper)的查询才能共享这个缓存,
  2. mapper代码:
<mapper namescape="net.biancheng.WebsiteMapper">
    <!-- cache配置 -->
    <cache
        eviction="FIFO"
        flushInterval="60000"
        size="512"
        readOnly="true" />
    ...
</mapper>
  1. eviction:代表的是缓存回收策略,目前 MyBatis 提供以下策略:
    1. LRU:使用较少,移除最长时间不用的对象
    2. FIFO:先进先出,按对象进入缓存的顺序来移除它们;
    3. SOFT:软引用,移除基于垃圾回收器状态和软引用规则的对象
    4. WEAK:弱引用,更积极地移除基于垃圾收集器状态和弱引用规则的对象
  2. flushInterval:刷新间隔时间,单位为毫秒,这里配置的是 100 秒刷新,如果省略该配置,那么只有当 SQL 被执行的时候才会刷新缓存。
  3. size:引用数目,正整数,代表缓存最多可以存储多少个对象,不宜设置过大。设置过大会导致内存溢出。这里配置的是 1024 个对象。
  4. readOnly:只读,默认值为 false,意味着缓存数据只能读取而不能修改,这样设置的好处是可以快速读取缓存,缺点是没有办法修改缓存。
  5. 在 mapper 文件配置支持 cache 后,如果需要对个别查询进行调整,可以单独设置 cache
<select id="getWebsiteList" resultType="net.biancheng.po.Website" usecache="true">
    ...
</select>
  1. MyBatis 缓存仅作了解因为面对一定规模的数据量,内置的 Cache 方式就派不上用场了,并且对查询结果集做缓存并不是 MyBatis 所擅长的,它专心做的应该是 SQL 映射。对于缓存,采用 OSCache、Memcached 等专门的缓存服务器来做更为合理。

以上是关于MyBatis_记录(四)的主要内容,如果未能解决你的问题,请参考以下文章

MYBATIS05_ifwherechoosewhentrimsetforEach标签sql片段

Mybatis:动态SQL

[mybatis]动态sql_sql_抽取可重用的sql片段

Spring+SpringMVC+MyBatis+Maven框架整合

discuz X3.1 源代码阅读,记录代码片段

MyBatis_记录