确认

  • [x] 我使用的版本是最新版, 并且使用插件确认过项目里无依赖版本冲突
  • [x] 我已经在 issue 中搜索过, 确认问题没有被提出过
  • [x] 我已经修改标题, 将标题中的 描述 替换为遇到的问题

当前程序版本

3.5.7-3.5.10.1

问题描述

执行环境 spring boot 3.3.7 版本 pgsql16.3 主键是UUID 执行removeByIds removeBatchByIds方法时报错 之前的mybatis 3.5.6 执行正常而升级之后的3.5.7-3.5.10.1 执行相关方法报错

List ids = List.of(UUID.fromString("688aa547-09f8-4a26-8c71-411d4ba7d67e")); boolean flag = sysUserTokenService.removeByIds(List.of(ids));

org.mybatis.spring.MyBatisSystemException:

Error updating database. Cause: java.lang.UnsupportedOperationException

The error may exist in system/mapper/SysUserTokenMapper.java (best guess)

The error may involve system.mapper.SysUserTokenMapper.deleteByIds

The error occurred while executing an update

Cause: java.lang.UnsupportedOperationException

详细堆栈日志

org.mybatis.spring.MyBatisSystemException: 
### Error updating database.  Cause: java.lang.UnsupportedOperationException
### The error may exist in /system/mapper/SysUserTokenMapper.java (best guess)
### The error may involve system.mapper.SysUserTokenMapper.deleteByIds
### The error occurred while executing an update
### Cause: java.lang.UnsupportedOperationException

    at org.mybatis.spring.MyBatisExceptionTranslator.translateExceptionIfPossible(MyBatisExceptionTranslator.java:99)
    at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:347)
    at jdk.proxy2/jdk.proxy2.$Proxy153.delete(Unknown Source)
    at org.mybatis.spring.SqlSessionTemplate.delete(SqlSessionTemplate.java:244)
    at com.baomidou.mybatisplus.core.mapper.BaseMapper.deleteByIds(BaseMapper.java:219)
    at java.base/java.lang.invoke.MethodHandle.invokeWithArguments(MethodHandle.java:732)
    at com.baomidou.mybatisplus.core.override.MybatisMapperProxy$DefaultMethodInvoker.invoke(MybatisMapperProxy.java:166)
    at com.baomidou.mybatisplus.core.override.MybatisMapperProxy.invoke(MybatisMapperProxy.java:89)
    at jdk.proxy2/jdk.proxy2.$Proxy178.deleteByIds(Unknown Source)
    at com.baomidou.mybatisplus.core.mapper.BaseMapper.deleteByIds(BaseMapper.java:185)
    at java.base/java.lang.invoke.MethodHandle.invokeWithArguments(MethodHandle.java:732)
    at com.baomidou.mybatisplus.core.override.MybatisMapperProxy$DefaultMethodInvoker.invoke(MybatisMapperProxy.java:166)
    at com.baomidou.mybatisplus.core.override.MybatisMapperProxy.invoke(MybatisMapperProxy.java:89)
    at jdk.proxy2/jdk.proxy2.$Proxy178.deleteByIds(Unknown Source)
    at com.baomidou.mybatisplus.extension.service.impl.ServiceImpl.removeBatchByIds(ServiceImpl.java:302)
    at com.baomidou.mybatisplus.extension.service.IService.removeBatchByIds(IService.java:186)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:568)
    at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:355)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:196)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:768)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:379)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:184)
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:768)
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:720)
    at system.service.impl.SysUserTokenServiceImpl$$SpringCGLIB$$0.removeBatchByIds(<generated>)
    at test.DemoTest.test3(DemoTest.java:21)
    at java.base/java.lang.reflect.Method.invoke(Method.java:568)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
Caused by: org.apache.ibatis.exceptions.PersistenceException: 
### Error updating database.  Cause: java.lang.UnsupportedOperationException
### The error may exist in system/mapper/SysUserTokenMapper.java (best guess)
### The error may involve system.mapper.SysUserTokenMapper.deleteByIds
### The error occurred while executing an update
### Cause: java.lang.UnsupportedOperationException
    at org.apache.ibatis.exceptions.ExceptionFactory.wrapException(ExceptionFactory.java:30)
    at org.apache.ibatis.session.defaults.DefaultSqlSession.update(DefaultSqlSession.java:199)
    at org.apache.ibatis.session.defaults.DefaultSqlSession.delete(DefaultSqlSession.java:212)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:568)
    at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:333)
    ... 32 more
Caused by: java.lang.UnsupportedOperationException
    at org.apache.ibatis.reflection.wrapper.CollectionWrapper.hasGetter(CollectionWrapper.java:78)
    at org.apache.ibatis.reflection.MetaObject.hasGetter(MetaObject.java:110)
    at org.apache.ibatis.reflection.wrapper.MapWrapper.hasGetter(MapWrapper.java:128)
    at org.apache.ibatis.reflection.MetaObject.hasGetter(MetaObject.java:110)
    at org.apache.ibatis.builder.SqlSourceBuilder$ParameterMappingTokenHandler.buildParameterMapping(SqlSourceBuilder.java:97)
    at org.apache.ibatis.builder.SqlSourceBuilder$ParameterMappingTokenHandler.handleToken(SqlSourceBuilder.java:89)
    at org.apache.ibatis.parsing.GenericTokenParser.parse(GenericTokenParser.java:76)
    at org.apache.ibatis.builder.SqlSourceBuilder.parse(SqlSourceBuilder.java:51)
    at org.apache.ibatis.scripting.xmltags.DynamicSqlSource.getBoundSql(DynamicSqlSource.java:42)
    at org.apache.ibatis.mapping.MappedStatement.getBoundSql(MappedStatement.java:320)
    at org.apache.ibatis.executor.statement.BaseStatementHandler.<init>(BaseStatementHandler.java:65)
    at org.apache.ibatis.executor.statement.PreparedStatementHandler.<init>(PreparedStatementHandler.java:42)
    at org.apache.ibatis.executor.statement.RoutingStatementHandler.<init>(RoutingStatementHandler.java:47)
    at org.apache.ibatis.session.Configuration.newStatementHandler(Configuration.java:719)
    at org.apache.ibatis.executor.SimpleExecutor.doUpdate(SimpleExecutor.java:48)
    at org.apache.ibatis.executor.BaseExecutor.update(BaseExecutor.java:117)
    at org.apache.ibatis.executor.CachingExecutor.update(CachingExecutor.java:76)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:568)
    at org.apache.ibatis.plugin.Invocation.proceed(Invocation.java:61)
    at com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor.intercept(MybatisPlusInterceptor.java:106)
    at org.apache.ibatis.plugin.Plugin.invoke(Plugin.java:59)
    at jdk.proxy2/jdk.proxy2.$Proxy198.update(Unknown Source)
    at org.apache.ibatis.session.defaults.DefaultSqlSession.update(DefaultSqlSession.java:197)
    ... 38 more

Comment From: zijun-hiwintech

另外 我的实体类主键是UUID @TableName(value = "sys_user_token") public class SysUserToken extends BaseModel {

@Serial
private static final long serialVersionUID = 1L;
@TableId(value = "id",type = IdType.INPUT)
private UUID id;

} 切换到3.5.8 报错信息如下:

org.mybatis.spring.MyBatisSystemException:

Error updating database. Cause: org.apache.ibatis.reflection.ReflectionException: There is no getter for property named 'id' in 'class java.util.UUID'

The error may exist in system/mapper/SysUserTokenMapper.java (best guess)

The error may involve system.mapper.SysUserTokenMapper.deleteByIds-Inline

The error occurred while setting parameters

SQL: UPDATE sys_user_token SET updated_at=?,updated_by=?, is_deleted=true WHERE id IN ( ? ) AND is_deleted=false

Cause: org.apache.ibatis.reflection.ReflectionException: There is no getter for property named 'id' in 'class java.util.UUID'

at org.mybatis.spring.MyBatisExceptionTranslator.translateExceptionIfPossible(MyBatisExceptionTranslator.java:99)
at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:347)
at jdk.proxy2/jdk.proxy2.$Proxy151.delete(Unknown Source)
at org.mybatis.spring.SqlSessionTemplate.delete(SqlSessionTemplate.java:244)
at com.baomidou.mybatisplus.core.mapper.BaseMapper.deleteByIds(BaseMapper.java:219)
at java.base/java.lang.invoke.MethodHandle.invokeWithArguments(MethodHandle.java:732)
at com.baomidou.mybatisplus.core.override.MybatisMapperProxy$DefaultMethodInvoker.invoke(MybatisMapperProxy.java:166)
at com.baomidou.mybatisplus.core.override.MybatisMapperProxy.invoke(MybatisMapperProxy.java:89)
at jdk.proxy2/jdk.proxy2.$Proxy176.deleteByIds(Unknown Source)
at com.baomidou.mybatisplus.core.mapper.BaseMapper.deleteByIds(BaseMapper.java:185)
at java.base/java.lang.invoke.MethodHandle.invokeWithArguments(MethodHandle.java:732)
at com.baomidou.mybatisplus.core.override.MybatisMapperProxy$DefaultMethodInvoker.invoke(MybatisMapperProxy.java:166)
at com.baomidou.mybatisplus.core.override.MybatisMapperProxy.invoke(MybatisMapperProxy.java:89)
at jdk.proxy2/jdk.proxy2.$Proxy176.deleteByIds(Unknown Source)
at com.baomidou.mybatisplus.extension.service.IService.removeByIds(IService.java:159)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:355)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:716)
at kare.freebird.system.service.impl.SysUserTokenServiceImpl$$SpringCGLIB$$0.removeByIds(<generated>)
at test.DemoTest.test3(DemoTest.java:23)
at java.base/java.lang.reflect.Method.invoke(Method.java:568)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)

Caused by: org.apache.ibatis.reflection.ReflectionException: There is no getter for property named 'id' in 'class java.util.UUID' at org.apache.ibatis.reflection.Reflector.getGetInvoker(Reflector.java:385) at org.apache.ibatis.reflection.MetaClass.getGetInvoker(MetaClass.java:160) at org.apache.ibatis.reflection.wrapper.BeanWrapper.getBeanProperty(BeanWrapper.java:156) at org.apache.ibatis.reflection.wrapper.BeanWrapper.get(BeanWrapper.java:50) at org.apache.ibatis.reflection.MetaObject.getValue(MetaObject.java:115) at org.apache.ibatis.reflection.wrapper.BaseWrapper.getChildValue(BaseWrapper.java:121) at org.apache.ibatis.reflection.wrapper.MapWrapper.get(MapWrapper.java:42) at org.apache.ibatis.reflection.MetaObject.getValue(MetaObject.java:115) at org.apache.ibatis.mapping.BoundSql.getAdditionalParameter(BoundSql.java:74) at org.apache.ibatis.scripting.defaults.DefaultParameterHandler.setParameters(DefaultParameterHandler.java:73) at org.apache.ibatis.executor.statement.PreparedStatementHandler.parameterize(PreparedStatementHandler.java:97) at org.apache.ibatis.executor.statement.RoutingStatementHandler.parameterize(RoutingStatementHandler.java:65) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:568) at org.apache.ibatis.plugin.Plugin.invoke(Plugin.java:61) at jdk.proxy2/jdk.proxy2.$Proxy199.parameterize(Unknown Source) at org.apache.ibatis.executor.SimpleExecutor.prepareStatement(SimpleExecutor.java:91) at org.apache.ibatis.executor.SimpleExecutor.doUpdate(SimpleExecutor.java:49) at org.apache.ibatis.executor.BaseExecutor.update(BaseExecutor.java:117) at org.apache.ibatis.executor.CachingExecutor.update(CachingExecutor.java:76) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:568) at org.apache.ibatis.plugin.Invocation.proceed(Invocation.java:61) at com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor.intercept(MybatisPlusInterceptor.java:106) at org.apache.ibatis.plugin.Plugin.invoke(Plugin.java:59) at jdk.proxy2/jdk.proxy2.$Proxy198.update(Unknown Source) at org.apache.ibatis.session.defaults.DefaultSqlSession.update(DefaultSqlSession.java:197) at org.apache.ibatis.session.defaults.DefaultSqlSession.delete(DefaultSqlSession.java:212) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:568) at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:333) ... 24 more

Comment From: miemieYaho

mybatis没有UUID的对应typehandler

Comment From: zijun-hiwintech

嗯 感觉您的回复,但是我们自己实现了一个UUIDTypeHandler 现在的代码在mybatis 3.5.6 可以正常执行 但是之后的版本就报上述的错误

import org.apache.ibatis.type.BaseTypeHandler; import org.apache.ibatis.type.JdbcType; import org.apache.ibatis.type.MappedJdbcTypes; import org.apache.ibatis.type.MappedTypes; import org.springframework.util.StringUtils;

import java.sql.CallableStatement; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; import java.util.UUID;

@MappedTypes(UUID.class) @MappedJdbcTypes(JdbcType.VARCHAR) public class UUIDTypeHandler extends BaseTypeHandler {

@Override
public UUID getNullableResult(ResultSet rs, String strArg)
        throws SQLException {
    String strVal = rs.getString(strArg);
    return this.getUUIDFromString(strVal);
}

@Override
public UUID getNullableResult(ResultSet rs, int intArg) throws SQLException {
    String strVal = rs.getString(intArg);
    return this.getUUIDFromString(strVal);
}

@Override
public UUID getNullableResult(CallableStatement cs, int intArg)
        throws SQLException {
    String strVal = cs.getString(intArg);
    return this.getUUIDFromString(strVal);
}

@Override
public void setNonNullParameter(PreparedStatement ps, int intArg,
                                UUID uuid, JdbcType jdbcType) throws SQLException {
    if (null != uuid) {
        ps.setObject(intArg, uuid);
    }
}

private UUID getUUIDFromString(String uuidStr) {
    if (StringUtils.hasLength(uuidStr)) {
        return UUID.fromString(uuidStr);
    }
    return null;
}

}

Comment From: miemieYaho

后面的版本支持了在逻辑删除下能自动填充字段 你自己debug找问题吧,你找出来我们再考虑一下要不要修

Comment From: yuxiaobin

有没有可能,是你代码写错了?

List ids = List.of(UUID.fromString("688aa547-09f8-4a26-8c71-411d4ba7d67e")); boolean flag = sysUserTokenService.removeByIds( List.of(ids) );

你的参数 包了2层