MyBatis(四)------MyBatis的生命周期及配置实例

目录

1、MyBatis的生命周期

1、SqlSessionFactoryBuilder

2、SqlSessionFactory

3、SqlSession

4、Mapper

2、MyBatis实例

1、配置log4j.properties日志

2、构建POJO对象

3、构建Mapper映射器

4、配置Mapper映射文件

5、配置mybatisConfig.xml全局基础文件

6、构建SqlSessionFactoryUtils工具类

7、测试


生命周期是组件的重要问题,尤其是在多线程的情况中,比如互联网应用、Socket请求等,而MyBatis也常用于多线程的环境中,错误使用会造成严重的多线程并发问题,因此,我们需要掌握MyBatis组件的生命周期。而MyBatis的生命周期就是每一个对象应该存活的时间,比如一些对象一次用完后就要关闭,使它们被JVM销毁,以免继续占用资源。

1、MyBatis的生命周期

1、SqlSessionFactoryBuilder

SqlSessionFactoryBuilder的作用在于创建SqlSessionFactory,创建成功后,SqlSessionFactoryBuilder就失去作用,所以它只能存在于创建SqlSessionFactory的方法中,而不要让其长期存在。

2、SqlSessionFactory

SqlSessionFactory可以被认为是一个数据库连接池,它的作用是创建SqlSession接口对象。因为MyBatis的本质就是Java对数据库的操作,所以SqlSessionFactory的生命周期存在于整个MyBatis的应用中,所以一旦创建了SqlSessionFactory,就要长期保存它,直至不在使用MyBatis应用,所以可以认为SqlSessionFactory的生命周期就等同与MyBatis的应用周期。

由于SqlSessionFactory是对一个数据库的连接池,所以它占据着数据库的连接资源。如果创建多个SqlSessionFactory,那么就存在多个数据库连接池,不利于对数据库资源的控制,也将导致数据库连接资源被消耗光,出现系统宕机等情况,所以尽量避免出现这种情况。因此在一般的应用中,我们往往希望SqlSessionFactory作为一个单例,让它在应用中被共享

3、SqlSession

如果说SqlSessionFactory相当于数据库连接池,那么SqlSession就相当于一个数据库连接(Connection对象),我们可以在一个事务中执行多条SQL,然后通过它的commit、rollback等方法,提交或回滚事务。所以SqlSession应该存活在一个业务请求中,处理完整个请求后,应该关闭这条连接,让它归还给SqlSessionFactory,否则数据库资源将被耗光,系统瘫痪,所以使用try...catch...finally语句来保证SqlSession正确关闭。

4、Mapper

Mapper是一个接口,它由SqlSession所创建,所以它的最大生命周期至多和SqlSession保持一致,当SqlSession关闭时,Mapper的数据库连接资源也会消失,所以Mapper的生命周期应该小于等于SqlSession的生命周期。Mapper代表的是一个请求中的业务处理,所以它应该在一个请求中,一旦处理完了相关业务,就应该废弃它。

Mybatis组件生命周期如图所示:

MyBatis(四)------MyBatis的生命周期及配置实例_第1张图片

2、MyBatis实例

这里我们做一个简单的实例,主要处理角色表的增、删、改、查,涉及的文件及其作用如下表 :

文件 作用
SysRoleMapper.java Mapper映射器接口
SysRoleMapper.xml Mapper映射器XML配置文件,描述映射关系、SQL等内容。【MyBatis核心文件】
SysRole.java POJO对象
SqlSessionFactoryUtils.java 会话工厂工具类,用于创建SqlSessionFactory和获取SqlSession对象
log4j.properties 日志配置文件
mybatisConfig.xml MyBatis的基础配置文件
SysRoleMapperConfigTest.java 测试程序

1、配置log4j.properties日志

#全局配置
#优先级:ALL < DEBUG < INFO < WARN < ERROR < FATAL < OFF
log4j.rootLogger=DEBUG, stdout
#设置为DEBUG级别,便于把详细的日志记录打印出来,便于调试。
#在生产中,可以设置为INFO级别
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 [%t] - %m%n

我们设置为DEBUG级别,以能够把最详细的日志打印出来,便于调试,在生产中可设置为INFO级别。

2、构建POJO对象

构建一个POJO对象,最终查询会映射到它上面,或将其保存到数据库中

public class SysRole {
	
    private Integer id;
    private String name;
    private String description;
    private Date createTime;
    private Date updateTime;

    /*省略setter和getter方法*/
}

3、构建Mapper映射器

采用XML方式构建映射器,它包含一个Mapper接口和一个XML映射文件。这里要实现增、删、改、查。所以定义一个接口

SysRoleMapper.Java

/**
 * 映射器接口
 */
public interface SysRoleMapper {
		
	/*[1.1]新增一条角色------->自定义主键*/
	public int insertRole(SysRole sysRole);
	/*[1.2]新增一条角色------->自增主键*/
	public int insertRole2(SysRole sysRole);
	/*[2]删除一条角色*/
	public int deleteRole(Integer id);
	/*[3]修改一条角色*/
	public int updateRole(SysRole sysRole);
	/*[4]查询一条角色*/
	public SysRole getRole(Integer id);
        /*[5]通过角色名获取整个角色列表*/
	public List findRoles(String roleName);
}

其中,insertRole表示插入一个SysRole对象;deleteRole表示删除;updateRole是修改一个SysRole对象;getRole获取一个SysRole对象;findRoles则是通过角色名称获取一个角色对象列表。我们要用一个XML文件来描述这些功能。

4、配置Mapper映射文件




	
	
		
			select LAST_INSERT_ID()
		
		insert into sys_role(name,description,createTime,updateTime)
		 	values (#{name}, #{description}, #{createTime},#{updateTime})
	
	
	
	
		insert into sys_role(name,description)
		 	values (#{name}, #{description})
	
	
	
	
	
		delete from sys_role where id = #{id}
	
	
	
	
		update sys_role set name = #{name},description = #{description}
			 where id = #{id}
	
	
	
	
	 
	
	
		id,name,description
	
	
	
	
	

这是一些比较简单的SQL语句,inser\delete、select、update、元素代表了增、删、改、查,而它们里面的元素id则标识了对应的SQL。paramterType标出了SQL返回值类型的参数,resultType则代表结果映射成为什么类型。

有了它们,我们就可以开始创建SqlSessionFactory了。首先来完成mybatisConfig.xml全局基础配置文件。

5、配置mybatisConfig.xml全局基础文件




	

	
	
	
	
	
	  
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
	
		
			
			
			
			
			
			
			
				
				
				
				
			
		
	
	
	
	
	
		
		
		
		
		
		
		
		
		
	 

使用mybatisConfig.xml文件,通过SqlSessionFactoryBuilder来构建SqlSessionFactory。由于SqlSessionFactory应该采用单例,代码如下:

6、构建SqlSessionFactoryUtils工具类

/**
 * SqlSessionFactoryUtils工具类,用于创建SqlSessionFactory和SqlSession对象
 */
public class SqlSessionFactoryUtils {
	
	private final static Class LOCK = SqlSessionFactoryUtils.class;
	// [3]定义会话工厂变量
	private static SqlSessionFactory sqlSessionFactory =null;
	//其他代码不能通过new的方式来创建它
	private SqlSessionFactoryUtils() {

	}
	public static SqlSessionFactory getSqlSessionFactory(){
		//锁,防止在多线程中多次实例化sqlSessionFactory对象,从而保证sqlSessionFactory的唯一性
		synchronized (LOCK) {
			if (sqlSessionFactory != null) {
				
			}
			//[1]mybatis全局配置文件路径
			String str = "mybatisConfig.xml";
			InputStream inputStream;
			try {
				//[2]把全局配置文件放入流中
				inputStream = Resources.getResourceAsStream(str);
				//[4]通过SqlSessionFactoryBuilder构造器的build方法创建sqlSessionFactory会话工厂
				sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
				//关闭流
				inputStream.close();
			} catch (IOException e) {
				e.printStackTrace();
				return null;
			}
			return sqlSessionFactory;
		}
		
	}
	
	//[5]通过会话工厂调用openSession方法,来创建sqlSession会话对象
	public static SqlSession openSqlSession(){
		if (sqlSessionFactory == null) {
			getSqlSessionFactory();
		}
		return sqlSessionFactory.openSession();
	}
}

构造方法中,加入private关键字,使得其他代码不能通过new的方式来创建它。而加入synchronized关键字加锁,主要是为了防止在多线程中多次实例化SqlSessionFactory对象,从而保证SqlSessionFactory的唯一性。而openSqlSession方法的作用则是创建SqlSession对象。

7、测试

public class SysRoleMapperConfigTest{
	
	private static Logger log = Logger.getLogger(SysRoleMapperConfigTest.class);
	
	/*=====================================插入一条角色记录=====================================*/
	@Test
	public void insertRole1() throws Exception{
		SqlSession sqlSession = null;
		try {
			sqlSession = SqlSessionFactoryUtils.openSqlSession();
			SysRoleMapper roleMapper = sqlSession.getMapper(SysRoleMapper.class);
			SysRole sysRole = new SysRole();
			// sysRole.setId(23);
			sysRole.setName("root2");
			sysRole.setDescription("root2");
			sysRole.setCreateTime(new Date());
			sysRole.setUpdateTime(new Date());
			int i = roleMapper.insertRole(sysRole);
			log.info("==>插入角色记录的结果:" + i);
			sqlSession.commit();
		} catch (Exception e) {
			sqlSession.rollback();
		} finally {
			if (sqlSession != null) {
				sqlSession.close();
			}
		}
	}
	
	@Test
	public void insertRole2()throws Exception{
		SqlSession sqlSession = null;
		try {
			sqlSession = SqlSessionFactoryUtils.openSqlSession();
			SysRoleMapper roleMapper = sqlSession.getMapper(SysRoleMapper.class);
			SysRole sysRole = new SysRole();
			sysRole.setName("root1000");
			sysRole.setDescription("root1000");
			int i = roleMapper.insertRole2(sysRole);
			log.info("========>>>>" + i);
			sqlSession.commit();
		} catch (Exception e) {
			sqlSession.rollback();
		} finally {
			if (sqlSession != null) {
				sqlSession.close();
			}
		}
	}
	/*=====================================删除一条角色记录=====================================*/
	@Test
	public void deleteRole(){
		SqlSession sqlSession = null;
		try {
			sqlSession = SqlSessionFactoryUtils.openSqlSession();
			SysRoleMapper roleMapper = sqlSession.getMapper(SysRoleMapper.class);
			int i = roleMapper.deleteRole(20);
			log.info("==>删除角色记录的结果:" + i);
			sqlSession.commit();
		} catch (Exception e) {
			sqlSession.rollback();
		} finally {
			if (sqlSession != null) {
				sqlSession.close();
			}
		}
	}
	/*=====================================修改一条角色记录=====================================*/
	@Test
	public void updateRole() throws Exception{
		SqlSession sqlSession = null;
		try {
			sqlSession = SqlSessionFactoryUtils.openSqlSession();
			SysRoleMapper roleMapper = sqlSession.getMapper(SysRoleMapper.class);
			SysRole sysRole = new SysRole();
			sysRole.setId(22);
			sysRole.setName("westone");
			sysRole.setDescription("westone");
			int i = roleMapper.updateRole(sysRole);
			log.info("==>修改角色记录的结果:" + i);
			sqlSession.commit();
		} catch (Exception e) {
			sqlSession.rollback();
		} finally {
			if (sqlSession != null) {
				sqlSession.close();
			}
		}
	}
	/*=====================================查询一条角色记录=====================================*/
	@Test
	public void getRoleById() throws Exception{
		SqlSession sqlSession = null;
		try {
			//获取会话对象
			sqlSession = SqlSessionFactoryUtils.openSqlSession();
			//加载Mapper接口类
			SysRoleMapper roleMapper = sqlSession.getMapper(SysRoleMapper.class);
			SysRole sysRole = roleMapper.getRole(1);
			log.info("==>根据ID查询的结果:" + sysRole.getName());
			//提交事务
			 sqlSession.commit();
		} catch (Exception e) {
			//操作出现错误时,就回滚
			sqlSession.rollback();
		}finally{
			if (sqlSession != null) {
				sqlSession.close();
			}
		}
	}
}

愿你就像早晨八九点钟的太阳,活力十足,永远年轻。

你可能感兴趣的:(MyBatis)