MyBatis入门(一)中讲述了主要组件以及基本用法,但远远不够支持我们在实际开发中写出高效的程序,尤其是在Web应用,Socket连接池等多线程场景中,可能会有很严重的并发问题,所以这篇博客主要了解MyBatis的生命周期,包括SqlSessionFactoryBuilder、SqlSessionFactory、SqlSession、Mapper的生命周期并且重构MyBatis入门(一)中代码使MyBatisb能够高效的工作。
1、SqlSessionFactoryBuilder
SqlSessionFactoryBuilder的主要是利用XML或Java编码获得资源来构建SqlSessionFactory通过它可以构建多个SqlSessionFactory。它的作用就是构建器,一旦构建SqlSessionFactory,它的作用就完结了,可以将它回收,它的生命周期只存在于方法的局部,作用就是生成SqlSessionFactory对象。
2、SqlSessionFactory
SqlsessionFactory的作用是用来创建SqlSession,SqlSession是一次会话,相当有JDBC中的Connection对象,每次应用需要访问数据库,就用通过SqlSessionFactory创建SqlSession,所以SqlSessionFactory存在应用的整个生命周期中。如果我们每次访问数据库都创建一个SqlSessionfactory,那么数据库连接资源很快就会被耗尽,因为SqlsessionFactory的责任单一,主要是用来创建SqlSession的,因此SqlSessionFactory的创建采用单例模式。一个数据库对应一个SqlSessionFactory,便于管理资源,避免过多Connection被消耗。
3、Sqlsession
SqlSession是一个会话,相当于JDBC的一个Connection对象,他的生命周期应该是在请求数据库处理事务的过程中,它是一个非线程安全的对象,再涉及多线程的时候需要多注意,操作数据库主要注意其隔离级别,数据库锁等高级特性。再就是每次创建SqlSession使用后都必须及时关闭,如果它长期存在就会使数据库连接池的活动资源减少,对应用性能影响很大,可以在finally语句块中保证正确关闭。它存活于一个应用的请求和操作,可以执行多条SQL,保证事务的一致性。
4、Mapper
Mapper是一个接口,没有任何实现类,它的作用是发送SQL返回我们需要的结果,或者发送SQL去修改数据库的数据,因此它应该在一个SqlSession事务方法之内,它如同JDBC中一条SQL语句的执行,它最大范围也不会超过SqlSession,尽管想一直保存着Mapper,但很难控制它,所以尽可能的在一个SqlSession事务的方法中使用,然后废弃掉。
了解了生命周期,下面将对MyBatis入门(一)中的代码进行优化,首先生成SqlSessionFactory单例,然后让它生成SqlSession,进而拿到映射器来完成业务逻辑。代码结构如下:
1、提供log4j配置文件,打印MyBatis运行轨迹,方便调试
---------------------------------log4j.properties-------------------------------------------------
#log4j配置文件,打印MyBatis运行轨迹,为调试带来帮助
log4j.rootLogger=DEBUG,stdout
log4j.logger.org.mybatis=DEBUG
log4j.appender.stdout=org.apache.log4j.ConsoleAppender
log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
log4j.appender.stdout.layout.ConversionPattern=%5p %d %C: %m%n
2、提供mybatis-config.xml配置文件,构建SqlSessionFactory对象,用来打开sqlSession
----------------------------------mybatis-config.xml--------------------------------------------
---------------------------------------------------------------------------------------------------
3、创建SqlSessionFactoryUtil.java工具类,责任单一,单例获取
----------------------------SqlSessionFactoryUtil.java------------------------------------------
package com.test.util;
import java.io.IOException;
import java.io.InputStream;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
/**
* SqlSeesionFactory工具类
*
* 创建单例SqlSessionFactory,打开SqlSession
*
* @author LHX
* @email
* @date 2018年7月18日-上午10:29:05
* @version 1.0.0
*/
public class SqlSessionFactoryUtil {
//sqlSessionFactory对象
private static SqlSessionFactory sqlSessionFactory = null;
//类线程锁
private static final Class CLASS_LOCK = SqlSessionFactory.class;
/*
* 私有化构造
*/
private SqlSessionFactoryUtil() {
}
/*
* 构建SqlSessionFactory
*/
public static SqlSessionFactory initSqlSessionFactory() {
String resource = "com/test/mybatis-config.xml";
InputStream inputStream = null;
try{
inputStream = Resources.getResourceAsStream( resource );
}catch(IOException ex){
//Logger.getLogger( SqlSessionFactoryUtil.class.getName()).log( Level.SEVERE,null,ex);
ex.printStackTrace();
}
synchronized ( CLASS_LOCK ) {
if( sqlSessionFactory == null ){
sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
}
}
return sqlSessionFactory;
}
/*
* 打开SqlSession
*/
public static SqlSession openSqlSession(){
if(sqlSessionFactory == null){
initSqlSessionFactory();
}
return sqlSessionFactory.openSession();
}
}
4、创建POJO
------------------------------------TestClass.java------------------------------------------------
package com.test.model;
/**
* POJO·
*
* 实体类对象
* @author LHX
* @email
* @date 2018年7月18日-上午11:11:16
* @version 1.0.0
*/
public class TestClass {
private Long id;
private String name;
/**
* id
* @return the id
* @since 1.0.0
*/
public Long getId() {
return id;
}
/**
* @param id the id to set
*/
public void setId(Long id) {
this.id = id;
}
/**
* name
* @return the name
* @since 1.0.0
*/
public String getName() {
return name;
}
/**
* @param name the name to set
*/
public void setName(String name) {
this.name = name;
}
}
5、创建Mapper.xml映射文件
---------------------------------TestClassMapper.xml------------------------------------------
insert into test_class ( name ) values ( #{name} )
delete from test_class where id = #{id}
6、创建Mapper.java接口声明
---------------------------------TestClassMapper.java------------------------------------------
package com.test.mapper;
import com.test.model.TestClass;
/**
* Mapper的接口声明
*
* TODO(这里描述这个类补充说明 – 可选)
* @author LHX
* @email
* @date 2018年7月18日-下午2:15:17
* @version 1.0.0
*/
public interface TestClassMapper {
public TestClass getTestClass( Long id );
public int deleteTestClass( Long id );
public int insertTestClass( TestClass testClass);
}
7、创建main方法,利用Java Application运行测试
---------------------------------ChapterMain.java------------------------------------------
package com.test.main;
import org.apache.ibatis.session.SqlSession;
import com.test.mapper.TestClassMapper;
import com.test.model.TestClass;
import com.test.util.SqlSessionFactoryUtil;
/**
* main方法,利用Java Application运行
*
* TODO(这里描述这个类补充说明 – 可选)
* @author LHX
* @email
* @date 2018年7月18日-下午2:39:08
* @version 1.0.0
*/
public class ChapterMain {
public static void main( String[] args ){
SqlSession sqlSession = null;
try{
sqlSession = SqlSessionFactoryUtil.openSqlSession();
TestClassMapper testClassMapper = sqlSession.getMapper( TestClassMapper.class );
TestClass testClass = new TestClass();
testClass.setName( "测试" );
testClassMapper.insertTestClass( testClass );
testClassMapper.deleteTestClass( 1L );
sqlSession.commit();
}catch( Exception ex){
ex.printStackTrace();
sqlSession.rollback();
}finally{
if(sqlSession != null){
sqlSession.close();
}
}
}
}
log4j会打印Mybatis的运行轨迹,重要的是可以打印出参数以及SQL。
源码地址:https://download.csdn.net/download/lihuaxin_bj/10549124