当前位置: 首页 > news >正文

IntelliJ IDEA 集成 ShardingSphere-JDBC 访问分库分表

背景

众所周知,IntelliJ IDEA 是 Java 领域常用的开发工具之一,IDEA Ultimate(旗舰版)或其他例如 DataGrip 等 Intellij 平台的工具都集成了对数据库的访问能力。

但是,对于做了分库分表的项目,直接使用 IDEA 连接数据库只能访问具体的库、表。假如开发测试过程中,需要执行一些不带分片条件的查询语句,直连数据库的话只能手动逐个库表查询。

要解决分库分表数据访问的问题,Apache ShardingSphere 还有 ShardingSphere-Proxy,可以通过 Proxy 实现开发测试过程中的分库分表数据访问。但 Proxy 毕竟是独立进程,部署需要额外的资源与操作。考虑到:

  • 部分项目只通过 ShardingSphere-JDBC 访问分库分表,没有引入 ShardingSphere-Proxy 的条件。
  • 测试环境没有可供 Proxy 部署的资源,每次开发测试使用 IDEA 时,还要再单独本地启动一个 Proxy,相对麻烦。

所以,我们能否直接把 ShardingSphere-JDBC 集成到 IDEA 的数据库工具中,在 IDEA 内直接用逻辑 SQL 访问数据?

步骤

打包 ShardingSphere-JDBC 并在 IDEA 新建自定义数据库驱动

本文 JAR 的打包可以参考:https://github.com/TeslaCN/shardingsphere-all-in-one

对于使用依赖管理的项目,JAR 数量的多少对于开发者来说相对透明,引入依赖改改 POM 文件即可。但如果需要集成 ShardingSphere 的项目没有 Maven 或 Gradle 依赖管理(甚至没有源码),引入 ShardingSphere 可能是一项麻烦的事情。

Apache ShardingSphere 是一个模块拆分非常细的项目。当你只把基本的 ShardingSphere-JDBC 引入项目,你会发现项目依赖 JAR 包瞬间多了 100+ org.apache.shardingsphere 开头的 JAR,且该数量不包含 ShardingSphere 的第三方依赖。

        <dependency><groupId>org.apache.shardingsphere</groupId><artifactId>shardingsphere-jdbc</artifactId><version>5.5.0</version><exclusions><exclusion><groupId>org.apache.shardingsphere</groupId><artifactId>shardingsphere-test-util</artifactId></exclusion></exclusions></dependency>

本质就是引入 ShardingSphere-JDBC 的所有依赖,通过 maven-shade-plugin 打包为单个 JAR,以便引入 IDEA。

Apache ShardingSphere 官方提供了 ShardingSphere-JDBC 二进制包 的下载,但该包内 仅包含了 ShardingSphere-JDBC 的 JAR,不包括所有第三方依赖 ,所以这个包的实际应用场景比较受限。

在这里插入图片描述

踩坑:报错 SPI 找不到实现类

当然,事情不会那么顺利。当我们把配置文件准备好,填写了正确的 ShardingSphere JDBC URL 后,测试连接发现报错找不到 SPI 实现类。

此处使用的是绝对路径指定配置文件,参考文档:

jdbc:shardingsphere:absolutepath:/home/wuweijie/dev/shardingsphere/config-sharding.yaml

在这里插入图片描述
打开 IDEA 日志,发现如下报错。

2024-08-11 21:50:38,554 [22072396]   WARN - #c.i.d.d.BaseDatabaseErrorHandler$UnknownErrorInfo - SPI-00001: No implementation class load from SPI 'org.apache.shardingsphere.infra.url.spi.ShardingSphereURLLoader' with type 'absolutepath:'.
org.apache.shardingsphere.infra.spi.exception.ServiceProviderNotFoundException: SPI-00001: No implementation class load from SPI 'org.apache.shardingsphere.infra.url.spi.ShardingSphereURLLoader' with type 'absolutepath:'.at org.apache.shardingsphere.infra.spi.type.typed.TypedSPILoader.lambda$getService$1(TypedSPILoader.java:110)at java.base/java.util.Optional.orElseThrow(Optional.java:403)at org.apache.shardingsphere.infra.spi.type.typed.TypedSPILoader.lambda$getService$2(TypedSPILoader.java:110)at java.base/java.util.Optional.orElseGet(Optional.java:364)at org.apache.shardingsphere.infra.spi.type.typed.TypedSPILoader.getService(TypedSPILoader.java:110)at org.apache.shardingsphere.infra.spi.type.typed.TypedSPILoader.getService(TypedSPILoader.java:97)at org.apache.shardingsphere.infra.url.core.ShardingSphereURLLoadEngine.<init>(ShardingSphereURLLoadEngine.java:39)at org.apache.shardingsphere.driver.jdbc.core.driver.DriverDataSourceCache.createDataSource(DriverDataSourceCache.java:56)at org.apache.shardingsphere.driver.jdbc.core.driver.DriverDataSourceCache.lambda$get$0(DriverDataSourceCache.java:50)at java.base/java.util.concurrent.ConcurrentHashMap.computeIfAbsent(ConcurrentHashMap.java:1708)at org.apache.shardingsphere.driver.jdbc.core.driver.DriverDataSourceCache.get(DriverDataSourceCache.java:50)at org.apache.shardingsphere.driver.ShardingSphereDriver.connect(ShardingSphereDriver.java:71)at com.intellij.database.remote.jdbc.helpers.JdbcHelperImpl.connect(JdbcHelperImpl.java:790)at com.intellij.database.remote.jdbc.impl.RemoteDriverImpl.connect(RemoteDriverImpl.java:153)

难道是我打的 shade 包出问题了?
检查 JAR 包发现,SPI 的 services 文件和 absolutepath 的 class 文件都在。
在这里插入图片描述
在这里插入图片描述

于是搜了下 IDEA 加载 SPI 的问题,发现 IDEA 的插件也有无法加载 SPI 实现类的问题:ServiceLoader issues and locating folders inside the plugin

大致意思:SPI 不生效是因为 IDEA 使用了独立的类加载器加载插件导致的。

那这个问题也不是完全无解,数据库插件的 Expert options 中可以去除勾选 Isolate class path

在这里插入图片描述
去除勾选后 SPI 找不到实现类的问题就解决了。

小结:当项目集成 ShardingSphere 后报错找不到 SPI 时,关注一下与类加载器是否有关系。

再踩坑:报错 StackOverflowError

在这里插入图片描述
查 IDEA 日志发现,爆栈的错误信息如下,明显是日志实现发生了问题。

Caused by: java.lang.StackOverflowErrorat org.slf4j.jul.JDK14LoggerAdapter.log(JDK14LoggerAdapter.java:167)at org.slf4j.bridge.SLF4JBridgeHandler.callLocationAwareLogger(SLF4JBridgeHandler.java:221)at org.slf4j.bridge.SLF4JBridgeHandler.publish(SLF4JBridgeHandler.java:303)at java.logging/java.util.logging.Logger.log(Logger.java:983)at org.slf4j.jul.JDK14LoggerAdapter.innerNormalizedLoggingCallHandler(JDK14LoggerAdapter.java:156)at org.slf4j.jul.JDK14LoggerAdapter.log(JDK14LoggerAdapter.java:172)at org.slf4j.bridge.SLF4JBridgeHandler.callLocationAwareLogger(SLF4JBridgeHandler.java:221)at org.slf4j.bridge.SLF4JBridgeHandler.publish(SLF4JBridgeHandler.java:303)at java.logging/java.util.logging.Logger.log(Logger.java:983)at org.slf4j.jul.JDK14LoggerAdapter.innerNormalizedLoggingCallHandler(JDK14LoggerAdapter.java:156)at org.slf4j.jul.JDK14LoggerAdapter.log(JDK14LoggerAdapter.java:172)at org.slf4j.bridge.SLF4JBridgeHandler.callLocationAwareLogger(SLF4JBridgeHandler.java:221)at org.slf4j.bridge.SLF4JBridgeHandler.publish(SLF4JBridgeHandler.java:303)at java.logging/java.util.logging.Logger.log(Logger.java:983)

此时笔者想起,IDEA 自从 2022.1 版本起使用 java.util.logging 代替第三方日志实现:Removing log4j from the IntelliJ Platform

ShardingSphere 内部使用的 Guava EventBus 默认以 java.util.logging 作为日志输出框架,为了将 EventBus 日志与 ShardingSphere-Proxy 的日志输出统一,ShardingSphere 通过 jul-to-slf4j 将日志输出统一到 slf4j 了。由于笔者当时没有考虑到与 ShardingSphere-JDBC 集成的项目可能会把 java.util.logging 作为日志输出框架,jul-to-slf4j 直接应用到了 infra 类上面(对 JDBC 与 Proxy 都生效)。

Bridges error logs which printed by ShardingSphereEventBus to slf4j #17541

由此引发的问题:假如集成 ShardingSphere 的项目本身使用 java.util.logging 作为日志框架,集成就会发生日志实现冲突,可能发生的问题包括但不限于本文中的 StackOverflowError

笔者针对该问题提交的 PR 已被合并,将随 ShardingSphere 下一版本发布:
Make jul-to-slf4j work in ShardingSphere-Proxy only #32347

集成初步完成

Test Connection 操作成功后,就可以在 Console 中执行逻辑 SQL 了。
在这里插入图片描述

打开 IDEA 的日志,可以在日志中找到逻辑 SQL 与实际执行的物理 SQL。
在这里插入图片描述

之所以说集成是“初步”完成的原因,是 ShardingSphere-JDBC 对元数据查询的支持有限,可能没有办法像直连数据库一样在 IDEA 中正确展示已有的数据库和表。

后续笔者会进一步研究 IDEA 加载数据源的库表的实现,尝试让 IDEA 能够加载 ShardingSphere-JDBC 的逻辑库与逻辑表。


http://www.mrgr.cn/news/4228.html

相关文章:

  • Ubuntu安装Mysql最新版本
  • 49. 字母异位词分组
  • stm32—IIC
  • 宠物掉毛、有异味怎么办?怎么选择宠物空气净化器?
  • 自然语言处理系列三十五》 语义相似度》基于深度学习的语义相似度算法原理
  • 【Temporal】Server启动逻辑
  • 数据库MySQL多表设计、查询
  • 【Redis】如何从单机架构演化为分布式系统
  • 【Java日志系列】Logback日志框架
  • ⌈ 传知代码 ⌋ DETR[端到端目标检测]
  • Metasploit漏洞利用系列(八):MSF渗透测试 - PHPCGI漏洞利用实战
  • 基于PHP+MySQL组合开发的DIY分销商城小程序源码系统 附带源代码包以及搭建部署教程
  • hyperf 协程作用和相关的方法
  • 通配符证书:轻松管理您的子域名安全
  • Git基础使用
  • NO呼气检测在临床应用重要性
  • HTTP请求的流转路径,从Tomcat到SpringMVC
  • Linux: 忘记密码的解决方法,passwd
  • EmguCV学习笔记 VB.Net 4.1 颜色变换
  • C++模板方法TemplateMethod