- 在 Mybatis 中进行查询操作的时候,查询单个对象、查询列表信息等的时候,我们需要每次都重复写创建 SqlSessionFactory、SqlSession 等相关代码
// 根据主键 id 查询单个用户
@Test
void testGet() {
InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
SqlSession sqlSession = sqlSessionFactory.openSession();
User user = sqlSession.selectOne("com.mxz.mybatis.mapper.UserMapper.get", 1L);
sqlSession.close();
}
// 查询所有用户
@Test
void testListAll() {
InputStream in = Resources.getResourceAsStream("mybatis-config.xml");
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(in);
SqlSession sqlSession = sqlSessionFactory.openSession();
List<User> userList = sqlSession.selectList("com.mxz.mybatis.mapper.UserMapper.ListAll");
sqlSession.close();
}
这样一来,如果后面有多个操作的话,代码就显得很冗余,所以我们需要提取共同的代码,创建 MybatisUtil 类,把冗余的代码进行封装
这里边共同的代码主要是
- 加载构造器配置数据库交互文件(SqlSessionFactoryBuilder)
- 创建构造器容器 (SqlSessionFactory)
- 数据库连接和操作的交互对象(SqlSession)
SqlSessionFactoryBuilder
这个类可以被实例化、使用和丢弃,一旦创建了 SqlSessionFactory,就不再需要它了。
因此 SqlSessionFactoryBuilder 的作用域是局部方法中
SqlSessionFactory
- SqlSessionFactory 一旦被创建就应该在应用的运行期间一直存在,没有任何理由丢弃它或重新创建另一个实例,而使用(private static)共享
- 使用 SqlSessionFactory 的最佳实践是在应用运行期间不要重复创建多次,因此使用单例模式或者静态单例模式控制只创建一次
SqlSession
- 每个线程都应该有它自己的 SqlSession 实例。
- SqlSession 的实例不是线程安全的,因此是不能被(public/private stastic)共享的,所以它的作用域是每个请求或每个方法的作用域中。
- 绝对不能将 SqlSession 实例的引用放在一个类的静态域中共享SqlSession连接,甚至一个类的实例变量也不行。
注
所以,要记住的是,SqlSessionFactory 是线程安全的,和数据库连接池 dataSource 一样,整个应用中有一份就够了
MybatisUtils 的封装
- 在 MybatisUtils 中,定义了一个静态代码块用于获取 SqlSession 对象。基本的 MybatisUtils 应该包含SqlSession 的获取创建和关闭
示例
- MyBatisUtils.java
public class MyBatisUtils {
private static SqlSessionFactory factory;
static {//静态代码下,factory只创建一次
System.out.print("static factory=============");
try {
// 从classpath 路径去加载mybatis 全局配置文件
InputStream is= Resources.getResourceAsStream("mybatis-config.xml");
factory=new SqlSessionFactoryBuilder().build(is);
}catch(IOException e){
e.printStackTrace();
}
}
public static SqlSession createSqlSession() {
return factory.openSession(false);//true提交事务
}
public static void closeSqlSession(SqlSession sqlSession) {
sqlSession.close();
}
}
MybatisUtils 的使用
SqlSession 和数据库连接对象 Connection 是一样的,是线程不安全的,每次都要创建新的连接,用完了都要去关闭它,这个关闭操作是很重要的,你应该把这个关闭操作放到 finally 块中以确保每次都能执行关闭
示例
public void testGetUserList() {
SqlSession sqlSession=null;
List<Users> userList =new ArrayList<Users>();
try{
//调用封装为MyBatisUtil的数据库连接方法.java
sqlSession=MyBatisUtils.createSqlSession();
//调用getMapper(Mapper.class)执行dao接口方法来实现对数据库的查询操作
count=sqlsession.getMapper(UsersMapper.class).count();
//获取实体类数据
userList=sqlSession.getMapper(UsersMapper.class).getUserList();
sqlSession.commit();
logger.debug("UserMappingTest count--->"+count);
}catch(Exception e){
e.printStackTrace();
}finally{
MyBatisUtil.closeSqlSession(sqlSession);
}
}