org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.builder.BuilderException: Error evaluating expression ‘ew.sqlSegment != null and ew.sqlSegment != ‘’ and ew.nonEmptyOfWhere’. Cause: org.apache.ibatis.ognl.OgnlException: sqlSegment [java.lang.ExceptionInInitializerError]
今天在看黑马的docker教程视频时,按照视频上的操作,对192.168.1.188:8080/search/list?pageNo=1&pageSize=5进行访问,发现返回的结果不同。
正常的返回结果:
{
“total”: “88475”,
“pages”: “17695”,
“list”: [
{
“id”: “100002624512”,
“name”: “【千玺代言】华为新品 HUAWEI nova 4 极点全面屏手机 2000万超广角三摄 8GB+128GB 蜜语红 全网通双卡双待”,
“price”: 90600,
“stock”: 9999,
“image”: “https://m.360buyimg.com/mobilecms/s720x720_jfs/t1/20085/14/1076/149604/5c0f8dd2Ebafd3bfd/0cb34a7826cbe1c3.jpg!q70.jpg.webp”,
…
而我返回的结果是:
{
“code”: 500,
“msg”: “服务器内部异常”,
“data”: null
}
我认为出错的原因:mysql和java应用两个容器之间的网络存在问题或者jdk和mybatis-plus的版本存在问题
查找原因
- 判断是否是网络问题
我们先在linux虚拟机中,查看mysql的ip地址
docker@docker:~$ docker inspect mysql
再进入到 java应用 容器中
docker@docker:~$ docker exec -it b6427b652ef5 /bin/bash
在容器中 ping mysql容器,发现可以ping通,这就说明不是两个容器之间的网络问题。
- 判断是否是jdk,mybatis-plus的版本问题
为了解决这个问题,我打算启动本地服务,进行调试
首先,我将 application.yaml 文件的 spring.profiles.active 改为 local
再对 application-local.yaml 文件进行修改
然后启动服务,对 127.0.0.1:8080/search/list?pageNo=1&pageSize=5 进行访问,查看控制台
控制台打印出以下信息:
16:01:35:758 ERROR 31312 --- [nio-8080-exec-1] c.h.common.advice.CommonExceptionAdvice : 其他异常 uri : /search/list ->
org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.builder.BuilderException: Error evaluating expression 'ew.sqlSegment != null and ew.sqlSegment != '' and ew.nonEmptyOfWhere'. Cause: org.apache.ibatis.ognl.OgnlException: sqlSegment [java.lang.ExceptionInInitializerError]
at org.mybatis.spring.MyBatisExceptionTranslator.translateExceptionIfPossible(MyBatisExceptionTranslator.java:96) ~[mybatis-spring-2.0.6.jar:2.0.6]
at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:441) ~[mybatis-spring-2.0.6.jar:2.0.6]
at jdk.proxy2/jdk.proxy2.$Proxy87.selectList(Unknown Source) ~[na:na]
at org.mybatis.spring.SqlSessionTemplate.selectList(SqlSessionTemplate.java:224) ~[mybatis-spring-2.0.6.jar:2.0.6]
at com.baomidou.mybatisplus.core.override.MybatisMapperMethod.executeForIPage(MybatisMapperMethod.java:121) ~[mybatis-plus-core-3.4.3.jar:3.4.3]
at com.baomidou.mybatisplus.core.override.MybatisMapperMethod.execute(MybatisMapperMethod.java:85) ~[mybatis-plus-core-3.4.3.jar:3.4.3]
at com.baomidou.mybatisplus.core.override.MybatisMapperProxy$PlainMethodInvoker.invoke(MybatisMapperProxy.java:148) ~[mybatis-plus-core-3.4.3.jar:3.4.3]
at com.baomidou.mybatisplus.core.override.MybatisMapperProxy.invoke(MybatisMapperProxy.java:89) ~[mybatis-plus-core-3.4.3.jar:3.4.3]
at jdk.proxy2/jdk.proxy2.$Proxy95.selectPage(Unknown Source) ~[na:na]
at com.baomidou.mybatisplus.extension.conditions.query.ChainQuery.page(ChainQuery.java:77) ~[mybatis-plus-extension-3.4.3.jar:3.4.3]
at com.hmall.controller.SearchController.search(SearchController.java:37) ~[classes/:na]
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
我发现报错的指向 SearchController.java:37 :
以下是发生错误的代码:
Page<Item> result = itemService.lambdaQuery()
.like(StrUtil.isNotBlank(query.getKey()), Item::getName, query.getKey())
.eq(StrUtil.isNotBlank(query.getBrand()), Item::getBrand, query.getBrand())
.eq(StrUtil.isNotBlank(query.getCategory()), Item::getCategory, query.getCategory())
.eq(Item::getStatus, 1)
.between(query.getMaxPrice() != null, Item::getPrice, query.getMinPrice(), query.getMaxPrice())
.page(query.toMpPage("update_time", false));
于是我去搜索有关 mybatis-plus3.4.3下的lambdaQuery报错问题,找到了这篇文章:
Mybatis-plus3.4.3下使用lambdaQuery报错
看了之后发现是 Mybatis-plus和JDK高版本冲突 的问题
于是我把我的jdk版本换为jdk11
mybatis-plus版本改为3.4.2
重新启动服务,再次访问 127.0.0.1:8080/search/list?pageNo=1&pageSize=5
返回结果如下:
访问成功
重新部署
使用maven进行重新打包,替换掉在linux中原有的hmall-server.jar
停止 hmall 容器的服务,再进行删除
docker@docker:/hmall$ docker stop hmall
docker@docker:/hmall$ docker rm hmall
删除之前构建过的 hmall镜像
docker@docker:/hmall$ docker image rm hmall
重新构建 hmall镜像
docker@docker:/hmall$ docker build -t hmall .
启动 hmall 容器
docker@docker:/hmall$ docker run -d --name hmall -p 8080:8080 hmall
总结
原因在于 Mybatis-plus和JDK高版本冲突,只要选择合适的mybatis-plus和jdk版本就能成功访问。
之后只要重新对java程序进行打包,替换掉原有的jar包,再重新构建镜像,启动容器,就成功了。
思维发散
之前提到过,错误的原因是在 SearchController.java:37 :
Page<Item> result = itemService.lambdaQuery()
.like(StrUtil.isNotBlank(query.getKey()), Item::getName, query.getKey())
.eq(StrUtil.isNotBlank(query.getBrand()), Item::getBrand, query.getBrand())
.eq(StrUtil.isNotBlank(query.getCategory()), Item::getCategory, query.getCategory())
.eq(Item::getStatus, 1)
.between(query.getMaxPrice() != null, Item::getPrice, query.getMinPrice(), query.getMaxPrice())
.page(query.toMpPage("update_time", false));
于是我想,如果我绕过这里,对其他路径进行访问能否访问成功呢?
我开始通过代码和mysql里存储的数据查找是否有能够成功访问的路径
我找到一条这样的路径 http://127.0.0.1:8080/addresses/59
当我对它进行访问时,它会提示我 未登入 ,我想应该是被拦截了,于是我进入MvcConfig.java文件中将addInterceptors方法里面的内容注释。
@Configuration
@RequiredArgsConstructor
@EnableConfigurationProperties(AuthProperties.class)
public class MvcConfig implements WebMvcConfigurer {
private final JwtTool jwtTool;
private final AuthProperties authProperties;
@Override
public void addInterceptors(InterceptorRegistry registry) {
// // 1.添加拦截器
// LoginInterceptor loginInterceptor = new LoginInterceptor(jwtTool);
// InterceptorRegistration registration = registry.addInterceptor(loginInterceptor);
// // 2.配置拦截路径
// List<String> includePaths = authProperties.getIncludePaths();
// if (CollUtil.isNotEmpty(includePaths)) {
// registration.addPathPatterns(includePaths);
// }
// // 3.配置放行路径
// List<String> excludePaths = authProperties.getExcludePaths();
// if (CollUtil.isNotEmpty(excludePaths)) {
// registration.excludePathPatterns(excludePaths);
// }
// registration.excludePathPatterns(
// "/error",
// "/favicon.ico",
// "/v2/**",
// "/v3/**",
// "/swagger-resources/**",
// "/webjars/**",
// "/doc.html"
// );
}
}
重启服务,再次访问 http://127.0.0.1:8080/addresses/59
返回结果:
{
“id”: “59”,
“province”: “北京”,
“city”: “北京”,
“town”: “朝阳区”,
“mobile”: “13900112222”,
“street”: “金燕龙办公楼”,
“contact”: “李嘉诚”,
“isDefault”: 0,
“notes”: null
}
如果绕过mybatis-plus的lambdaQuery,进行访问是能够成功的。