手写源码之路(四):Mybatis框架篇(3)会话篇

手写源码之路(四):Mybatis框架篇(3)会话篇

上篇文章 我们知道了SqlSessionFactoryBuilder类解析配置文件构建出SqlSessionFactory,一看类名就知道使用了工厂模式了,SqlSessionFactory负责生产SqlSession对象,SqlSession就是数据库的会话了,由会话对象负责SQL语句的执行,先看看源码:

SqlSession

/**
 * @author Mr.Wang
 * @Description:
 * @date 2019/5/11 20:01
 */
public interface MySqlSession {

    /**
     * 查询带条记录
     *
     * @param statementKey
     * @param args
     * @return
     * @see
     */
    <T> T selectOne(String statementKey, Object[] args);

    /**
     * 查询多条记录
     *
     * @param statementKey
     * @param args
     * @return
     * @see
     */
    <E> List<E> selectList(String statementKey, Object[] args);

    /**
     * 查询记录返回Map
     *
     * @param statementKey
     * @param args
     * @param <K>
     * @param <V>
     * @return
     */
    <K, V> Map<K, V> selectMap(String statementKey, Object[] args);

    /**
     * insert
     *
     * @param statementKey
     * @param args
     */
    int insert(String statementKey, Object[] args);

    /**
     * update
     *
     * @param statementKey
     * @param args
     */
    int update(String statementKey, Object[] args);

    /**
     * delete
     *
     * @param statementKey
     * @param args
     */
    int delete(String statementKey, Object[] args);

    /**
     * 提交
     */
    void commit();

    void commit(boolean force);

    /**
     * 回滚
     */
    void rollback();

    void rollback(boolean force);

    void close();

    void clearCache();

    /**
     * 获取mapper对象
     *
     * @param paramClass
     * @param <T>
     * @return
     */
    <T> T getMapper(Class<T> paramClass);

    /**
     * 获取配置类
     *
     * @return
     * @see
     */
    MyConfiguration getConfiguration();

    /**
     * 获取数据库连接
     *
     * @return
     */
    Connection getConnection();
}

SqlSessionFactory

/**
 * @author Mr.Wang
 * @Description: session工厂
 * @date 2019/5/11 17:40
 */
public interface MySqlSessionFactory {

    /**
     * 打开session
     *
     * @return
     */
    MySqlSession openSession();

    MySqlSession openSession(boolean autoCommit);

    MySqlSession openSession(Connection connection);

    MySqlSession openSession(MyTransactionIsolationLevel level);

    MySqlSession openSession(MyExecutorType execType);

    MySqlSession openSession(MyExecutorType execType, boolean autoCommit);

    MySqlSession openSession(MyExecutorType execType, MyTransactionIsolationLevel level);

    MySqlSession openSession(MyExecutorType execType, Connection connection);

    MyConfiguration getConfiguration();
}

SqlSession实现类:DefaultSqlSession
SqlSessionFactory实现类:DefaultSqlSessionFactory

DefaultSqlSession

/**
 * @author Mr.Wang
 * @Description:
 * @date 2019/8/26 19:28
 */
public class MyDefaultSqlSession implements MySqlSession {

    private final MyConfiguration configuration;
    private final MyExecutor executor;

    private final boolean autoCommit;
    private boolean dirty;

    public MyDefaultSqlSession(MyConfiguration configuration, MyExecutor executor) {
        this(configuration, executor, false);
    }

    public MyDefaultSqlSession(MyConfiguration configuration, MyExecutor executor, boolean autoCommit) {
        this.configuration = configuration;
        this.executor = executor;
        this.dirty = false;
        this.autoCommit = autoCommit;
    }

    @Override
    public <T> T selectOne(String statementKey, Object[] args) {
        List<T> list = this.selectList(statementKey, args);
        if (list.size() == 1) {
            return list.get(0);
        } else if (list.size() > 1) {
            throw new RuntimeException("Expected one result (or null) to be returned by selectOne(), but found: " + list.size());
        } else {
            return null;
        }
    }

    @Override
    public <T> List<T> selectList(String statementKey, Object[] args) {
        try {
            MyMappedStatement mappedStatement = configuration.getMappedStatement(statementKey);
            return executor.query(mappedStatement, args);
        } catch (Exception e) {
            throw new RuntimeException("Error querying database.  Cause: " + e, e);
        }
    }

    @Override
    public <K, V> Map<K, V> selectMap(String statementKey, Object[] args) {
        return null;
    }

    @Override
    public int insert(String statementKey, Object[] args) {
        return update(statementKey, args);
    }

    @Override
    public int update(String statementKey, Object[] args) {
        try {
            dirty = true;
            MyMappedStatement myMapperStatement = configuration.getMappedStatement(statementKey);
            return executor.update(myMapperStatement, args);
        } catch (Exception e) {
            throw new RuntimeException("Error updating database.  Cause: " + e, e);
        }
    }

    @Override
    public int delete(String statementKey, Object[] args) {
        return update(statementKey, args);
    }

    @Override
    public void commit() {
        commit(false);
    }

    @Override
    public void commit(boolean force) {
        try {
            executor.commit(isCommitOrRollbackRequired(force));
            dirty = false;
        } catch (Exception e) {
            throw new RuntimeException("Error committing transaction.  Cause: " + e, e);
        }
    }

    @Override
    public void rollback() {
        rollback(false);
    }

    @Override
    public void rollback(boolean force) {
        try {
            executor.rollback(isCommitOrRollbackRequired(force));
            dirty = false;
        } catch (Exception e) {
            throw new RuntimeException("Error rolling back transaction.  Cause: " + e, e);
        }
    }

    @Override
    public void close() {
        try {
            executor.close(isCommitOrRollbackRequired(false));
            dirty = false;
        } finally {

        }
    }

    @Override
    public void clearCache() {
        executor.clearLocalCache();
    }

    @Override
    public <T> T getMapper(Class<T> type) {
        return configuration.<T>getMapper(type, this);
    }

    @Override
    public MyConfiguration getConfiguration() {
        return this.configuration;
    }

    @Override
    public Connection getConnection() {
        try {
            return executor.getTransaction().getConnection();
        } catch (SQLException e) {
            throw new RuntimeException("Error getting a new connection.  Cause: " + e, e);
        }
    }

    private boolean isCommitOrRollbackRequired(boolean force) {
        return (!autoCommit && dirty) || force;
    }

}

DefaultSqlSessionFactory

/**
 * @author Mr.Wang
 * @Description:
 * @date 2019/8/26 19:44
 */
public class MyDefaultSqlSessionFactory implements MySqlSessionFactory {

    public static MySqlSession sqlSession;

    private MyConfiguration configuration;

    public MyDefaultSqlSessionFactory(MyConfiguration configuration) {
        this.configuration = configuration;
    }

    @Override
    public MySqlSession openSession() {
        sqlSession = openSessionFromDataSource(configuration.getDefaultExecutorType(), null, false);
        return sqlSession;
    }

    @Override
    public MySqlSession openSession(boolean autoCommit) {
        sqlSession = openSessionFromDataSource(configuration.getDefaultExecutorType(), null, autoCommit);
        return sqlSession;
    }

    @Override
    public MySqlSession openSession(Connection connection) {
        sqlSession = openSessionFromConnection(configuration.getDefaultExecutorType(), connection);
        return sqlSession;
    }

    @Override
    public MySqlSession openSession(MyTransactionIsolationLevel level) {
        sqlSession = openSessionFromDataSource(configuration.getDefaultExecutorType(), level, false);
        return sqlSession;
    }

    @Override
    public MySqlSession openSession(MyExecutorType execType) {
        sqlSession = openSessionFromDataSource(execType, null, false);
        return sqlSession;
    }

    @Override
    public MySqlSession openSession(MyExecutorType execType, boolean autoCommit) {
        sqlSession = openSessionFromDataSource(execType, null, autoCommit);
        return sqlSession;
    }

    @Override
    public MySqlSession openSession(MyExecutorType execType, MyTransactionIsolationLevel level) {
        sqlSession = openSessionFromDataSource(execType, level, false);
        return sqlSession;
    }

    @Override
    public MySqlSession openSession(MyExecutorType execType, Connection connection) {
        sqlSession = openSessionFromConnection(execType, connection);
        return sqlSession;
    }

    @Override
    public MyConfiguration getConfiguration() {
        return this.configuration;
    }

    private MySqlSession openSessionFromDataSource(MyExecutorType execType, MyTransactionIsolationLevel level, boolean autoCommit) {
        MyTransaction tx = null;
        try {
            //获取环境对象
            final MyEnvironment environment = configuration.getEnvironment();
            //获取事务工厂对象
            final MyTransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
            //创建事务对象
            tx = transactionFactory.newTransaction(environment.getDataSource(), level, autoCommit);
            //创建执行器对象
            final MyExecutor executor = configuration.newExecutor(tx, execType);
            //创建数据库会话对象
            return new MyDefaultSqlSession(configuration, executor, autoCommit);
        } catch (Exception e) {
            closeTransaction(tx);
            throw new RuntimeException("Error opening session.  Cause: " + e, e);
        }
    }

    private MySqlSession openSessionFromConnection(MyExecutorType execType, Connection connection) {
        try {
            boolean autoCommit;
            try {
                autoCommit = connection.getAutoCommit();
            } catch (SQLException e) {
                autoCommit = true;
            }
            //获取环境对象
            final MyEnvironment environment = configuration.getEnvironment();
            //获取事务工厂对象
            final MyTransactionFactory transactionFactory = getTransactionFactoryFromEnvironment(environment);
            //创建事务对象
            final MyTransaction tx = transactionFactory.newTransaction(connection);
            //创建执行器对象
            final MyExecutor executor = configuration.newExecutor(tx, execType);
            //创建数据库会话对象
            return new MyDefaultSqlSession(configuration, executor, autoCommit);
        } catch (Exception e) {
            throw new RuntimeException("Error opening session.  Cause: " + e, e);
        }
    }

    private MyTransactionFactory getTransactionFactoryFromEnvironment(MyEnvironment environment) {
        if (environment == null || environment.getTransactionFactory() == null) {
            return new MyManagedTransactionFactory();
        }
        return environment.getTransactionFactory();
    }

    private void closeTransaction(MyTransaction tx) {
        if (tx != null) {
            try {
                tx.close();
            } catch (SQLException ignore) {

            }
        }
    }
}

可以看到,SqlSessionFactory负责打开数据库会话,SqlSession负责SQL语句的执行,有了SqlSession对象我们就可以调用getMapper方法去获取Mapper对象了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值