ShardingSphere 踩过的坑:Cannot invoke method div() on null object
背景
Java:8
ShardingSphere:4.0.0-RC1
SpringBoot:2.1.9.RELEASE
mybatis-spring-boot-starter:2.1.4 (mybatis 3.5.6)
数据源:druid 1.1.16
分表分库规则
t_user 表 DDL:
CREATE TABLE `t_user0` ( `USER_ID` bigint(20) NOT NULL, `TENANT_ID` bigint(20) NOT NULL, PRIMARY KEY (`USER_ID`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
分库分表思路:10 个租户一个物理库,2000w 个用户一张用户表。规则配置如下所示:
# 数据分库规则 - 指定分库主键 spring.shardingsphere.sharding.default-database-strategy.inline.sharding-column=tenant_id # 数据分库规则 - 分库规则为主键除以 10 取整 spring.shardingsphere.sharding.default-database-strategy.inline.algorithm-expression=ds$->{tenant_id / 10 as int} # 数据分表规则 # 指定所需分流的表 spring.shardingsphere.sharding.tables.t_user.actual-data-nodes=ds$->{0..1}.t_user$->{0..5} # 指定主键 spring.shardingsphere.sharding.tables.t_user.table-strategy.inline.sharding-column=user_id # 分表规则为主键除以 1000 取整 spring.shardingsphere.sharding.tables.t_user.table-strategy.inline.algorithm-expression=t_user$->{user_id / 1000 as int}
TabUserMapper.xml 插入一行记录相关代码如下:
<insert id="insertSelective" parameterType="com.sharding.tabledemo.pojo.TabUser"> insert into t_user(USER_ID, TENANT_ID) values(#{userId}, #{tenantId}) </insert>
报错信息
测试插入逻辑的时候,ShardingSphere 报错:
2022-03-14 15:45:37.660 ERROR 6896 --- [nio-9343-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.exceptions.PersistenceException: ### Error updating database. Cause: java.lang.NullPointerException: Cannot invoke method div() on null object ### The error may exist in file [D:\tmp\table-demo\target\classes\mapper\TabUserMapper.xml] ### The error may involve com.sharding.tabledemo.mapper.TabUserMapper.insertSelective-Inline ### The error occurred while setting parameters ### SQL: insert into t_user(USER_ID, TENANT_ID) values(?, ?}) ### Cause: java.lang.NullPointerException: Cannot invoke method div() on null object] with root cause java.lang.NullPointerException: Cannot invoke method div() on null object at org.codehaus.groovy.runtime.NullObject.invokeMethod(NullObject.java:91) ~[groovy-2.4.5-indy.jar:2.4.5]
解决方案
去 ShardingSphere 维护的 github 上的 issues 列表中搜索,虽然报的不一定是 div() 方法,但大体也能给出改错方向:
于是反复检查 inline,很不幸的是没有发现语法或逻辑错误;分片键和分片策略中的字段是拷贝复制的已经没法再一致了。
最后发现,问题竟然是 inline 和 TabUserMapper.xml 里的相关字段大小写不一致导致的。
于是把 TabUserMapper.xml 上述伪代码部分分片主键相关改为和 inline 一致:
<insert id="insertSelective" parameterType="com.sharding.tabledemo.pojo.TabUser"> insert into t_user(user_id, tenant_id) values(#{userId}, #{tenantId}) </insert>
问题顺利解决。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 周边上新:园子的第一款马克杯温暖上架
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· DeepSeek如何颠覆传统软件测试?测试工程师会被淘汰吗?
· 使用C#创建一个MCP客户端