原生mybatis创建SqlSession的流程:
SqlSession sqlSession = null; try { sqlSession = sqlSessionFactory.openSession(); sqlSession.insert("cn.jarjar.dao.BlogMapper.insertBlog", blog); sqlSession.commit(true) } catch (Exception e) { e.printStackTrace(); sqlSession.rollback(true); } finally { sqlSession.close(); }
缺点:
原生seesion操作就像原始的JDBC对象一样,必须按照:新建连接->执行SQL->提交(查询不需要)->如果操作数据存在异常需要回滚->释放数据库连接。
每个SqlSession新建之后必须释放,不然会造成数据库连接泄露的危险
SqlSession是个有状态的对象,是无法进行复用的,所以只能局限于request或者方法的范围,也就是所谓的线程不安全
把seesion托管给spring:
SqlSessionTemplate
public SqlSessionTemplate(SqlSessionFactory sqlSessionFactory, ExecutorType executorType,PersistenceExceptionTranslator exceptionTranslator) { notNull(sqlSessionFactory, "Property 'sqlSessionFactory' is required"); notNull(executorType, "Property 'executorType' is required"); this.sqlSessionFactory = sqlSessionFactory; this.executorType = executorType; this.exceptionTranslator = exceptionTranslator; this.sqlSessionProxy = (SqlSession) newProxyInstance(SqlSessionFactory.class.getClassLoader(),new Class[] { SqlSession.class },new SqlSessionInterceptor()); }
SqlSessionInterceptor
private class SqlSessionInterceptor implements InvocationHandler { @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { //创建sqlSession对象 SqlSession sqlSession = getSqlSession(SqlSessionTemplate.this.sqlSessionFactory,SqlSessionTemplate.this.executorType, SqlSessionTemplate.this.exceptionTranslator); try { //通过sqlSession对象执行真正的crud操作 Object result = method.invoke(sqlSession, args); return result; } catch (Throwable t) { //异常处理 }finally { if (sqlSession != null) { // 释放sqlSession closeSqlSession(sqlSession, SqlSessionTemplate.this.sqlSessionFactory); } } } }
托管流程:spring创建了SqlSessionTemplate,在创建SqlSessionTemplate的时候提供了方法拦截器 SqlSessionInterceptor;SqlSessionTemplate实现了SqlSession接口,所以SqlSessionInterceptor会对SqlSessionTemplate中所有SqlSession接口定义的方法进行拦截;也就是说,整合spring之后的crud操作都会经过SqlSessionTemplate类,并且所有crud方法会被SqlSessionInterceptor拦截;最终SqlSessionTemplate通过代理拦截,并且通过SqlSessionHolder实现的sqlsession线程安全和自动新建和释放连接。