美文网首页
shardingsphere 之 ShardingParsing

shardingsphere 之 ShardingParsing

作者: Justpeng | 来源:发表于2020-04-07 14:51 被阅读0次

    问题

    在使用 shardingsphere 时,在执行sql查询语句时报了一个异常:

    ### Cause: java.lang.NullPointerException
        at org.apache.ibatis.exceptions.ExceptionFactory.wrapException(ExceptionFactory.java:30)
        at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:150)
        at org.apache.ibatis.session.defaults.DefaultSqlSession.selectList(DefaultSqlSession.java:141)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
        at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
        at java.base/java.lang.reflect.Method.invoke(Method.java:564)
        at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:433)
        ... 110 common frames omitted
    Caused by: java.lang.NullPointerException: null
        at org.apache.shardingsphere.core.parse.antlr.rule.registry.ParsingRuleRegistry.findSQLStatementRule(ParsingRuleRegistry.java:117)
        at org.apache.shardingsphere.core.parse.antlr.parser.SQLParserEngine.parse(SQLParserEngine.java:55)
        at org.apache.shardingsphere.core.parse.antlr.AntlrParsingEngine.parse(AntlrParsingEngine.java:67)
        at org.apache.shardingsphere.core.parse.SQLParsingEngine.parse(SQLParsingEngine.java:61)
        at org.apache.shardingsphere.core.route.router.sharding.ParsingSQLRouter.parse(ParsingSQLRouter.java:78)
        at org.apache.shardingsphere.core.route.PreparedStatementRoutingEngine.route(PreparedStatementRoutingEngine.java:64)
        at org.apache.shardingsphere.core.PreparedQueryShardingEngine.route(PreparedQueryShardingEngine.java:60)
        at org.apache.shardingsphere.core.BaseShardingEngine.shard(BaseShardingEngine.java:64)
        at org.apache.shardingsphere.shardingjdbc.jdbc.core.statement.ShardingPreparedStatement.shard(ShardingPreparedStatement.java:224)
        at org.apache.shardingsphere.shardingjdbc.jdbc.core.statement.ShardingPreparedStatement.execute(ShardingPreparedStatement.java:170)
    
    

    根据异常信息,定位到ParsingRuleRegistry的代码,实际为集合parserRuleDefinitions 为空:

    public Optional<SQLStatementRule> findSQLStatementRule(final DatabaseType databaseType, final String contextClassName) {
            return Optional.fromNullable(parserRuleDefinitions.get(DatabaseType.H2 == databaseType ? DatabaseType.MySQL : databaseType).getSqlStatementRuleDefinition().getRules().get(contextClassName));
        }
    

    那么看集合 parserRuleDefinitions 是如何加载的,为何为空? 依次继续定位到 ShardingParsingRuleRegistry 的 init 方法

    public static ParsingRuleRegistry getInstance() {
            if (null == instance) {
                synchronized (ShardingParsingRuleRegistry.class) {
                    if (null == instance) {
                        instance = new ShardingParsingRuleRegistry();
                        instance.init();
                    }
                }
            }
            return instance;
    }
    

    其中,在 instance.init() 方法中进行了来个类的数据初始化,即:

     protected final void init() {
            initCommonParserRuleDefinition();
            initParserRuleDefinition();
        }
    

    其中 initParserRuleDefinition 就是我们报空指针的集合的初始化的地方,于是在这两个通过打断点方式启动调试,调试时发现,initParserRuleDefinition 没有调用就结束了,所以初步判定在 initCommonParserRuleDefinition 时发生了异常。

    于是重点放在 initParserRuleDefinition方法的追踪,最终定位到一个 Method threw 'java.lang.ClassNotFoundException' exception. 异常信息,具体代码为:

    
    public final class FillerRuleDefinitionEntityLoader implements RuleDefinitionEntityLoader {
        
        @Override
        @SneakyThrows
        public FillerRuleDefinitionEntity load(final String fillerRuleDefinitionFile) {
            InputStream inputStream = FillerRuleDefinitionEntityLoader.class.getClassLoader().getResourceAsStream(fillerRuleDefinitionFile);
            Preconditions.checkNotNull(inputStream, "Cannot load SQL filler rule definition file :%s, ", fillerRuleDefinitionFile);
            return (FillerRuleDefinitionEntity) JAXBContext.newInstance(FillerRuleDefinitionEntity.class).createUnmarshaller().unmarshal(inputStream);//此行异常  ClassNotFoundException
        }
    }
    

    这个地方比较坑人的时 这个异常并没有在控制台输出,而是被shardingsphere吃掉了,所以比较难以定位。

    解决

    • 方法一:将 jdk的运行版本将为 1.8,我的默认是1.9所以出现了异常。
    • 方法二:将 JAXB 相关jar包重新引入,具体maven
     <dependency>
        <groupId>javax.xml.bind</groupId>
        <artifactId>jaxb-api</artifactId>
        <version>2.3.1</version>
    </dependency>
    <dependency>
        <groupId>com.sun.xml.bind</groupId>
        <artifactId>jaxb-impl</artifactId>
        <version>2.3.1</version>
    </dependency>
    <dependency>
        <groupId>com.sun.xml.bind</groupId>
        <artifactId>jaxb-core</artifactId>
        <version>2.3.0</version>
    </dependency>
    <dependency>
        <groupId>javax.activation</groupId>
        <artifactId>activation</artifactId>
        <version>1.1.1</version>
    </dependency>
    
    

    相关文章

      网友评论

          本文标题:shardingsphere 之 ShardingParsing

          本文链接:https://www.haomeiwen.com/subject/kjhnphtx.html