一文带你快速搭建框架(五)

150 阅读5分钟

本文正在参加「金石计划 . 瓜分6万现金大奖」

五.相关API

1.Resources

  • Resources类由MyBatis提供用于获取来自核心配置文件的输入流
  • 相关方法是:InputStream getResourceAsStream(String filepath),注意这是一个静态方法

2.SqlSessionFactoryBuilder

  • SqlSessionFactoryBuilder类由MyBatis提供用于获取SqlSessionFactory的实例对象
  • 相关方法是:SqlSessionFactory build(InputStream is),该方法通过一个输入流返回了SqlSessionFactory对象

3.SqlSessionFactory

  • SqlSessionFactory类由MyBatis提供用于获取SqlSession对象,每个基于MyBatis的应用都是以一个SqlSessionFactory的实例为核心的
  • 相关方法:SqlSession openSession()SqlSession openSession(boolean autoCommit),这两个方法都用于获取SqlSession对象,如果使用有参数的可以指定是否自动提交事务,没有指定参数的默认是不自动提交事务

4.SqlSession

  • SqlSession类由MyBatis提供用于执行SQL、管理事务、接口代理

  • 常用方法

    方法说明
    void commit()提交事务
    void rollback()回滚事务
    T getMapper(Class aClass)获取指定接口的代理实现类
    void close()释放资源
  • 除了以上常用方法外,SqlSession还有很多有关数据库增删改查的方法,但是这些方法繁琐而且不符合类型安全,所以使用getMapper()方法来获取一个Mapper接口的代理实现类来执行映射语句是个比较方便的做法

5.最佳实践

  • SqlSessionFactoryBuilder

    这个类可以被实例化、使用和丢弃,一旦创建了 SqlSessionFactory,就不再需要它了。因此 SqlSessionFactoryBuilder 实例的最佳范围是方法范围( 也就是局部方法变量)。你可以重用 SqlSessionFactoryBuilder 来创建多个 SqlSessionFactory 实例,但是最好还是不要让其一直存在以保证所有的 XML 解析资源开放给更重要的事情

  • SqlSessionFactory

    SqlSessionFactory 一旦被创建就应该在应用的运行期间一直存在,没有任何理由对它进行清除或重建。使用 SqlSessionFactory 的最佳实践是在应用运行期间不要重复创建多次,多次重建 SqlSessionFactory 被视为一种代码“坏味道(bad smell)”。因此  SqlSessionFactory 的最佳范围是应用范围。有很多方法可以做到,最简单的就是使用单例模式或者静态单例模式

  • SqlSession

    每个线程都应该有它自己的 SqlSession 实例。SqlSession 的实例不是线程安全的,因此是不能被共享的,所以它的最佳的范围是请求或方法范围。绝对不能将 SqlSession 实例的引用放在一个类的静态域,甚至一个类的实例变量也不行。也绝不能将 SqlSession 实例的引用放在任何类型的管理范围中,比如 Serlvet 架构中的 HttpSession。如果你现在正在使用一种 Web 框架,要考虑 SqlSession 放在一个和 HTTP 请求对象相似的范围中。换句话说,每次收到的 HTTP 请求,就可以打开一个 SqlSession,返回一个响应,就关闭它。这个关闭操作是很重要的,你应该把这个关闭操作放到 finally 块中以确保每次都能执行关闭

  • 工具类

    public class SqlSessionUtil {
    ​
        private static SqlSessionFactory sqlSessionFactory;
    ​
        static{
            try {
                InputStream is = Resources.getResourceAsStream("mybatis-config.xml");
                SqlSessionFactoryBuilder sqlSessionFactoryBuilder = new SqlSessionFactoryBuilder();
                sqlSessionFactory = sqlSessionFactoryBuilder.build(is);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    ​
        public static SqlSession getSqlSession(){
            return sqlSessionFactory.openSession(true);
        }
    }
    ​
    

六.缓存

1.一级缓存

  • 一级缓存是SqlSession级别的,通过同一个SqlSession查询的数据会被缓存,下次查询相同的数据,就会从缓存中直接获取,不会从数据库重新访问,一级缓存是默认开启的

  • 一级缓存失效的四种情况:

    • 使用另一个SqlSession
    • 同一个SqlSession但是查询条件不同
    • 同一个SqlSession但是两次查询中间执行了任何一次增删改操作
    • 同一个SqlSession但是两次查询中间手动清空了缓存,手动清空缓存的方法是调用SqlSession的clearCache()方法

2.二级缓存

  • 二级缓存是SqlSessionFactory级别,通过同一个SqlSessionFactory创建的SqlSession查询的结果会被缓存,此后若再次执行相同的查询语句,结果就会从缓存中获取

  • 二级缓存开启的条件:

    • 在核心配置文件中,设置全局配置属性cacheEnabled="true",默认为true,不需要设置
    • 在映射文件中设置标签
    • 二级缓存必须在SqlSession关闭或提交之后有效
    • 查询的数据所转换的实体类类型必须实现序列化的接口
  • 二级缓存失效的情况:两次查询之间执行了任意的增删改,会使一级和二级缓存同时失效

  • 可以设置的一些属性:

    • eviction属性:缓存回收策略,默认的是 LRU

      1. LRU(Least Recently Used) – 最近最少使用的:移除最长时间不被使用的对象
      2. FIFO(First in First out) – 先进先出:按对象进入缓存的顺序来移除它们
      3. SOFT – 软引用:移除基于垃圾回收器状态和软引用规则的对象
      4. WEAK – 弱引用:更积极地移除基于垃圾收集器状态和弱引用规则的对象
    • flushInterval属性:刷新间隔,单位是毫秒,默认情况下不设置也就是没有刷新间隔,缓存仅仅调用语句时刷新

    • size属性:引用数目,正整数代表缓存最多可以存储多少个对象,太大容易导致内存溢出

    • readOnly属性:只读, 取值是true/false

      1. true:只读缓存,会给所有调用者返回缓存对象的相同实例,因此这些对象不能被修改,这提供了很重要的性能优势
      2. false:读写缓存,会返回缓存对象的拷贝(通过序列化),这会慢一些,但是安全,因此默认是false

3.缓存的查询顺序

  • 先查询二级缓存,因为二级缓存中可能会有其他程序已经查出来的数据,可以拿来直接使用
  • 如果二级缓存没有命中,再查询一级缓存
  • 如果一级缓存也没有命中,则查询数据库
  • 注意SqlSession关闭之后,一级缓存中的数据才会写入二级缓存