本文收录于模仿与学习MyBatis系列
简述
在前一章《模仿与学习MyBatis - 1.3 xml配置的解析》中,对指定的文件实行了一个基本的DataSource解析类
XMLConfigBuilder
。在本篇中将讨论以及实现一个最基本的
SessionFactory
(关于Session的意义可跳转到这里)。计划未来所有Session,都统一通过SessionFactory.openSession()
这类方式获取。
最终项目是一个Java Maven项目,代码存在github了。
SessionFactory的意义
首先我们来观察一下SessionFactory在MyBatis中是怎样的:
public interface SqlSessionFactory {
SqlSession openSession();
SqlSession openSession(boolean autoCommit);
SqlSession openSession(Connection connection);
SqlSession openSession(TransactionIsolationLevel level);
SqlSession openSession(ExecutorType execType);
SqlSession openSession(ExecutorType execType, boolean autoCommit);
SqlSession openSession(ExecutorType execType, TransactionIsolationLevel level);
SqlSession openSession(ExecutorType execType, Connection connection);
Configuration getConfiguration();
}
- 可以看到这个接口定义了非常多方法,但主要的目的,无非就是为了获取一个Session。根据设计模式的角度来看,SessionFactory是Session的工厂,即是负责吐出Session的类。实现不同的SessionFactory,以及有着不同的配置方式(xml配置、Spring对接等等),而实现不同的Session有不同的执行效果。这样框架的配置与功能就分开了,这样我们可以方便的搭配与组合。这一处也正是解耦与工厂模式的意义。
- 另外,Session中的缓存就是俗称的一级缓存,通过一个Session查询的值(如果中间未修改的话)可以直接从缓存中读取到,不用每次都从数据库中查询同样的东西。那么问题来了,如果有些值查询特别频繁,我们希望有一个,对所有Session查询都有效的全局缓存,要怎么办呢?这时候SessionFactory的作用又体现出来了,通常全局缓存(也称为二级缓存)就是与SessionFactory相关的。这里暂时不作展开,因为在后续改进版当中会用到缓存。
- 还有第三个用处,在MyBatis中并不有效。有的框架,新建Session代价较大,不希望频繁的创建销毁,而是希望对应一个线程分配一个Session。这时线程独立的Session,通常只能在SessionFactory这个全局唯一的factory上进行分配。
综上所述,暂时我们只需要考虑第一点就足够了。
SessionFactory的实现
在本章节,将利用上一章实现的XMLConfigBuilder
,完成一个基本功能。先构造一个标准的SessionFactory接口:
public interface SessionFactory {
Session openSession();
}
利用XMLConfigBuilder
只要简单的把文件名传给它,吐出一个DataSource
,存下,在openSession时带入即可 :
public class VSessionFactory implements SessionFactory {
private DataSource config;
public VSessionFactory(String resource) {
config = XMLConfigBuilder.build(resource);
}
public Session openSession() {
return new VSession(config);
}
}
最后还是惯例,上一段测试代码。
public static void main(String args[]) throws Exception {
SessionFactory factory = new VSessionFactory("config.xml");
Session session = factory.openSession();
session.exec("select * from article where id<30");
}
结果没有任何问题:
--------------------print--------------------
id=1
title=欢迎来到自由茶社
brief=这里是大门的入口
content=这里是大门的入口
father_id=0
author_name=me
create_time=2016-11-16 23:44:36.0
modify_time=2016-12-06 00:41:07.0
id=29
title=第一章
brief=随便打的内容
content=随便打的内容
father_id=1
author_name=me
create_time=2016-11-16 23:45:20.0
modify_time=2016-11-16 23:45:20.0
以上。