sharding-JDBC源码分析(一)标准JDBC接口实现

希望读者看完Sharding-JDBC系列文章后,掌握分库分表核心知识点,了解实现原理,自行实现简单的嵌入式分库分表组件,另外也希望读者思考为什么分库分表?以及分库分表后带来的问题?以及如何处理该类问题等,这也是面试中常见知识点。

1、JDBC标准接口

JDBC是J2EE的标准规范之一,J2EE就是为了规范JAVA解决企业级应用开发制定的一系列规范,JDBC也不例外。

JDBC是用于Java编程语言和数据库之间的数据库无关连接的标准Java API。换句话说,使用JAVA语言连接数据库进行操作,就需要使用JDBC API。

统一的JDBC API接口,屏蔽了底层数据库的细节,可以使用一致性的编码(跨数据库)对数据库进行操作。通过JDBC将JAVA应用于数据库访问连接进行解耦,可以相互独立发展,又能够结合使用。

各数据库提供的驱动实现JDBC标准 API,访问数据库,应用不用为访问不同数据库而在编码层进行适配

Sharding-JDBC处理也不例外,原理相同。sharding-JDBC实现标准JDBC协议外外提供接口,比如ShardingConnection、ShardingStatement等供外部使用,清楚JDBC后,Sharding-JDBC就好理解了,下来分析sharding-JDBC实现JDBC四大接口,后面对sharding-JDBC简称sharding

2、JDBC四大接口实现

2.1、 Connection

sharding中shardingConnection实现了标准的JDBC Connection接口,首先看下类关系图

抽象类AbstractUnsupportedOperationConnection实现Connection原生接口,其中对于sharding中不支持Connection的方法在此类中抛异常

 @Override
    public final CallableStatement prepareCall(final String sql) throws SQLException {
        throw new SQLFeatureNotSupportedException("prepareCall");
    }
   ......
    
    @Override
    public final CallableStatement prepareCall(final String sql, final int resultSetType, final int resultSetConcurrency) throws SQLException {
        throw new SQLFeatureNotSupportedException("prepareCall");
    }

AbstractConnectionAdapter中实现了功能逻辑,包括创建连接,关闭连接等,该类中有三个需要掌握的地方,个人觉得不错,可以提升编码能力

  • ForceExecuteTemplate 类提供执行模板方法参数是一个collection 和callbackForceExecuteCallback 回调接口
    public void execute(final Collection<T> targets, final ForceExecuteCallback<T> callback) throws SQLException {
        Collection<SQLException> exceptions = new LinkedList<>();
        for (T each : targets) {
            try {
                callback.execute(each);
            } catch (final SQLException ex) {
                exceptions.add(ex);
            }
        }
        throwSQLExceptionIfNecessary(exceptions);
    }

自己体会这样写的好处。

  • RootInvokeHook钩子方法

通过SPI方式注册钩子方法,记录调用过程,可以有多种实现,这种扩展方式比较灵活,易于扩展,可以方便的适配不同的平台对调用链信息采集,

public interface RootInvokeHook {
    
    /**
     * Handle when root invoke started.
     */
    void start();
    
    /**
     * Handle when root invoke finished.
     * 
     * @param connectionCount connection count
     */
    void finish(int connectionCount);
}

SPI实现

public final class SPIRootInvokeHook implements RootInvokeHook {
    
    private final Collection<RootInvokeHook> rootInvokeHooks = NewInstanceServiceLoader.newServiceInstances(RootInvokeHook.class);
    
    static {
        NewInstanceServiceLoader.register(RootInvokeHook.class);
    }
    
    @Override
    public void start() {
        for (RootInvokeHook each : rootInvokeHooks) {
            each.start();
        }
    }
    
    @Override
    public void finish(final int connectionCount) {
        for (RootInvokeHook each : rootInvokeHooks) {
            each.finish(connectionCount);
        }
    }
}

流程开始调用

 protected AbstractConnectionAdapter() {
        rootInvokeHook.start();
    }

流程结束

 public final void close() throws SQLException {
        closed = true;
        MasterVisitedManager.clear();
        TransactionTypeHolder.clear();
        int connectionSize = cachedConnections.size();
        try {
            forceExecuteTemplateForClose.execute(cachedConnections.entries(), new ForceExecuteCallback<Entry<String, Connection>>() {
        
                @Override
                public void execute(final Entry<String, Connection> cachedConnections) throws SQLException {
                    cachedConnections.getValue().close();
                }
            });
        } finally {
            cachedConnections.clear();
            rootInvokeHook.finish(connectionSize);
        }
    }

可以利用钩子方法统计SQL执行时间等,这种扩展设计方法可以学习。

2.2、Statement

sharding中shardingStatement实现Statement接口,shardingPrepareStatement实现PreparedStatement

抽象类作用与Connection基本相似,这里不重复介绍,主要看shardingstatement与SharingPrepareStatement

2.3、ResultSet

sharding-JDBC 中shardingResultSet实现了ResultSet接口,主要对结果集进行处理,以前在单库场景中操作的单个resultSet,现在可能返回多个,需要对结果集进行处理

shardingResultSet有个成员变量

private final MergedResult mergeResultSet

这是一个接口,主要对不同的结果集处理,看下实现就可以明白大概意思

这里细节不做分析,后边会针对结果集合并有专门章节进行分析。结果集合并在分库分表中间件的实现中算是个难点。

2.4、DataSource

ShardingDataSource实现了DataSource接口,提供获取connection方法

    @Override
    public final ShardingConnection getConnection() {
        return new ShardingConnection(getDataSourceMap(), runtimeContext, TransactionTypeHolder.get());
    }

3、结束语

主要对Sharding-JDBC实现标准的JDBC协议做了整体介绍,以及Sharding-JDBC中入口,这是实现一个ORM必不可少的知识点,比如Mybatis等,后面章节会对分库分表路由模块、SQL执行模块、结果集合并模块的源码会细致的进行分析,希望读者看完这一系列文章后,可以自己实现简化版的分库分表组件。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值