我try 了创建返回类型ImmuableList并从表中 Select 一组ID,但当然,mybatis不知道如何做到这一点,并抛出异常:

org.apache.ibatis.reflection.ReflectionException: Error instantiating class com.google.common.collect.ImmutableList with invalid types () or values (). Cause: java.lang.InstantiationException
    at org.apache.ibatis.reflection.factory.DefaultObjectFactory.instantiateClass(DefaultObjectFactory.java:88)
    at org.apache.ibatis.reflection.factory.DefaultObjectFactory.create(DefaultObjectFactory.java:53)
    at org.apache.ibatis.reflection.factory.DefaultObjectFactory.create(DefaultObjectFactory.java:45)
    at org.apache.ibatis.binding.MapperMethod.convertToDeclaredCollection(MapperMethod.java:173)
    at org.apache.ibatis.binding.MapperMethod.executeForMany(MapperMethod.java:154)
    at org.apache.ibatis.binding.MapperMethod.execute(MapperMethod.java:80)
    at org.apache.ibatis.binding.MapperProxy$PlainMethodInvoker.invoke(MapperProxy.java:145)
    at org.apache.ibatis.binding.MapperProxy.invoke(MapperProxy.java:86)
    at jdk.proxy5/jdk.proxy5.$Proxy76.getAllIds(Unknown Source)
    at org.acanthite.services.UtilityService.getAllIds(UtilityService.java:98)
    at org.acanthite.services.UtilityService_ClientProxy.getAllIds(Unknown Source)
    at org.acanthite.resources.UtilityResource.ids(UtilityResource.java:77)
    at org.acanthite.resources.UtilityResource$quarkusrestinvoker$ids_8602df045ce9b7e168a75788bbd936486ed83b98.invoke(Unknown Source)
    at org.jboss.resteasy.reactive.server.handlers.InvocationHandler.handle(InvocationHandler.java:29)
    at io.quarkus.resteasy.reactive.server.runtime.QuarkusResteasyReactiveRequestContext.invokeHandler(QuarkusResteasyReactiveRequestContext.java:141)
    at org.jboss.resteasy.reactive.common.core.AbstractResteasyReactiveContext.run(AbstractResteasyReactiveContext.java:145)
    at io.quarkus.vertx.core.runtime.VertxCoreRecorder$14.runWith(VertxCoreRecorder.java:576)
    at org.jboss.threads.EnhancedQueueExecutor$Task.run(EnhancedQueueExecutor.java:2513)
    at org.jboss.threads.EnhancedQueueExecutor$ThreadBody.run(EnhancedQueueExecutor.java:1538)
    at org.jboss.threads.DelegatingRunnable.run(DelegatingRunnable.java:29)
    at org.jboss.threads.ThreadLocalResettingRunnable.run(ThreadLocalResettingRunnable.java:29)
    at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
    at java.base/java.lang.Thread.run(Thread.java:833)
Caused by: java.lang.InstantiationException
    at java.base/jdk.internal.reflect.InstantiationExceptionConstructorAccessorImpl.newInstance(InstantiationExceptionConstructorAccessorImpl.java:48)
    at java.base/java.lang.reflect.Constructor.newInstanceWithCaller(Constructor.java:499)
    at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:480)
    at org.apache.ibatis.reflection.factory.DefaultObjectFactory.instantiateClass(DefaultObjectFactory.java:66)
    ... 22 more

下面是我的映射器的XML:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
        PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
        "https://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.acanthite.repository.UtilityRepository">
    <select id="getAllIds" resultType="integer">
        select id from utility;
    </select>
</mapper>

映射器界面:

@Mapper
public interface UtilityRepository {
  ImmutableList<Integer> getAllIds();
}

以及我如何使用它:

@ApplicationScoped
@AllArgsConstructor
public class UtilityService {
  private final UtilityRepository repository;
  
  public ImmutableList<Integer> getAllIds() {
    return repository.getAllIds();
  }
}

有没有库或变通方法教mybatis如何实例化Guava的不可变集合(或者基本上任何其他非Java集合)?

推荐答案

以下是代码的关键部分:

  public Object execute(SqlSession sqlSession, Object[] args) {
    Object result;
    switch (command.getType()) {
      // ...
      case SELECT:
        if (method.returnsVoid() && method.hasResultHandler()) {
          executeWithResultHandler(sqlSession, args);
          result = null;
        } else if (method.returnsMany()) {
          result = executeForMany(sqlSession, args);
        } else if (method.returnsMap()) {
          result = executeForMap(sqlSession, args);
        } else if (method.returnsCursor()) {
          result = executeForCursor(sqlSession, args);
        } else {
          Object param = method.convertArgsToSqlCommandParam(args);
          result = sqlSession.selectOne(command.getName(), param);
          if (method.returnsOptional() && (result == null || !method.getReturnType().equals(result.getClass()))) {
            result = Optional.ofNullable(result);
          }
        }
        break;
      // ...
    }
    if (result == null && method.getReturnType().isPrimitive() && !method.returnsVoid()) {
      throw new BindingException("Mapper method '" + command.getName()
          + "' attempted to return null from a method with a primitive return type (" + method.getReturnType() + ").");
    }
    return result;
  }
  private <E> Object executeForMany(SqlSession sqlSession, Object[] args) {
    List<E> result;
    Object param = method.convertArgsToSqlCommandParam(args);
    if (method.hasRowBounds()) {
      RowBounds rowBounds = method.extractRowBounds(args);
      result = sqlSession.selectList(command.getName(), param, rowBounds);
    } else {
      result = sqlSession.selectList(command.getName(), param);
    }
    // issue #510 Collections & arrays support
    if (!method.getReturnType().isAssignableFrom(result.getClass())) {
      if (method.getReturnType().isArray()) {
        return convertToArray(result);
      }
      return convertToDeclaredCollection(sqlSession.getConfiguration(), result);
    }
    return result;
  }
  private <E> Object convertToDeclaredCollection(Configuration config, List<E> list) {
    Object collection = config.getObjectFactory().create(method.getReturnType());
    MetaObject metaObject = config.newMetaObject(collection);
    metaObject.addAll(list);
    return collection;
  }

https://mybatis.org/mybatis-3/zh/jacoco/org.apache.ibatis.binding/MapperMethod.java.html

不幸的是,看起来唯一的 Select 是使用原始列表,使用no-arg构造函数+addAll转换为新集合,或者转换为array.因此,我会这样做:

@Mapper
public interface UtilityRepository {
  List<Integer> getAllIds();
}

@ApplicationScoped
@AllArgsConstructor
public class UtilityService {
  private final UtilityRepository repository;
  
  public ImmutableList<Integer> getAllIds() {
    return ImmutableList.copyOf(repository.getAllIds());
  }
}

Java相关问答推荐

如何在Inspaut中获取当前路径的 * 模式 *?

如何让HikariCP指标在NewRelic中正确显示?

我可以从Java模块中排除maven资源文件夹吗?

具有额外列的Hibert多对多关系在添加关系时返回NonUniqueHealthExcellent

当切换javaFX场景时,stage的大小正在Minimize

OpenJDK、4K显示和文本质量

填写文本字段后锁定PDF

Spring @Value default无法计算表达式

我如何知道MediaDiscoverer何时完成发现介质?

通过Spring Security公开Spring Boot执行器端点

使SLF4J在Android中登录到Logcat,在测试中登录到控制台(Gradle依赖问题)

在Java中将int[]矩阵添加到ArrayList中,但出现错误

在实例化中指定泛型类型与不指定泛型类型之间的区别

Java集合:NPE,即使没有添加空值

用于Java的Visual Studio代码完成不起作用

我们可以在方法中声明接口吗?

Java System.getProperty在哪里检索user.home?

如何使用Rascal Evaluator从编译的JAR访问Rascal函数?

如何以事务方式向ibmmq发送消息

java 11上出现DateTimeParseException,但java 8上没有