Spring 统一访问数据模版

使用jdbc 访问数据库按以下流程进行:
1. 准备资源
2. 启动事务
3. 在事务中执行具体数据库访问操作
4. 提交或回滚事务
5. 关闭资源,处理异常。

按照传统方式,编写任何带事务的数据访问程序时,都要重复编写上面代码。除了3是和业务相关的,1,2,4,5 步骤都一样。
所以spring 将相同的数据访问流程固化到模版类,并将数据访问中固定和变化的部分分开,同时保证模版类是线程安全的,以便多个线程访问同一个模版实例出现异常。固定的部分已在模版类准备好,而变化的部分通过回调接口开放出来,用于定义具体数据访问和结果返回操作。

spring 为不同的持久化技术提供了不同的模版类

ORM持久化技术模版类
JDBCorg.springframework.jdbc.core.JdbcTemplate
iBatisorg.springframework.orm.ibatis.SqlMapClientTemplate

等等。

我们以JdbcTemplate为例

    @Override
    public void execute(final String sql) throws DataAccessException {
        if (logger.isDebugEnabled()) {
            logger.debug("Executing SQL statement [" + sql + "]");
        }
        class ExecuteStatementCallback implements StatementCallback<Object>, SqlProvider {
            @Override
            public Object doInStatement(Statement stmt) throws SQLException {
                stmt.execute(sql);
                return null;
            }
            @Override
            public String getSql() {
                return sql;
            }
        }
        execute(new ExecuteStatementCallback());
    }

这个方法是最常用的,参数为要执行的sql语句,内部调用的是

@Override
    public <T> T execute(StatementCallback<T> action) throws DataAccessException {
        Assert.notNull(action, "Callback object must not be null");
//当前线程持有的数据库连接,保证线程安全
        Connection con = DataSourceUtils.getConnection(getDataSource());
        Statement stmt = null;
        try {
            Connection conToUse = con;
            if (this.nativeJdbcExtractor != null &&
                    this.nativeJdbcExtractor.isNativeConnectionNecessaryForNativeStatements()) {
                conToUse = this.nativeJdbcExtractor.getNativeConnection(con);
            }
            //构造statement
            stmt = conToUse.createStatement();
            applyStatementSettings(stmt);
            Statement stmtToUse = stmt;
            if (this.nativeJdbcExtractor != null) {
                stmtToUse = this.nativeJdbcExtractor.getNativeStatement(stmt);
            }
            //调用回调函数执行sql
            T result = action.doInStatement(stmtToUse);
            handleWarnings(stmt);
            return result;
        }
        catch (SQLException ex) {
            // Release Connection early, to avoid potential connection pool deadlock
            // in the case when the exception translator hasn't been initialized yet.
            JdbcUtils.closeStatement(stmt);
            stmt = null;
            //释放数据库连接
            DataSourceUtils.releaseConnection(con, getDataSource());
            con = null;
            throw getExceptionTranslator().translate("StatementCallback", getSql(action), ex);
        }
        finally {
            JdbcUtils.closeStatement(stmt);
            DataSourceUtils.releaseConnection(con, getDataSource());
        }
    }

execute方法用了模版设计模式,将获取数据库连接,创建statement,释放数据库连接封装起来,这些是固定部分;传入的sql语句通过回调传入方法中,这是变化部分。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值