从XML中构建SqlSessionFactory
Mybatis应用的核心是一个SqlSessionFactory的实例。
SqlSessionFactory实例可以通过SqlSessionFactoryBuilder获得。而SqlSessionFactoryBuilder则可以从XML配置文件或一个预先配置的Configuration实例来构建出SqlSessionFactory实例。
从XML文件中构建SqlSessionFactory的实例非常简单,建议使用类路径下的资源文件进行配置。Mybatis包含一个Resources的工具类,它包含了一些使用方法,使得从类路径或其它位置加载资源文件更加容易。
String resource="org/mybatis/example/mybatis-config.xml";
InputStream inputStream=Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory=new SqlSessionFactoryBuilder().build(inputStream);
XML配置文件包含了对Mybatis系统的核心设置,包括获取数据库连接实例的数据源(DataSource)以及决定事务作用域和控制方式的事务管理器(TransactionManager)。先给出一个简单示例:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE configuration
PUBLIC "-//mybatis.org//DTD Config 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-config.dtd"> <!--XML头部的声明,用来验证XML文档的正确性-->
<configuration>
<environments default="development">
<environment id="development">
<transactionManager type="JDBC"/>
<dataSource type="POOLED">
<property name="driver" value="${driver}"/>
<property name="url" value="${url}"/>
<property name="username" value="${username}"/>
<property name="password" value="${password}"/>
</dataSource>
</environment>
</environments>
<mappers>
<mapper resource="org/mybatis/example/BlogMapper.xml"/>
</mappers>
</configuration>
利用java类构建SqlSessionFactory
DataSource dataSource = BlogDataSourceFactory.getBlogDataSource();
TransactionFactory transactionFactory = new JdbcTransactionFactory();
Environment environment = new Environment("development",transactionFactory,dataSource);
Configuration configuration = new Configuration(environment);
configuration.addMapper(BlogMapper.class);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(configuration);
configuration添加了一个映射器类(mapper class)。映射器类是Java类,它们包含SQL映射注解从而避免依赖XML文件。不过,由于Java注解的一些限制以及某些Mybatis映射的复杂性,要使用大多数高级映射,仍然需要使用XML配置。所以,如果存在同一个XML配置文件,Mybatis会自动查找并加载它。
从SqlSessionFactory中获取SqlSession
SqlSession提供了在数据库执行SQL命令的所需的所有方法。
旧的使用方法:
try(SqlSession session = sqlSessionFactory.openSession()){
Blog blog = (Blog)session.selectOne("org.mybatis.example.BlogMapper.selectBlog",101);
}
新的使用方法(代码更加清晰,更加类型安全):
try(SqlSession session = sqlSessionFactory.openSession()){
BlogMapper mapper = session.getMapper(BlogMapper.class);
Blog blog = mapper.selectBlog(101);
}
探究已映射的SQL语句
一个SQL语句既可以通过XML定义,也可以通过注解定义。事实上,Mybatis提供的所有特性都可以利用基于XML的映射语言来实现。这里给出一个基于XML映射语句的示例,它应该可以满足上个示例中SqlSession的调用。
<?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="org.mybatis.example.BlogMapper">
<select id="selectBlog" resultType="Blog">
select * from Blog where id = #{id}
</select>
</mapper>
作用域(Scope)和生命周期
对象生命周期和依赖注入框架:
依赖注入框架可以创建线程安全的、基于事务的SqlSession和映射器,并将它们直接注入到你的Bean中,因此可以直接忽略它们的生命周期。
SqlSessionFactoryBuilder:
这个类可以被实例化、使用和丢弃,一旦创建了SqlSessionFactory,就不再需要它了。因此SqlSessionFactoryBuilder实例的最佳作用域(也就是局部方法变量)。可以重用SqlSessionFactoryBuilder来创建多个SqlSessionFactory实例,但最好还是不要一直保留着它,以保证所有的XML解析资源可以被释放给更重要的事情。
SqlSessionFactory:
SqlSessionFactory一旦被创建就应该在应用的运行期间一直存在,没有任何理由丢弃它或者重新创建另一个实例。使用SqlSessionFactory的最佳实践是在应用运行期间不要重复创建多次,多次创建SqlSessionFactory,否则被视为一种代码“坏习惯”。因此SqlSessionFactory的最佳作用域是应用作用域。有很多方法可以做到,最简单的就是使用单例模式或者静态单例模式。
SqlSession:
每个线程都应该有它自己的SqlSession实例。SqlSession的实例不是线程安全的,因此是不能被共享的,所以它的最佳的作用域是请求或方法作用域。绝对不能将SqlSession实例的引用放在一个类的静态域,甚至一个类的实例变量也不行。也绝不能将SqlSession实例的引用放在任何类型的托管作用域中。
映射器实例:
映射器是一些绑定映射语句的接口。映射器接口的实例是从SqlSession中获得的。虽然从技术层面上来讲,任何映射器实例的最大作用域与请求它们的SqlSession相同。但方法作用域才是映射器实例的最合适的作用域。
补充
命名空间:随着命名空间越发重要,现在写XML文件必须指定命名空间。
作用:一个是利用更长的全限定类名来将不同的语句隔离开来,同时也实现了你上面见到的接口绑定。就算你觉得暂时用不到接口绑定,你也应该遵循这里的规定,以防哪天你改变了主意。
命名解析:为了减少输入量,Mybatis对所有具有名称的配置元素(包括语句,结果映射,缓存等)使用了如下的命名解析规则。
· 全限定名将被直接用于查找及使用。
· 短名称如果全局唯一也可以作为一个单独的引用。如果不唯一,那么使用时就会产生“短名称不唯一”的错误,这种情况下就必须使用全限定名。
还有一种使用Java注解来配置,比如:
package org.mybatis.example;
public interface BlogMapper {
@Select("SELECT * FROM blog WHERE id = #{id}")
Blog selectBlog(int id);
}
使用注解来映射简单的语句会使代码显得更加简洁,但对于稍微复杂一点的语句,最好还是用XML来映射语句。