mybatis-mapper / mapper

MyBatis Mapper
https://mapper.mybatis.io
Apache License 2.0
325 stars 47 forks source link

使用 jpa 模块 insert 失败 #40

Closed ydq closed 2 years ago

ydq commented 2 years ago

引入 jpa 模块后,执行 insert 操作时获取实体类型出错,导致表名错误、字段也没能获取到,最终导致sql错误而无法执行

debug 追了一下,问题出在 JpaEntityClassFinder#isEntityClass方法判断有误

该方法调用了 SimpleTypeUtil#isSimpleType 判断是否为基础类型时

SimpleTypeUtil 中有定义一个静态方法registerPrimitiveTypes 去注册 int 等这些原始类型,但代码中没有去调用这个方法初始化

而 insert、update、delete 方法的返回值为原始类型 int,所以会误将 int 类型作为了 Entity 类型来处理


因为 spi JpaEntityClassFinder 类 获取实体类型 的时候 没有重写 findEntityClass 方法,所以调用的是父类的方法

  public Optional<Class<?>> findEntityClass(Class<?> mapperType, Method mapperMethod) {
    //先判断返回值
    Optional<Class<?>> optionalClass;
    if (mapperMethod != null) {
      optionalClass = getEntityClassByMapperMethodReturnType(mapperType, mapperMethod);
      if (optionalClass.isPresent()) {
        return optionalClass;
      }
      //再判断参数
      optionalClass = getEntityClassByMapperMethodParamTypes(mapperType, mapperMethod);
      if (optionalClass.isPresent()) {
        return optionalClass;
      }
      //最后从接口泛型中获取
      optionalClass = getEntityClassByMapperMethodAndMapperType(mapperType, mapperMethod);
      if (optionalClass.isPresent()) {
        return optionalClass;
      }
    }
    return getEntityClassByMapperType(mapperType);
  }

该方法优先使用 当前调用的 mapper 方法的返回值作为 Entity 类型

而 insert 相关的方法 返回的是受影响的行数,是个 int,所以导致获取的 EntityClass 成了 int

最后在 JpaEntityClassFinder#isEntityClass 中判断是否为实体类型,检查的时候没有匹配 基础原始类型

虽然有在SimpleTypeUtil 类中定义了 registerPrimitiveTypes 方法,但是没有使用

导致 生成的sql错误

只测试了 insert 相关的方法,没测试其他方法,猜测 update / delete 应该也都有问题

abel533 commented 2 years ago

如果是误将基本类型返回值当成了实体类,应该在Finder处理,不建议PR中直接改的SimpleTypeUtil,作用不同,影响范围不同。

ydq commented 2 years ago

如果是误将基本类型返回值当成了实体类,应该在Finder处理,不建议PR中直接改的SimpleTypeUtil,作用不同,影响范围不同。

@abel533 嗯,确实没考虑这么多,主要是看到 SimpleTypeUtil 只有 JpaEntityClassFinder 有在使用,所以就直接在 SimpleTypeUtil 中去修改了

PR 已经重新推送了,将调整放在了 Finder 中