如何防止模型映射器急切加载 spring 数据 jpa 中的关联集合?

How to prevent model mapper from eager loading associated collections in spring data jpa?

如何防止模型映射器预先加载 spring 数据 jpa 中的关联集合?

呃,我上次遇到过这个问题,我必须说这是我开始不喜欢的地方 ModelMapper :)

基本上唯一的方法是使用适当的映射定义您自己的 TypeMap,这将省略集合映射。问题是如果你已经获取了 Entity 实例,有时你想将它映射到带有集合的目标 class ,有时则不然(取决于是否获取了集合)。

如果您使用的是 Hibernate,这会导致您应该检查是否使用一些奇怪的机制(例如检查 LazyInitializationException 或字段的代理实现属性的类型)来获取 Collection 字段。 ..疯狂

我的建议是创建几种类型的目标模型 class 有或没有集合字段,并且对于它们中的每一个 custom mappings configuration (如果您的应用程序设计允许)或 根本不使用 ModelMapper 在这个特定实体的情况下(并且只提供你自己的映射机制)

我遇到了这个问题,我有一个 User 实体,其中 One-to-Many 映射到角色,即一个用户有多个角色

@Entity
@Table(name = "user")
public class User implements Serializable {
    @Id
    @Basic(optional = false)
    @Column(name = "id")
    private String id;

    @Basic(optional = false)
    @Column(name = "name")
    private String name;

    @Basic(optional = false)
    @Column(name = "email_id")
    private String emailId;

    .............
    @OneToMany(cascade = CascadeType.ALL, mappedBy = "user")
    private Collection<UserRole> userRoleCollection;


}

我想将此 class 映射到 DTO

@Data
public class UserVO implements Serializable {
    /**
     * 
     */
    private static final long serialVersionUID = -7985084979805425972L;
    private String name;
    private String emailId;
    ......
    private List<RoleVO> roles;
}

基本上我需要使用 ModelMapper 将 Collection<UserRole> 转换为 List<RoleVO>,其中 Collection<UserRole> 是延迟加载的。

我设置了一个 ModelMapper Converter 如下:

@Configuration
public class ModelMapperConfiguration {
    public ModelMapper modelMapper() {
        ModelMapper mapper = new ModelMapper();
        TypeMap<User, UserVO> userToUserVOTypeMap = mapper.createTypeMap(User.class, UserVO.class);
        TypeMap<Role, RoleVO> roleRoleVOTypeMap = mapper.createTypeMap(Role.class, RoleVO.class);

        Converter<Collection<UserRole>, List<RoleVO>> collectionListConverter =
                ctx -> (ctx == null) ? null : ctx.getSource().stream()
                        .map(ur -> roleRoleVOTypeMap.map(ur.getRole()))
                        .collect(Collectors.toList());
        userToUserVOTypeMap.addMappings(mpr ->
                mpr.using(collectionListConverter)
                        .map(src -> src.getUserRoleCollection(), UserVO::setRoles));

   }
}

stream() 方法应该为延迟加载的数据触发 FETCH。