ShardingJDBC 空指针异常 GroupByMemoryMergedResult.getValueCaseSensitiveFromTables

GroupByMemoryMergedResult.getValueCaseSensitiveFromTables 空指针异常

背景

​ 使用ShardingJDBC5.1.1版本分库分表时,服务正常启动,访问订单相关的接口,后端报空指针。访问商品相关接口没有报错。订单表配置了分片,商品表未分片,显然问题是分表插件引起的。

Caused by: java.lang.NullPointerException: null
        at org.apache.shardingsphere.sharding.merge.dql.groupby.GroupByMemoryMergedResult.getValueCaseSensitiveFromTables(GroupByMemoryMergedResult.java:134)
        at org.apache.shardingsphere.sharding.merge.dql.groupby.GroupByMemoryMergedResult.getValueCaseSensitive(GroupByMemoryMergedResult.java:124)
        at 

问题原因

​ order表的分片规则中,第一张物理表不存在,获取不到表元数据信息,最后导致空指针

源码分析

​ 从数据节点中获取表元数据信息,是获取的第一个数据节点,也就是第一张order物理分片表。如果第一张物理分片表不存在,那么表的元数据信息也获取不到。

    private static void addOneActualTableDataNode(final SchemaBuilderMaterials materials, final Map<String, Collection<String>> dataSourceTableGroups, final DataNodes dataNodes, final String table) {
        // 获取第一个数据节点信息 .findFirst()
        Optional<DataNode> optional = dataNodes.getDataNodes(table).stream().filter(dataNode -> materials.getDataSourceMap().containsKey(dataNode.getDataSourceName())).findFirst();
        String dataSourceName = optional.map(DataNode::getDataSourceName).orElseGet(() -> materials.getDataSourceMap().keySet().iterator().next());
        String tableName = optional.map(DataNode::getTableName).orElse(table);
        addDataSourceTableGroups(dataSourceName, tableName, dataSourceTableGroups);
    }

表的元数据信息没有存入到schema中,那么在查询的时候 schema.get(tableName)返回null,最后导致空指针

    private boolean getValueCaseSensitiveFromTables(final QueryResult queryResult,
                                                    final SelectStatementContext selectStatementContext, final ShardingSphereSchema schema, final int columnIndex) throws SQLException {
        for (SimpleTableSegment each : selectStatementContext.getAllTables()) {
            String tableName = each.getTableName().getIdentifier().getValue();
            log.error("SimpleTableSegment tableName:{}", tableName);
            // 根据物理表名获取表元数据信息,
            TableMetaData tableMetaData = schema.get(tableName);
            Map<String, ColumnMetaData> columns = tableMetaData.getColumns();
            String columnName = queryResult.getMetaData().getColumnName(columnIndex);
            if (columns.containsKey(columnName)) {
                return columns.get(columnName).isCaseSensitive();
            }
        }
        return false;
    }

解决方法

​ 创建第一张物理分片表即可,具体参考actual-data-nodes的配置

​ 例如下面配置,第一张物理分片表为tb_order_202112,创建这张表,最终解决NullPointerException报错

spring:
  shardingsphere:
    rules:
      sharding:
        tables:
          tb_order:
            actual-data-nodes: db1.tb_order_$->{2021..2022}12,db1.tb_order_$->{2023..2100}0$->{1..9},db1.tb_order_$->{2023..2100}1$->{0..2}

如能解决问题,回来点个赞吧!

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值