spring揭秘15-spring集成数据访问技术(orm框架)总结

【README】

本文总结自《spring揭秘》,作者王福强,非常棒的一本书,墙裂推荐;



【1】spring集成数据访问技术总结

【1.1】解耦数据访问资源与业务逻辑

1)数据访问资源管理,通过模版方法模式来建模(如JdbcTemplate,HibernateTemplate模版类);而具体的数据访问逻辑统一由回调接口提供(策略模式,如PreparedStatementCallback,HibernateCallback回调接口);从而将数据访问资源管理和具体数据访问逻辑解耦开;

【JdbcTemplate#execute()】管理数据访问资源

private <T> T execute(PreparedStatementCreator psc, PreparedStatementCallback<T> action, boolean closeResources) throws DataAccessException {
   // .......

    Connection con = DataSourceUtils.getConnection(this.obtainDataSource()); // 获取连接 
    PreparedStatement ps = null;
    boolean var13 = false;

    Object var18;
    try {
        var13 = true;
        ps = psc.createPreparedStatement(con); // 创建预编译语句
        this.applyStatementSettings(ps); // 设置配置 
        T result = action.doInPreparedStatement(ps); // *重要: 执行回调(具体数据访问逻辑)
        this.handleWarnings((Statement)ps);
		// ......
    } catch (SQLException var14) {
		// ......
        String sql = getSql(psc);
        psc = null;
        JdbcUtils.closeStatement(ps); // 关闭语句
        ps = null;
        DataSourceUtils.releaseConnection(con, this.getDataSource()); // 释放连接 
        con = null;
        throw this.translateException("PreparedStatementCallback", sql, var14);
    } finally {
        if (var13) {
            if (closeResources) {
                if (psc instanceof ParameterDisposer) {
                    ParameterDisposer parameterDisposer = (ParameterDisposer)psc;
                    parameterDisposer.cleanupParameters();
                }

                JdbcUtils.closeStatement(ps);// 关闭语句
                DataSourceUtils.releaseConnection(con, this.getDataSource()); // 释放连接 
            }
        }
    }
    if (closeResources) {
        if (psc instanceof ParameterDisposer) {
            ParameterDisposer parameterDisposer = (ParameterDisposer)psc;
            parameterDisposer.cleanupParameters();
        }

        JdbcUtils.closeStatement(ps);
        DataSourceUtils.releaseConnection(con, this.getDataSource());// 释放连接 
    }
    return var18;
}

【JdbcTemplate#getPreparedStatementCallback()方法】回调接口实现示例

private PreparedStatementCallback<int[]> getPreparedStatementCallback(BatchPreparedStatementSetter pss, @Nullable KeyHolder generatedKeyHolder) {
    return (ps) -> {
        boolean var13 = false;
        int[] rowsAffectedArray;
        label192: {
            int[] var19;
            try {
                var13 = true;
                int batchSize = pss.getBatchSize();
                InterruptibleBatchPreparedStatementSetter var10000;
                if (pss instanceof InterruptibleBatchPreparedStatementSetter ibpss) {
                    var10000 = ibpss;
                } else {
                    var10000 = null;
                }

                InterruptibleBatchPreparedStatementSetter ipss = var10000;
                if (generatedKeyHolder != null) {
                    generatedKeyHolder.getKeyList().clear();
                }

                if (JdbcUtils.supportsBatchUpdates(ps.getConnection())) {
                    for(int i = 0; i < batchSize; ++i) {
                        pss.setValues(ps, i);
                        if (ipss != null && ipss.isBatchExhausted(i)) {
                            break;
                        }
                        ps.addBatch();
                    }

                    int[] results = ps.executeBatch();
                    if (generatedKeyHolder != null) {
                        this.storeGeneratedKeys(generatedKeyHolder, ps, batchSize);
                    }

                    rowsAffectedArray = results;
                    var13 = false;
                    break label192;
                }

                List<Integer> rowsAffected = new ArrayList();
                int ix = 0;
                while(true) {
                    if (ix < batchSize) {
                        pss.setValues(ps, ix);
                        if (ipss == null || !ipss.isBatchExhausted(ix)) {
                            rowsAffected.add(ps.executeUpdate());
                            if (generatedKeyHolder != null) {
                                this.storeGeneratedKeys(generatedKeyHolder, ps, 1);
                            }

                            ++ix;
                            continue;
                        }
                    }
                    rowsAffectedArray = new int[rowsAffected.size()];
                    for(int ixx = 0; ixx < rowsAffectedArray.length; ++ixx) {
                        rowsAffectedArray[ixx] = (Integer)rowsAffected.get(ixx);
                    }
                    var19 = rowsAffectedArray;
                    var13 = false;
                    break;
                }
            } finally {
                // ......
            }
			// ......
            return var19;
        }
        // ...... 
        return rowsAffectedArray;
    };
}


【1.2】集成数据访问技术

1)spring对数据访问技术的集成总结为以下3点:

  • 数据访问资源管理:spring通过FactoryBean管理连接工厂,而由模板方法类管理连接(如JdbcTemplate);
  • 数据访问异常转译*:spring对不同数据访问技术的异常进行转译,形成统一数据访问异常体系,使得客户端可以以统一的方式处理异常
  • 事务管理抽象*:spring对不同数据访问技术的事务管理进行抽象,形成事务管理抽象层,使得客户端可以以统一方式管理事务


【1.2.1】数据访问资源管理

1)数据访问资源,主要涉及2种资源:连接与连接工厂。通常spring通过FactoryBean管理连接工厂,连接管理由具体的模版方法类来处理;

  • 连接或者说会话资源: 指的是客户端与数据媒介进行通信的通道,每次数据访问都是通过连接访问,操作完成后关闭当前连接;
    • 如JDBC技术的连接使用Connection抽象,Hibernate技术的连接使用Session抽象;
  • 连接工厂(ConnectionFactory):创建连接的工厂对象;
    • 如JDBC技术的连接工厂使用DataSource抽象,Hibernate技术的连接使用SessionFactory抽象;
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值