当前使用版本(必填,否则不予处理)

3.5.2

该问题是如何引起的?(确定最新版也有问题再提!!!)

当同时使用自定义类型和sql注入器时报错

重现步骤(如果有就写完整)

insertBatch.java

    public class insertBatch extends AbstractMethod {

      @Override
      public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
          final String sql = "<script>insert into %s %s values %s</script>";
          final String fieldSql = prepareFieldSql(tableInfo);
          final String valueSql = prepareValuesSql(tableInfo);
          final  String sqlResult = String.format(sql,tableInfo.getTableName(),fieldSql,valueSql);
          SqlSource sqlSource = languageDriver.createSqlSource(configuration,sqlResult,modelClass);

          return this.addInsertMappedStatement(mapperClass,modelClass,"insertBatch",sqlSource,new NoKeyGenerator(),null,null);
      }

      /**
       * 准备属性名
       * @param tableInfo
       * @return
       */
      private String prepareFieldSql(TableInfo tableInfo) {
          StringBuilder fieldSql = new StringBuilder();
          if (tableInfo.getKeyColumn() != null) {
              if(!tableInfo.getIdType().equals(IdType.AUTO)){
                  fieldSql.append(tableInfo.getKeyColumn()).append(",");
              }
          }
          tableInfo.getFieldList().forEach(x -> {
              fieldSql.append(x.getColumn()).append(",");
          });
          fieldSql.delete(fieldSql.length() - 1, fieldSql.length());
          fieldSql.insert(0, "(");
          fieldSql.append(")");
          return fieldSql.toString();
      }

      private String prepareValuesSql(TableInfo tableInfo) {
          final StringBuilder valueSql = new StringBuilder();
          valueSql.append("<foreach collection=\"list\" item=\"item\" index=\"index\" open=\"(\" separator=\"),(\" close=\")\">");
          if (tableInfo.getKeyProperty() != null) {
              if(!tableInfo.getIdType().equals(IdType.AUTO)){
                  valueSql.append("#{item.").append(tableInfo.getKeyProperty()).append("},");
              }
          }
          tableInfo.getFieldList().forEach(x -> valueSql.append("#{item.").append(x.getProperty()).append("},"));
          valueSql.delete(valueSql.length() - 1, valueSql.length());
          valueSql.append("</foreach>");
          return valueSql.toString();
      }

    }

MySqlInjector

@Component
public class MySqlInjector extends DefaultSqlInjector {

    @Override
    public List<AbstractMethod> getMethodList(Class<?> mapperClass, TableInfo tableInfo) {
        List<AbstractMethod> methodList = super.getMethodList(mapperClass,tableInfo);
        methodList.add(new insertBatch());
        return methodList;
    }
}

user.java

@Data
@Accessors(chain = true)
@TableName(autoResultMap = true)
public class User {
    private Long id;
    private String name;
    private Integer age;
    private String email;

    /**
     * 注意!! 必须开启映射注解
     *
     * @TableName(autoResultMap = true)
     * <p>
     * 以下两种类型处理器,二选一 也可以同时存在
     * <p>
     * 注意!!选择对应的 JSON 处理器也必须存在对应依赖包
     */
    @TableField(typeHandler = WalletListTypeHandler.class)
    private List<Wallet> wallets;

    @TableField(typeHandler = FastjsonTypeHandler.class)
    private OtherInfo otherInfo;
}

usermapper

public interface UserMapper extends MyBaseMapper<User> {

}

mybaseMapper

public interface MyBaseMapper<T> extends BaseMapper<T> {

    /**
     * 自定义批量插入
     * 如果要自动填充,@Param(xx) xx参数名必须是 list/collection/array 3个的其中之一
     */
    int insertBatch(@Param("list") List<T> list);


}

测试代码

        User test = new User();
        test.setName("test");
        List<Wallet> walletList = new ArrayList<>();
        walletList.add(new Wallet("aaa",new ArrayList<>()));
        test.setWallets(walletList);

        userMapper.insertBatch(Arrays.asList(test));

报错信息

org.mybatis.spring.MyBatisSystemException: nested exception is org.apache.ibatis.exceptions.PersistenceException: 
### Error updating database.  Cause: java.lang.IllegalStateException: Type handler was null on parameter mapping for property '__frch_item_0.wallets'. It was either not specified and/or could not be found for the javaType (java.util.List) : jdbcType (null) combination.
### The error may exist in com/baomidou/mybatisplus/samples/typehandler/mapper/UserMapper.java (best guess)
### The error may involve com.baomidou.mybatisplus.samples.typehandler.mapper.UserMapper.insertBatch
### The error occurred while executing an update
### Cause: java.lang.IllegalStateException: Type handler was null on parameter mapping for property '__frch_item_0.wallets'. It was either not specified and/or could not be found for the javaType (java.util.List) : jdbcType (null) combination.

    at org.mybatis.spring.MyBatisExceptionTranslator.translateExceptionIfPossible(MyBatisExceptionTranslator.java:96)
    at org.mybatis.spring.SqlSessionTemplate$SqlSessionInterceptor.invoke(SqlSessionTemplate.java:441)
    at jdk.proxy2/jdk.proxy2.$Proxy58.insert(Unknown Source)
    at org.mybatis.spring.SqlSessionTemplate.insert(SqlSessionTemplate.java:272)
    at com.baomidou.mybatisplus.core.override.MybatisMapperMethod.execute(MybatisMapperMethod.java:59)
    at com.baomidou.mybatisplus.core.override.MybatisMapperProxy$PlainMethodInvoker.invoke(MybatisMapperProxy.java:148)
    at com.baomidou.mybatisplus.core.override.MybatisMapperProxy.invoke(MybatisMapperProxy.java:89)
    at jdk.proxy2/jdk.proxy2.$Proxy65.insertBatch(Unknown Source)
    at com.baomidou.mybatisplus.samples.typehandler.TypeHandlerTest.test(TypeHandlerTest.java:54)
    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.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:725)
    at org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
    at org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:149)
    at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:140)
    at org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:84)
    at org.junit.jupiter.engine.execution.ExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(ExecutableInvoker.java:115)
    at org.junit.jupiter.engine.execution.ExecutableInvoker.lambda$invoke$0(ExecutableInvoker.java:105)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
    at org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
    at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:104)
    at org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:98)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$7(TestMethodTestDescriptor.java:214)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:210)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:135)
    at org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:66)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:151)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
    at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
    at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
    at java.base/java.util.ArrayList.forEach(ArrayList.java:1511)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:41)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$6(NodeTestTask.java:155)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:141)
    at org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$9(NodeTestTask.java:139)
    at org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:138)
    at org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:95)
    at org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:35)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
    at org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:54)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:107)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:54)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67)
    at org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:114)
    at org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:86)
    at org.junit.platform.launcher.core.DefaultLauncherSession$DelegatingLauncher.execute(DefaultLauncherSession.java:86)
    at org.junit.platform.launcher.core.SessionPerRequestLauncher.execute(SessionPerRequestLauncher.java:53)
    at com.intellij.junit5.JUnit5IdeaTestRunner.startRunnerWithArgs(JUnit5IdeaTestRunner.java:71)
    at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:33)
    at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:235)
    at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:54)
Caused by: org.apache.ibatis.exceptions.PersistenceException: 
### Error updating database.  Cause: java.lang.IllegalStateException: Type handler was null on parameter mapping for property '__frch_item_0.wallets'. It was either not specified and/or could not be found for the javaType (java.util.List) : jdbcType (null) combination.
### The error may exist in com/baomidou/mybatisplus/samples/typehandler/mapper/UserMapper.java (best guess)
### The error may involve com.baomidou.mybatisplus.samples.typehandler.mapper.UserMapper.insertBatch
### The error occurred while executing an update
### Cause: java.lang.IllegalStateException: Type handler was null on parameter mapping for property '__frch_item_0.wallets'. It was either not specified and/or could not be found for the javaType (java.util.List) : jdbcType (null) combination.
    at org.apache.ibatis.exceptions.ExceptionFactory.wrapException(ExceptionFactory.java:30)
    at org.apache.ibatis.session.defaults.DefaultSqlSession.update(DefaultSqlSession.java:196)
    at org.apache.ibatis.session.defaults.DefaultSqlSession.insert(DefaultSqlSession.java:181)
    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:427)
    ... 74 more
Caused by: java.lang.IllegalStateException: Type handler was null on parameter mapping for property '__frch_item_0.wallets'. It was either not specified and/or could not be found for the javaType (java.util.List) : jdbcType (null) combination.
    at org.apache.ibatis.mapping.ParameterMapping$Builder.validate(ParameterMapping.java:119)
    at org.apache.ibatis.mapping.ParameterMapping$Builder.build(ParameterMapping.java:104)
    at org.apache.ibatis.builder.SqlSourceBuilder$ParameterMappingTokenHandler.buildParameterMapping(SqlSourceBuilder.java:143)
    at org.apache.ibatis.builder.SqlSourceBuilder$ParameterMappingTokenHandler.handleToken(SqlSourceBuilder.java:87)
    at org.apache.ibatis.parsing.GenericTokenParser.parse(GenericTokenParser.java:77)
    at org.apache.ibatis.builder.SqlSourceBuilder.parse(SqlSourceBuilder.java:50)
    at org.apache.ibatis.scripting.xmltags.DynamicSqlSource.getBoundSql(DynamicSqlSource.java:42)
    at org.apache.ibatis.mapping.MappedStatement.getBoundSql(MappedStatement.java:305)
    at org.apache.ibatis.executor.statement.BaseStatementHandler.<init>(BaseStatementHandler.java:64)
    at org.apache.ibatis.executor.statement.PreparedStatementHandler.<init>(PreparedStatementHandler.java:41)
    at org.apache.ibatis.executor.statement.RoutingStatementHandler.<init>(RoutingStatementHandler.java:46)
    at org.apache.ibatis.session.Configuration.newStatementHandler(Configuration.java:690)
    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:49)
    at com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor.intercept(MybatisPlusInterceptor.java:106)
    at org.apache.ibatis.plugin.Plugin.invoke(Plugin.java:62)
    at jdk.proxy2/jdk.proxy2.$Proxy98.update(Unknown Source)
    at org.apache.ibatis.session.defaults.DefaultSqlSession.update(DefaultSqlSession.java:194)
    ... 80 more

Comment From: miemieYaho

自己debug看insert是注入的什么再自己改

Comment From: huang-zs

自己debug看insert是注入的什么再自己改

作者的这个回答不对,他这个的代码应该是参考demo, 问题的原因是没指定typehandler,需要修改MysqlInsertAllBatch#prepareValuesSql(TableInfo tableInfo)中,
tableInfo.getFieldList().forEach(x -> valueSql.append("#{item.").append(x.getProperty()).append("},"));. 改为. tableInfo.getFieldList().forEach(x -> valueSql.append("#{item.").append(x.getEl()).append("},"));.