每个基于 MyBatis 的应用都是以一个 SqlSessionFactory 的实例为核心的。SqlSessionFactory 的实例可以
通过 SqlSessionFactoryBuilder 获得。而 SqlSessionFactoryBuilder 则可以从 XML 配置文件或一个预先配
置的 Configuration 实例来构建出 SqlSessionFactory 实例。
SqlSessionFactory 一旦被创建就应该在应用的运行期间一直存在,没有任何理由丢弃它或重新创建另一
个实例。 使用 SqlSessionFactory 的最佳实践是在应用运行期间不要重复创建多次,多次重建
SqlSessionFactory 被视为一种代码“坏习惯”。因此 SqlSessionFactory 的最佳作用域是应用作用域。 有很
多方法可以做到,最简单的就是使用单例模式。
# (2)SqlSession
每个线程都应该有它自己的 SqlSession 实例。SqlSession 的实例不是线程安全的,因此是不能被共享
的,所以它的最佳的作用域是请求或方法作用域。 绝对不能将 SqlSession 实例的引用放在一个类的静态
域,甚至一个类的实例变量也不行。 也绝不能将 SqlSession 实例的引用放在任何类型的托管作用域中,
比如 Servlet 框架中的 HttpSession。 换句话说,每次收到 HTTP 请求,就可以打开一个 SqlSession,返
回一个响应后,就关闭它。 这个关闭操作很重要,为了确保每次都能执行关闭操作,你应该把这个关闭
操作放到 finally 块中。 下面的示例就是一个确保 SqlSession 关闭的标准模式:
在所有代码中都遵循这种使用模式,可以保证所有数据库资源都能被正确地关闭。
# (3)测试
当我们看到sqlSession有selectList,delete,update等方法时,我们会忍不住这样去使用。
但是这样确实是错误的。
错误消息中显示Mapped Statements collection does not contain value for select * from user,说是mapper
的申明中没有“select * from user”,其实这里让你填的是一个申明。我们在源码注释中可以看到:】
private SqlSessionFactory sqlSessionFactory = null;
private static final Logger LOGGER = LoggerFactory.getLogger(TestMybatis.class);
@Before
public void build() {
SqlSessionFactoryBuilder builder = new SqlSessionFactoryBuilder();
sqlSessionFactory =
builder.build(Thread.currentThread().getContextClassLoader().getResourceAsStream("
mybatis-config.xml"));
}
1
2
3
4
5
6
7
8
@Test
public void testSession(){
try (SqlSession sqlSession = sqlSessionFactory.openSession();){
List<Object> objects = sqlSession.selectList("select * from user");
System.out.println(objects);
}
}
1
2
3
4
5
6
7
org.apache.ibatis.exceptions.PersistenceException:
### Error querying database. Cause: java.lang.IllegalArgumentException: Mapped
Statements collection does not contain value for select * from user
### Cause: java.lang.IllegalArgumentException: Mapped Statements collection does
not contain value for select * from user
1
2
3