一、接口定义
听名字就知道这里使用了工厂方法模式,SqlSessionFactory负责创建SqlSession对象。其中开发人员最常用的就是DefaultSqlSession
(1)SqlSession接口定义
public interface SqlSession extends Closeable { // 泛型方法,参数表示使用的查询SQL语句,返回值为查询的结果对象 <T> T selectOne(String statement); // 第二个参数表示需要用户传入的实参,也就是SQL语句绑定的实参 <T> T selectOne(String statement, Object parameter); // 查询结果集有多条记录,会封装成结果对象列表返回 <E> List<E> selectList(String statement); <E> List<E> selectList(String statement, Object parameter); // 第三个参数用于限制解析结果集的范围 <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds); /** * * selectMap 方法的原理和参数都与selectList方法类型,但结果集会被映射成Map对象返回 * 其中mapKey参数指定了结果集哪一列作为map的key,其他参数同上 */ <K, V> Map<K, V> selectMap(String statement, String mapKey); <K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey); <K, V> Map<K, V> selectMap(String statement, Object parameter, String mapKey, RowBounds rowBounds); // 返回值是游标对象,参数同上 <T> Cursor<T> selectCursor(String statement); <T> Cursor<T> selectCursor(String statement, Object parameter); <T> Cursor<T> selectCursor(String statement, Object parameter, RowBounds rowBounds); // 查询的结果对象将由此处指定的handler对象处理,其余参数同上 void select(String statement, Object parameter, ResultHandler handler); void select(String statement, ResultHandler handler); void select(String statement, Object parameter, RowBounds rowBounds, ResultHandler handler); // 执行insert语句 int insert(String statement); int insert(String statement, Object parameter); // 执行update语句 int update(String statement); int update(String statement, Object parameter); // 执行delete int delete(String statement); int delete(String statement, Object parameter); // 提交事务 void commit(); void commit(boolean force); // 事务回滚 void rollback(); void rollback(boolean force); // 将请求刷新到数据库 List<BatchResult> flushStatements(); // 关闭当前session @Override void close(); // 清空session 缓存 void clearCache(); // 获取Configuration 对象 Configuration getConfiguration(); // 获取type 对象的Mapper对象 <T> T getMapper(Class<T> type); // 获取该Sqlsession 对象的数据库连接 Connection getConnection(); }
SqlSession数据库的C、R、U、D及事务处理接口,你懂的。
(2)SqlSessionFactory
public interface SqlSessionFactory { SqlSession openSession(); SqlSession openSession(boolean autoCommit); SqlSession openSession(Connection connection); SqlSession openSession(TransactionIsolationLevel level); SqlSession openSession(ExecutorType execType); SqlSession openSession(ExecutorType execType, boolean autoCommit); SqlSession openSession(ExecutorType execType, TransactionIsolationLevel level); SqlSession openSession(ExecutorType execType, Connection connection); Configuration getConfiguration(); }
这个大家也都懂的
SqlSession实现类:DefaultSqlSession和SqlSessionManager
SqlSessionFactory实现类:DefaultSqlSessionFactory和SqlSessionManager
(3)DefaultSqlSession
@Override public int update(String statement, Object parameter) { try { dirty = true; MappedStatement ms = configuration.getMappedStatement(statement); return executor.update(ms, wrapCollection(parameter)); } catch (Exception e) { throw ExceptionFactory.wrapException("Error updating database. Cause: " + e, e); } finally { ErrorContext.instance().reset(); } }
@Override public <E> List<E> selectList(String statement, Object parameter, RowBounds rowBounds) { try { MappedStatement ms = configuration.getMappedStatement(statement); return executor.query(ms, wrapCollection(parameter), rowBounds, Executor.NO_RESULT_HANDLER); } catch (Exception e) { throw ExceptionFactory.wrapException("Error querying database. Cause: " + e, e); } finally { ErrorContext.instance().reset(); } }
这里主要看这两个方法,因为delete和insert最终执行掉用的都是update方法,查询就更不用说了。从代码上看都是从configuration对象中获取MappedStatement 对象 然后把事情交给小弟Executor去执行,这里用了很典型的策略设计模式,这个关于Executor 后面介绍。
(4)DefaultSqlSessionFactory
/** * 通过数据源获取数据库连接,并创建Executor以及DefaultSqlSession对象 */ private SqlSession openSessionFromDataSource(ExecutorType execType, TransactionIsolationLevel level, boolean autoCommit) { Transaction tx = null; try { final Environment environment = configuration.getEnvironment(); final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment); tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit); final Executor executor = configuration.newExecutor(tx, execType); return new DefaultSqlSession(configuration, executor, autoCommit); } catch (Exception e) { closeTransaction(tx); // may have fetched a connection so lets call close() throw ExceptionFactory.wrapException("Error opening session. Cause: " + e, e); } finally { ErrorContext.instance().reset(); } } /** * 用户提供数据库连接对象,使用该数据库连接对象创建Executor和DefaultSqlSession对象 */ private SqlSession openSessionFromConnection(ExecutorType execType, Connection connection) { try { boolean autoCommit; try { autoCommit = connection.getAutoCommit(); } catch (SQLException e) { // Failover to true, as most poor drivers // or databases won't support transactions autoCommit = true; } final Environment environment = configuration.getEnvironment(); final TransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment); final Transaction tx = transactionFactory.newTransaction(connection); final Executor executor = configuration.newExecutor(tx, execType); return new DefaultSqlSession(configuration, executor, autoCommit); } catch (Exception e) { throw ExceptionFactory.wrapException("Error opening session. Cause: " + e, e); } finally { ErrorContext.instance().reset(); } }
DefaultSqlSessionFactory主要提供了两种创建DefaultSqlSession对象的方式,一种是通过数据源获取数据库连接,并创建Executor以及DefaultSqlSession对象,另一种是用户提供数据库连接对象,使用该数据库连接对象创建Executor和DefaultSqlSession对象。
(5)SqlSessionManager
SqlSessionManager同时实现SqlSession接口和SqlSessionFactory接口,也就是同时提供了创建SqlSession对象以及SqlSession对象操作数据库的功能。SqlSessionManager与DefaultSqlSessionFactory的主要不同点是SqlSessionManager提供了两种模式,一种是和DefaultSqlSessionFactory的行为相同,同一线程每次访问数据库就都会创建新的DefaultSqlSession,第二种是通过ThreadLocal变量记录当前线程的SqlSession对象,避免同一线程多次创建SqlSession对象。至于使用动态代理的目的,是为了通过拦截器InvocationHandler,增强目标target的方法调用。
private final SqlSessionFactory sqlSessionFactory; // SqlSession的代理对象 会使用JDK的动态代理方式实现 private final SqlSession sqlSessionProxy; /** * ThreadLocal 变量,记录一个与当前线程绑定的SqlSession对象 * localSqlSession 中记录的SqlSession对象的代理对象,在SqlSessionManager初始化的时候 */ private final ThreadLocal<SqlSession> localSqlSession = new ThreadLocal<SqlSession>();
/** * SqlSessionManager 的私有构造方法 */ private SqlSessionManager(SqlSessionFactory sqlSessionFactory) { this.sqlSessionFactory = sqlSessionFactory; // 使用动态代理生成SqlSession的代理对象 this.sqlSessionProxy = (SqlSession) Proxy.newProxyInstance( SqlSessionFactory.class.getClassLoader(), new Class[]{SqlSession.class}, new SqlSessionInterceptor()); } /** * 通过newInstance方法创建SqlSessionManager对象 * @param reader * @return */ public static SqlSessionManager newInstance(Reader reader) { return new SqlSessionManager(new SqlSessionFactoryBuilder().build(reader, null, null)); }
// 内部类 private class SqlSessionInterceptor implements InvocationHandler { public SqlSessionInterceptor() { // Prevent Synthetic Access } @Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { // 获取当前线程绑定的SqlSession对象 final SqlSession sqlSession = SqlSessionManager.this.localSqlSession.get(); if (sqlSession != null) {// 第二种模式 try { return method.invoke(sqlSession, args); } catch (Throwable t) { throw ExceptionUtil.unwrapThrowable(t); } } else {// 第一种模式 创建新的SqlSession final SqlSession autoSqlSession = openSession(); try { final Object result = method.invoke(autoSqlSession, args); autoSqlSession.commit(); return result; } catch (Throwable t) { autoSqlSession.rollback(); throw ExceptionUtil.unwrapThrowable(t); } finally { autoSqlSession.close(); } } } }