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.mzph.cn/web/51019.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

中秋节月饼销售利用106短信群发平台业绩翻倍案例分析

在中秋节这一传统佳节&#xff0c;月饼作为节日的标志性食品&#xff0c;其销售市场竞争尤为激烈。为了在众多品牌中脱颖而出&#xff0c;不少月饼销售企业开始探索创新的营销方式。其中&#xff0c;利用106短信群发平台进行精准营销&#xff0c;成为众多企业实现业绩翻倍的有效…

TCP端口范围

ip_local_port_range sysctl -a | grep ip_local_port_range | head 默认情况下&#xff0c;net.ipv4.ip_local_port_range的默认值为32768-60999。这意味着本地应用程序可以使用的端口号范围为32768到60999。 sysctl -a | grep net.ipv4.ip_local_reserved_ports |head …

C++ 特殊类设计以及单例模式

目录 1 不能被拷贝 2 只能在堆上创建对象 3 只能在栈上创建对象 4 禁止在堆上创建对象 5 不能被继承的类 6 单例类 特殊类就是一些有特殊需求的类。 1 不能被拷贝 要设计一个防拷贝的类&#xff0c;C98之前我们只需要将拷贝构造以及拷贝赋值设为私有&#xff0c;同时只声明…

2 种方式申请免费 SSL 证书,阿里云 Certbot

如何使用免费的 SSL 证书&#xff0c;有时在项目中需要使用免费的 SSL 证书&#xff0c;Aliyun 提供免费证书&#xff0c;三个月有效期&#xff0c;可以直接在aliyun 申请&#xff0c;搜索 SSL 证书&#xff0c;选择测试证书。 Aliyun 证书需要每三月来来换一次&#xff0c;页…

【学习笔记】8、脉冲波形的变换与产生

本章简略记录。 8.1 单稳态触发器&#xff08;脉冲触发&#xff09; 单稳态触发器 应用于 &#xff1a;&#xff08;1&#xff09;脉冲整型&#xff08;2&#xff09;脉冲延时 &#xff08;3&#xff09;定时 单稳态触发器的工作特性&#xff1a; 没有触发脉冲作用时&#xf…

Vue项目-三级联动的路由跳转与传参

三级联动组件的路由的跳转与传参 三级联动&#xff0c;用户可以点击的&#xff1a;一级分类、二级分类和三级分类 以商城项目为例&#xff0c;Home模块跳转到Search模块&#xff0c;以及会把用户选中的产品&#xff08;产品名字、产品ID&#xff09;在路由跳转的时候&#xff…

《黑神话.悟空》:一场跨越神话与现实的深度探索

《黑神话.悟空》&#xff1a;一场跨越神话与现实的深度探索 在国产游戏日益崛起的今天&#xff0c;《黑神话.悟空》以其独特的剧情、丰富的人物设定和深刻的主题&#xff0c;成为了无数玩家翘首以盼的国产3A大作。这款游戏不仅是一次对传统故事的创新演绎&#xff0c;更是一场对…

操作系统:内存管理策略

外部碎片 当应用程序启动时&#xff0c;由操作系统负责给该应用程序分配其内存空间&#xff0c;假设此时启动了三个应用程序&#xff0c;操作系统分别给其分配了100m&#xff0c;10m和50m的内存&#xff0c;内存情况如下图 此时如果程序B下线&#xff0c;程序A和程序C之间便会…

【css】伪元素实现图片个悬停文字聚焦效果

实现重点&#xff1a; 文字覆盖在图片上&#xff1a; 通过使用 position: absolute 将 .box 文字盒子定位在图片上方。父容器 .img-wrap 使用了 position: relative 确保子元素的绝对定位在父容器的边界内生效。 创建悬停效果&#xff1a; 通过使用 &::before 和 &::…

国富基金入股的关联性与奇瑞依赖症,大昌科技业务独立性引关注

《港湾商业观察》廖紫雯 日前&#xff0c;安徽大昌科技有限公司&#xff08;以下简称&#xff1a;大昌科技&#xff09;更新招股书并完成三轮问询&#xff0c;公司冲刺深交所创业板得到进一步进展。此前&#xff0c;2023年6月&#xff0c;大昌科技IPO获深交所受理&#xff0c;…

【微信小程序】自定义组件 - 数据、方法和属性

1. data 数据 2. methods 方法 在小程序组件中&#xff0c;事件处理函数和自定义方法需要定义到 methods 节点中&#xff0c;示例代码如下&#xff1a; 3. properties 属性 在小程序组件中&#xff0c;properties 是组件的对外属性&#xff0c;用来接收外界传递到组件中的数…

杰发科技AC7840——CAN通信简介(8)_通过波特率和时钟计算SEG_1/SEG_2/SJW/PRESC

通过公式计算 * 波特率和采样点计算公式&#xff1a;* tSeg1 (S_SEG_1 2); tSeg2 (S_SEG_2 1).* BandRate (SCR_CLK / (S_PRESC 1) / ((S_SEG_1 2) (S_SEG_2 1))), SCR_CLK 为CAN 模块源时钟* SamplePoint (tSeg1 / (tSeg1 tSeg2)). {0x0D, 0x04, 0x04, 0x3B},…

数据结构——链式队列和循环队列

目录 引言 队列的定义 队列的分类 1.单链表实现 2.数组实现 队列的功能 队列的声明 1.链式队列 2.循环队列 队列的功能实现 1.队列初始化 (1)链式队列 (2)循环队列 (3)复杂度分析 2.判断队列是否为空 (1)链式队列 (2)循环队列 (3)复杂度分析 3.判断队列是否…

26.删除有序数组中的重复项---力扣

题目链接&#xff1a; . - 力扣&#xff08;LeetCode&#xff09;. - 备战技术面试&#xff1f;力扣提供海量技术面试资源&#xff0c;帮助你高效提升编程技能,轻松拿下世界 IT 名企 Dream Offer。https://leetcode.cn/problems/remove-duplicates-from-sorted-array/descript…

仿Muduo库实现高并发服务器——Server.hpp框架的简单描述

EventLoop模块在本项目中的简单使用&#xff1a; 下面这张图 是channel模块&#xff0c;poller模块&#xff0c;TimerWheel模块&#xff0c;EventLoop模块&#xff0c;LoopThreadPool模块进行组合。便于大家对这个项目的理解&#xff0c;因为代码看起来挺复杂的。 下面这个图&…

招募活动投稿展示 | 感受科技温度,从一个 LLM 应用开始

活动介绍 谷歌开发者招募活动是专为 Google 技术的爱好者及开发者们开展的活动&#xff0c;旨在鼓励大家通过多种形式 (文章/视频/coding 等) 创作与 Google 技术相关的讲解分享、实践案例或活动感受等内容&#xff0c;展示代码、框架、平台在真实世界中的生动表现&#xff0c;…

详解Spring Bean的生命周期

详解Bean的生命周期 前言 在我们没有使用Spring框架之前&#xff0c;创建对象一般都是使用new关键字进行创建&#xff0c;当然除了new关键字外&#xff0c;还有 运用反射手段&#xff0c;使用Class类的newInstance方法 或者 Constructor类中的newInstance方法使用clone方法使…

JavaScript语法基础之DOM基础

目录 1. DOM 基础 1.1. DOM 是什么&#xff1f; 1.1.1. DOM 对象 1.1.2. DOM 结构 1.2. 节点类型 1.3. 获取元素 1.3.1. getElementById() 1.3.2. getElementsByTagName() 1.3.3. getElementsByClassName() 1.3.4. getElementsByName() 1.4.如何去操作对象 修改属性…

IP SSL证书的未来趋势:适应不断变化的安全挑战

随着网络攻击手段的不断进化和用户对隐私保护意识的增强&#xff0c;IP SSL证书作为保障网络安全的关键组件之一&#xff0c;也在不断地发展和完善。本文将探讨IP SSL证书的未来趋势&#xff0c;以及如何适应这些不断变化的安全挑战。 当前状况与挑战 网络安全意识提升&#…

ARM 裸机与 Linux 驱动对比及 Linux 内核入门

目录 ARM裸机代码和驱动的区别 Linux系统组成 内核五大功能 设备驱动分类 内核类型 驱动模块 驱动模块示例 Makefile配置 命令 编码辅助工具 内核中的打印函数 printk 函数 修改打印级别 ​编辑 打印级别含义 驱动多文件编译 示例 模块传递参数 命令行传递参数…