当前位置: 首页 > 知识库问答 >
问题:

由于循环问题,Mapstruct的异常

贺飞
2023-03-14

我有一个开发项目,使用SpringDataJPA和MapStruct在实体和DTO之间进行映射。上周我决定是时候解决FetchType.EAGERvsLAZY问题了,我已经推迟了一段时间。我选择使用@NamedEntityGraph@EntityGraph在需要时加载属性。但是,在执行从实体到dto的映射时,我遇到了这个问题。我想我知道这在哪里发生,但我不知道如何通过它。

密码

@NamedEntityGraph(name="Employee.full", ...)
@Entity
public class Employee {
  private Set<Role> roles = new HashSet<>();
}

@Entity
public class Role {
  private Set<Employee> employees = new HashSet<>();
}

public interface EmployeeRepository extends JpaRepository<Employee, Long> {
  @EntityGraph(value = "Employee.full")
  @Override
  Page<Employee> findAll(Pageable pageable);
}

@Service
public class EmployeeService {
  public Page<EmployeeDTO> findAll(PageRequest pageRequest) {
    Page<Employee> employees = repository.findAll(pageRequest); // ok
    Page<EmployeeDTO> dtos = employees.map(emp -> mapper.toDTO(emp, new CycleAvoidMappingContext()); // this is where the exception happens
    return dtos;
  }
}

// also there is EmployeeDTO and RoleDTO classes mirroring the entity classes 
// and there is a simple interface EmployeeMapper loaded as a spring component 
// without any special mappings. However CycleAvoidingMappingContext is used.

我已经跟踪了当映射器试图映射角色依赖关系时发生的Lazy初始化异常Role对象有Set

使用FetchType时。EAGERnew CycleAvoidingMappingContext()解决了这个问题,但是在LAZY中,这不再有效。

有人知道如何避免异常,同时正确映射我的DTO吗?

共有1个答案

仲孙毅
2023-03-14

问题在于,当代码从findAll返回时,实体不再被管理。因此,您有一个LazyInitializationException,因为您正在会话范围之外尝试访问尚未初始化的集合。

添加渴望使其工作,因为它确保集合已经初始化。

你有两个选择:

  1. Using an EAGER fetch;
  2. Make sure that the entities are still managed when you return from the findAll. Adding a @Transactional to the method should work:
    @Service
    public class EmployeeService {
    
        @Transactional
        public Page<EmployeeDTO> findAll(PageRequest pageRequest) {
            Page<Employee> employees = repository.findAll(pageRequest);
            Page<EmployeeDTO> dtos = employees.map(emp -> mapper.toDTO(emp, new CycleAvoidMappingContext());
            return dtos;
        }
     }
    

    我想说,如果您需要初始化集合,那么急切地获取它(使用实体图或查询)是有意义的。

    有关Hibernate ORM中实体状态的更多详细信息,请查看本文。

    更新:发生此错误的原因似乎是Mapstruct正在转换集合,即使DTO中不需要它。在这种情况下,您有不同的选项:

    1. Remove the field roles from the DTO. Mapstruct will ignore the field in the entity because the DTO doesn't have a field with the same name;
    2. Create a different DTO class for this specific case without the field roles;
    3. Use the @Mapping annotation to ignore the field in the entity:
      @Mapping(target = "roles", ignore = true)
      void toDTO(...)
      
      @Mapping(target = "roles", ignore = true)
      void toSkipRolesDTO(...) // same signature as toDTO
      

 类似资料:
  • 我已经在其他项目中多次遇到这个问题。现在我试图理解异常处理,但我仍然不知道它到底是如何工作的。我试图用循环编程一个计算器,当我试图输入字符串时,会出现InputMismatchException-我试图捕捉它,但出于某种原因,在catch子句之后,java给了我另一个InputMismatchException,为什么? 起初有一个无限循环,我用扫描器求解。nextInt() 在catch块内,但

  • 问题内容: 我有以下代码片段。 上面的代码用于生成5个链接,并将每个链接与警报事件绑定以显示当前链接ID。但这是行不通的。当您单击生成的链接时,它们都说“链接5”。 但是以下代码段符合我们的预期。 这里引用了以上两个片段。 但是它是如何工作的以及 关闭 是如何工作的,这些都是我无法理解的。为什么第一个不起作用而第二个却起作用?任何人都可以对魔术进行详细说明吗? 谢谢。 问题答案: 解释第一个示例:

  • 我是java的新手,我正在编写这个简短的程序,您可以在其中猜测1到10之间的数字。正确的数字存储为整数。如果您猜测较低的数字,它应该说“正确的数字较高”,如果您猜测较高,它应该说“正确的数字较低”。这是我所拥有的: 所以很明显这是行不通的,因为如果你输入一个更小的数字,它会跳到下一个数字,即使这个数字更大,它也是正确的。那么,我如何解决这个问题,让它检查两个语句呢?抱歉解释得不好。谢了。

  • 我已经创建了一个字符串数组,其中包含单词“磅”、“美元”和“欧元”,我想把这些标签放在旗帜的左边(为了用户应用程序的清晰性,因为不是每个用户都知道哪个货币属于哪个国家)。 我创建了一个循环,将创建一个标签,并将其分配到旗帜的左侧,它应该使一个"英镑"标签,然后一个"美元",然后一个"欧元"每次穿越Y轴南部,使他们与旗帜对齐然后,它将重置数组计数以返回到正确的字符串,沿着x轴移动并再次重复。然而,它

  • 本文向大家介绍spring循环注入异常问题的解决方案,包括了spring循环注入异常问题的解决方案的使用技巧和注意事项,需要的朋友参考一下 今天在做项目的时候突然遇到一个问题:启动服务器的时候spring没报错,可是当我访问某个页面的时候spring报Request bean is currently in creation: is there an unresolvable circular r

  • 这段代码是为一个基本的杂货计算器的按钮。当我按下按钮时,一个输入对话框显示您在哪里输入您的商品价格。我遇到的问题是,我不知道如何获得循环,使输入对话框在输入后弹出。 我希望它总是回来,除非用户选择ok与nothing或cancel,在这种情况下,循环应该中断并填充剩余的框。使用当前的代码,我必须每次手动按下按钮来恢复对话框。我一直在玩不同的while条件和if语句,但我似乎无法让它发挥作用。我是一