问题
在使用 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>