Cause: org.apache.ibatis.ognl.OgnlException: sqlSegment

17:12:47.358 [http-nio-11080-exec-2] ERROR c.c.f.w.e.GlobalExceptionHandler - [handleRuntimeException,100] - 请求地址'/xx/xxx/xxx/xxx/xxx/8bbe5b132a7a4d9bb28cedfeac94d69f',发生未知异常.
org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.builder.BuilderException: Error evaluating expression 'ew.sqlSegment != null and ew.sqlSegment != '''. Cause: org.apache.ibatis.ognl.OgnlException: sqlSegment [com.baomidou.mybatisplus.core.exceptions.MybatisPlusException: can not use this method for "getSqlSegment"]
	at org.mybatis.spring.MyBatisExceptionTranslator.translateExceptionIfPossible(MyBatisExceptionTranslator.java:97)
	at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:439)
	at com.sun.proxy.$Proxy129.delete(Unknown Source)
	at org.mybatis.spring.SqlSessionTemplate.delete(SqlSessionTemplate.java:304)
	at com.baomidou.mybatisplus.core.override.MybatisMapperMethod.execute(MybatisMapperMethod.java:69)
	at com.baomidou.mybatisplus.core.override.MybatisMapperProxy$PlainMethodInvoker.invoke(MybatisMapperProxy.java:148)
	at com.baomidou.mybatisplus.core.override.MybatisMapperProxy.invoke(MybatisMapperProxy.java:89)
	at com.sun.proxy.$Proxy205.delete(Unknown Source)
	at com.baomidou.mybatisplus.extension.service.IService.remove(IService.java:146)
	at com.cn.basedata.service.impl.xxxxImpl.deletexxxIds(xxxxImpl.java:80)
	at com.cn.basedata.service.impl.xxxxImpl$$FastClassBySpringCGLIB$$35e8855a.invoke(<generated>)
	at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:792)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:762)
	at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:123)
	at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:388)
	at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186)
	at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:762)
	at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:707)
	at com.cn.basedata.service.impl.xxxxImpl$$EnhancerBySpringCGLIB$$94053a1.deletexxxByIds(<generated>)
	at com.cn.basedata.service.impl.xxxxImpl.deletexxxByIds(xxxxImpl.java:172)
	at com.cn.basedata.service.impl.xxxxImpl$$FastClassBySpringCGLIB$$17e90df0.invoke(<generated>)
	at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:218)
	at org.springframework.aop.framework.CglibAopProxy.invokeMethod(CglibAopProxy.java:386)
	at org.springframework.aop.framework.CglibAopProxy.access$000(CglibAopProxy.java:85)
	at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:703)
	at com.cn.basedata.service.impl.xxxxImpl$$EnhancerBySpringCGLIB$$cf8fb23.deletexxxByIds(<generated>)
	at com.cn.web.controller.xxx.xxx.remove(xxx.java:221)
	at com.cn.web.controller.videom

其中,报错的代码如下 (xxxImpl.deletexxxIds() 方法):


    @Transactional(rollbackFor = Exception.class)
    public boolean deletexxxIds(List<String> ids) {
        return ids != null && ! ids.isEmpty() ? this.remove(this.lambdaQuery().in(xxx::getId, ids)) : false;
    }

问题在于:

  1. lambdaQuery() 创建的是一个 LambdaQueryWrapper,而 remove() 方法内部会尝试获取 sqlSegment

  2. 在某些 MyBatis-Plus 版本中,这种链式调用会导致 getSqlSegment 方法被错误调用

解决方案

方案1:改用传统 QueryWrapper(推荐)
@Override
@Transactional(rollbackFor = Exception.class)
public boolean deletexxxIds(List<String> ids) {
    if (ids == null || ids.isEmpty()) {
        return false;
    }
    QueryWrapper<xxx> wrapper = new QueryWrapper<>();
    wrapper.in("id", ids);
    return this.remove(wrapper);
}
 方案2:分离 Lambda 表达式构造
@Override
@Transactional(rollbackFor = Exception.class)
public boolean deletexxxIds(List<String> ids) {
    if (ids == null || ids.isEmpty()) {
        return false;
    }
    LambdaQueryWrapper<xxx> wrapper = Wrappers.lambdaQuery();
    wrapper.in(xxx::getId, ids);
    return this.remove(wrapper);
}
方案4:升级 MyBatis-Plus 版本

如果是版本问题(特别是 3.4.x 之前的版本),建议升级到最新稳定版:

<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.5.3.1</version>
</dependency>

为什么这样修改有效?

原始代码中的链式调用 this.remove(this.lambdaQuery().in(...)) 在某些版本中会导致:

  1. 条件构造器被过早评估

  2. 内部尝试获取 sqlSegment 时上下文不完整

而分离构造步骤(方案2)或使用传统 QueryWrapper(方案1)可以避免这种内部处理冲突。这是 MyBatis-Plus 实现细节导致的问题,官方文档中也推荐避免过于复杂的链式调用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值