219 Star 2.4K Fork 470

MyBatis-Flex / MyBatis-Flex

 / 详情

[Bug]: FlexDefaultResultSetHandler.linkObjects 不应该给集合中添加默认元素

已完成
创建于  
2024-04-11 17:27

这个 Bug 是否已经存在:

如何复现:

此问题同#I9FTOI:[功能建议]: pageAs查询时VO中的字段映射,不应该处理嵌套的List对象。
当类中存在一个集合时,不应该往里面放入默认的元素。
假设这个属性是一个RelationOneToMany,当没有关联的元素时,会出现一个[{}]结构
输入图片说明
以这张图为例 会出现
{
orderEmployeeList:[{}]
}
预期的结果应该是
{
orderEmployeeList:[]
}

预期结果:

如果查询不到结果 应该是空集合 或者null

实际结果:

变成了有一个空对象(字段全为null)的集合

截图或视频:

输入图片说明

关联版本:

1.8.7

评论 (16)

SWQXDBA 创建了任务
SWQXDBA 添加了
 
bug
标签
展开全部操作日志

[图片上传中…(image-CrBDLFtz74v4QSpKaIWq)]

麻烦 @Michael Yang @王帅 看下这个问题,这个问题的影响比较严重,所有嵌套的集合结构都存在bug,导致该功能大面积不可用。

所有的ToMany Relation事实上都存在出错的风险

请给出示例,以及错误信息。

这个问题比想象中的复杂,并不是原先想的原因。
问题出在 没有在resultMapping中对重复的列使用$进行区分。

现在我追踪到了TableInfo.buildResultMap.

create table person
(
    id         bigint primary key,
    name varchar(200)

);
create table child
(
    id         bigint primary key,
    person_id bigint,
    student_id bigint,
    name varchar(200)

);
create table student
(
    id   bigint primary key,

    person_id bigint
);

```java
public class Child extends BaseEntity{

    Long personId;

    Long studentId;

    String name;
}
public class Person extends BaseEntity{

    String name;

    @RelationOneToMany(targetTable = "student", targetField = "personId")
    List<Student> students ;
}

public class Student extends BaseEntity{

  //  String name;

    Long personId;

    @RelationOneToOne(targetTable = "child", targetField = "studentId")
    Child child;
    
}

    public static void main(String[] args) {
        final ConfigurableApplicationContext context = SpringApplication.run(Demo7Application.class, args);
        //开启审计功能
        AuditManager.setAuditEnable(true);

//设置 SQL 审计收集器
        MessageCollector collector = new ConsoleMessageCollector();
        AuditManager.setMessageCollector(collector);
        final PersonMapper mapper =(PersonMapper) Mappers.ofEntityClass(Person.class);

        final Person selectPerson = mapper.selectOneById(1L);

        System.out.println(selectPerson);
    }

输入图片说明

可以看到 当孙子层级中出现了祖先层级中的同名字段时,可以复现这个问题(但是父辈中不存在这个属性)
即:这个属性在第一级和第三级存在 但是在第二级不存在,可能因为中断了,导致没有在ResultMap中拼接上$

我对这块逻辑不是很清楚,但是我觉得问题可能出在这里existedColumns的收集上
输入图片说明

我创建一个仓库 里面现成的代码可以用于复现这个问题
@王帅
https://gitee.com/swqxdba/flex-bug-report

升级到 1.8.7 再做测试。

ok,已经修改了demo的版本到1.8.7问题同样存在
输入图片说明
输入图片说明

我提供了测试demo仓库,测试仓库中的代码打个断点就可以复现
输入图片说明
这里mapper.selectOneById
输入图片说明
没有使用withRelation,显然这里的student应该是空集合或者null

这个AliasTest没有关系,并不是别名功能

查询是直接selecctOneById的

或者你啥时候有空 跟你远程一下

private void collectNestedColumnsDfs(Class<?> root,List<String> collected,Set<Class<?>> existClasses){
    if(existClasses.contains(root)){
        return;
    }
    existClasses.add(root);
    final TableInfo tableInfo = TableInfoFactory.ofEntityClass(root);
    collected.addAll(Arrays.asList(tableInfo.allColumns));
    if(tableInfo.collectionType!=null){
        for (Class<?> entityType : tableInfo.collectionType.values()) {
            collectNestedColumnsDfs(entityType,collected,existClasses);
        }
    }
    if(tableInfo.associationType!=null){
        for (Class<?> entityType : tableInfo.associationType.values()) {
            collectNestedColumnsDfs(entityType,collected,existClasses);
        }
    }

}

public ResultMap buildResultMap(Configuration configuration) {
    // 所有的嵌套类对象引用
    List<String> collector = new LinkedList<>();
    collectNestedColumnsDfs(this.entityClass,collector,new HashSet<>());
    Stream<String> nestedColumns =collector.stream();

}
@王帅 看看这个实现

王帅 任务状态待办的 修改为已完成

登录 后才可以发表评论

状态
负责人
里程碑
Pull Requests
关联的 Pull Requests 被合并后可能会关闭此 issue
分支
开始日期   -   截止日期
-
置顶选项
优先级
参与者(2)
7984572 suomm 1698661375
1
https://gitee.com/mybatis-flex/mybatis-flex.git
git@gitee.com:mybatis-flex/mybatis-flex.git
mybatis-flex
mybatis-flex
MyBatis-Flex

搜索帮助