手写mybatis(五):事务

文末附有源码地址

博客为代码完成后才开始整理,展示的代码都是最终代码

介绍:

个人学习,代码写的不够好,有点乱
通过学习mybatis源码模拟实现Mybatis(在完善)
已实现:
crud(实现XML配置,注解配置写过一点,原理差不多不写了)、
事务、
数据库连接池、
动态sql(一部分,原理没问题了,以后有时间再完善)、
一级二级缓存

一、从使用开始

单独使用mybatis时,使用sqlsession来处理事务。你一定看过下面的代码:

SqlSession session = factory.openSession(true);
SqlSession session = factory.openSession();
session.commit();

为了实现mybatis事务,通过模仿mybatis写出下面几个类:
手写mybatis(五):事务_第1张图片

二、类

首先我们创造出TransactionFactoryTransaction接口。

public interface TransactionFactory {

    Transaction newTransaction(Connection conn, boolean autoCommit);

    Transaction newTransaction(DataSource dataSource, boolean autoCommit);

}

通过工厂TransactionFactory根据不同的配置创建出Transaction。

public interface Transaction {

    Connection getConnection() throws SQLException;


    void commit() throws SQLException;


    void rollback() throws SQLException;


    void close() throws SQLException;

    boolean isAutoCommit() throws SQLException;

    void setAutoCommit(boolean autoCommit);

}

TransactionIsolationLevel是一个枚举类,定义了事务隔离级别。

NONE(Connection.TRANSACTION_NONE),
READ_COMMITTED(Connection.TRANSACTION_READ_COMMITTED),
READ_UNCOMMITTED(Connection.TRANSACTION_READ_UNCOMMITTED),
REPEATABLE_READ(Connection.TRANSACTION_REPEATABLE_READ),
SERIALIZABLE(Connection.TRANSACTION_SERIALIZABLE),

我们创造JdbcTransaction 实现Transaction 接口:

public class JdbcTransaction implements Transaction {
    protected Connection connection;
    protected DataSource dataSource;
    protected TransactionIsolationLevel level;
    protected boolean autoCommit;

    public JdbcTransaction(Connection conn, boolean autoComm) {
        this.connection = conn;
        this.autoCommit = autoComm;
    }

    public JdbcTransaction(DataSource dataSource) {
        this.dataSource = dataSource;
    }

    public JdbcTransaction(DataSource ds, TransactionIsolationLevel desiredLevel, boolean desiredAutoCommit) {
        dataSource = ds;
        level = desiredLevel;
        autoCommit = desiredAutoCommit;
    }

    @Override
    public Connection getConnection() throws SQLException {
        if (connection == null) {
            openConnection();
        }
        return connection;
    }

    public void setConnection(Connection connection) {
        this.connection = connection;
    }

    @Override
    public void commit() throws SQLException {
        connection.commit();
    }

    @Override
    public void rollback() throws SQLException {
        connection.rollback();
    }

    @Override
    public void close() throws SQLException {
        if (connection != null) {
            /**若是返回连接池需重置*/
            resetAutoCommit();
            connection.close();
        }
    }

    protected void resetAutoCommit() {
        try {
            if (!connection.getAutoCommit()) {

                connection.setAutoCommit(true);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    protected void openConnection() throws SQLException {
        connection = dataSource.getConnection();
        if (level != null) {
            connection.setTransactionIsolation(level.getLevel());
        }
        setDesiredAutoCommit(autoCommit);
    }

    protected void setDesiredAutoCommit(boolean desiredAutoCommit) {
        try {
            if (connection.getAutoCommit() != desiredAutoCommit) {
                connection.setAutoCommit(desiredAutoCommit);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    public DataSource getDataSource() {
        return dataSource;
    }

    public void setDataSource(DataSource dataSource) {
        this.dataSource = dataSource;
    }

    public TransactionIsolationLevel getLevel() {
        return level;
    }

    public void setLevel(TransactionIsolationLevel level) {
        this.level = level;
    }

    @Override
    public boolean isAutoCommit() {
        return autoCommit;
    }

    @Override
    public void setAutoCommit(boolean autoCommit) {
        this.autoCommit = autoCommit;
    }
}

将DataSource置于JdbcTransaction 中,关闭连接是调用事务的方法。

private void release(Connection con, PreparedStatement pstm, ResultSet rs) {
        if (con != null) {
            try {
                if (transaction.isAutoCommit()) {
                    transaction.close();
                }

            } catch (Exception e) {
                throw new MybatisException("资源释放异常", e);
            }
        }
        if (rs != null) {
            try {
                rs.close();
            } catch (Exception e) {
                throw new MybatisException("资源释放异常", e);
            }
        }

        if (pstm != null) {
            try {
                pstm.close();
            } catch (Exception e) {
                throw new MybatisException("资源释放异常", e);
            }
        }
    }
 @Override
    public void close() {
        localCache.clear();
        try {
            transaction.close();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void clearLocalCache() {
        if (!closed) {
            localCache.clear();
        }
    }

    @Override
    public void rollback() {
        try {
            transaction.rollback();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void commit() {
        try {
            transaction.commit();
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

最终在Executor中执行事务的各种操作。

项目地址

github:https://github.com/Alice-175/Mybaits

gitee:https://gitee.com/alice-175/Mybaits

你可能感兴趣的:(自定义框架,java,开发语言,后端,mybatis)