JPA使用shardingsphere-proxy连接,查询报错Exception occur

场景

  • 业务要求,需要按照租户进行分表,并需要对敏感信息进行脱敏存储
  • 决定使用业界成熟的数据库中间件shardingshere-proxy
  • 使用的是PostgreSQL数据库,版本13.5
  • 项目使用的hibernate 版本 5.4,jdk版本11
  • 部署使用中间件版本shardingsphere 5.0.0,jdk 8(无法使用11)
  • 使用JPA查询时报错,但是不使用shardingphere-proxy时,JPA可以正常查询
  • 报错的代码
    // 报错片段1,get报错
    Map<String, Object> params = new HashMap<>();
    params.put("villageId", villageId);
    params.put("customerId", customerId);
    params.put("relaId", id);
    List<VillageAttachmentEO> attachments = this.getEntities(VillageAttachmentEO.class, params);
    
    // 报错片段2,JPA的deleteBy删除方法报错
    void deleteByRelaId(Long relaId);

报错信息

[ERROR] 2022-02-25 17:54:37.073 [Connection-1-ThreadExecutor] o.a.s.p.f.c.CommandExecutorTask - Exception occur: 
com.google.common.util.concurrent.UncheckedExecutionException: org.apache.shardingsphere.sql.parser.exception.SQLParsingException: You have an error in your SQL syntax.
	at com.google.common.cache.LocalCache$Segment.get(LocalCache.java:2051)
	at com.google.common.cache.LocalCache.get(LocalCache.java:3951)
	at com.google.common.cache.LocalCache.getOrLoad(LocalCache.java:3974)
	at com.google.common.cache.LocalCache$LocalLoadingCache.get(LocalCache.java:4958)
	at com.google.common.cache.LocalCache$LocalLoadingCache.getUnchecked(LocalCache.java:4964)
	at org.apache.shardingsphere.infra.parser.sql.SQLStatementParserEngine.parse(SQLStatementParserEngine.java:48)
	at org.apache.shardingsphere.infra.parser.ShardingSphereSQLParserEngine.parse0(ShardingSphereSQLParserEngine.java:71)
	at org.apache.shardingsphere.infra.parser.ShardingSphereSQLParserEngine.parse(ShardingSphereSQLParserEngine.java:60)
	at org.apache.shardingsphere.proxy.frontend.postgresql.command.query.binary.parse.PostgreSQLComParseExecutor.parseSql(PostgreSQLComParseExecutor.java:54)
	at org.apache.shardingsphere.proxy.frontend.postgresql.command.query.binary.parse.PostgreSQLComParseExecutor.<init>(PostgreSQLComParseExecutor.java:42)
	at org.apache.shardingsphere.proxy.frontend.postgresql.command.PostgreSQLCommandExecutorFactory.newInstance(PostgreSQLCommandExecutorFactory.java:70)
	at org.apache.shardingsphere.proxy.frontend.postgresql.command.PostgreSQLCommandExecuteEngine.getCommandExecutor(PostgreSQLCommandExecuteEngine.java:72)
	at org.apache.shardingsphere.proxy.frontend.command.CommandExecutorTask.executeCommand(CommandExecutorTask.java:97)
	at org.apache.shardingsphere.proxy.frontend.command.CommandExecutorTask.run(CommandExecutorTask.java:72)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
	at java.lang.Thread.run(Thread.java:748)
Caused by: org.apache.shardingsphere.sql.parser.exception.SQLParsingException: You have an error in your SQL syntax.
	at org.apache.shardingsphere.sql.parser.core.database.parser.SQLParserExecutor.twoPhaseParse(SQLParserExecutor.java:68)
	at org.apache.shardingsphere.sql.parser.core.database.parser.SQLParserExecutor.parse(SQLParserExecutor.java:49)
	at org.apache.shardingsphere.sql.parser.api.SQLParserEngine.parse(SQLParserEngine.java:51)
	at org.apache.shardingsphere.infra.parser.sql.SQLStatementParserExecutor.parse(SQLStatementParserExecutor.java:47)
	at org.apache.shardingsphere.infra.parser.cache.SQLStatementCacheLoader.load(SQLStatementCacheLoader.java:40)
	at org.apache.shardingsphere.infra.parser.cache.SQLStatementCacheLoader.load(SQLStatementCacheLoader.java:29)
	at com.google.common.cache.LocalCache$LoadingValueReference.loadFuture(LocalCache.java:3529)
	at com.google.common.cache.LocalCache$Segment.loadSync(LocalCache.java:2278)
	at com.google.common.cache.LocalCache$Segment.lockedGetOrLoad(LocalCache.java:2155)
	at com.google.common.cache.LocalCache$Segment.get(LocalCache.java:2045)
	... 16 common frames omitted

排查过程

  • 未使用sharingphere-proxy前不报错,使用后报错,说明是中间件的问题
  • 报错信息很明显,就是SQL执行报错,需要把SQL打印出来
  • 修改源码,把报错SQL打印出来,根据报错行数,修改类SQLParserExecutor,增加报错的SQL打印,输出后如下:
select villageatt0_.id as id1_8_, 
villageatt0_.create_date as create_d2_8_,
villageatt0_.create_organ_id as create_o3_8_,
villageatt0_.create_user_id as create_u4_8_,
villageatt0_.update_date as update_d5_8_,
villageatt0_.update_user_id as update_u6_8_,
villageatt0_.customer_id as customer7_8_,
villageatt0_.file_name as file_nam8_8_, 
villageatt0_.file_type as file_typ9_8_, 
villageatt0_.path as path10_8_, 
villageatt0_.rela_id as rela_id11_8_,
villageatt0_.size as size12_8_, 
villageatt0_.type as type13_8_, 
villageatt0_.village_id as village14_8_ 
from village_attachment villageatt0_ 
where villageatt0_.rela_id=?
  • 没发现SQL有任何问题,拿到原有pgsql建立连接,去执行SQL,没问题
  • 使用sharding的ip端口建立连接,执行SQL,发现确实报错
  • 把SQL拿到navcat,使用美化SQL功能,发现有几个字段转化为了大写,疑似为关键字或函数名称,ID、PATH、SIZE、TYPE
  • 对这4个字段逐个测试,发现会出现大小写异常,使用小写的继续测试
  • 最终发现是path字段影响的,去除该字段就不会报错,即使大写也不会报大小写异常

处理方式

  • 既然确定了是字段path的影响,修改该字段即可,修改为path_,问题解决
    /**
     * 附件路径
     */
    @Column(name = "path_")
    private String path;
  • 其实也可以通过修改源码解决,SQL解析时,对字段名称拼接上双引号。path字段加上双引号,就可以执行成功,即"path"
  • 但是考虑到以后中间件的版本升级替换问题,暂时不采用此方法

字段记录(未完待续)

  • 对使用中遇到的字段进行汇总,后续开发使用时,作为参考
  • path
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

坚持是一种态度

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值