java - Spring modelmapper 映射延迟加载的实体
问题描述
我正在使用 modelmapper ( http://modelmapper.org/ ) 将具有延迟加载的对象列表(通过休眠)的实体映射到具有 modelmapper.map() 的 DTO。
输出的 dto 有一个空值作为列表,尽管实体的列表已填充。当我更改为急切加载时,一切正常,但我的查询变得太大,所以这不是一个选择。
有谁知道modelmapper如何映射代理的休眠实体类?
这是我的父实体:
public class Category {
@OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true, mappedBy = "category")
@OrderBy("sortOrder")
private SortedSet<CategorySubarea> categorySubareas;
}
dto:
@Data
@AllArgsConstructor
@NoArgsConstructor
@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS)
public class CategoryDto {
private LinkedHashSet<@Valid CategorySubareaDto> categorySubareas;
}
这就是我使用映射器的方式(sourceCategory 是实体,destinationCategory 是 dto):
modelMapper.map(sourceCategory, destinationCategory);
当然这样的事情是可行的,但这是一个非常丑陋的解决方法:
sourceCategory.getCategorySubareas().forEach(subarea -> {
// do nothing here
});
modelMapper.map(sourceCategory, destinationCategory);
解决方案
我知道用 mapstruct 处理惰性/dto 的好方法。只需创建自定义上下文类
public class CycleAvoidingMappingContext {
private Map<Object, Object> knownInstances = new IdentityHashMap<Object, Object>();
PersistenceUtil persistenceUnitUtil = Persistence.getPersistenceUtil();
@SneakyThrows
@BeforeMapping
public <T> T getMappedInstance(Object source, @TargetType Class<T> targetType) {
if (source != null) {
for (PropertyDescriptor pd : Introspector.getBeanInfo(source.getClass()).getPropertyDescriptors()) {
if (pd.getWriteMethod() != null && pd.getReadMethod() != null && !"class".equals(pd.getName())) {
var vvalue = pd.getReadMethod().invoke(source);
if (vvalue == null) {
continue;
}
var classs = vvalue.getClass();
if (HibernateProxy.class.isAssignableFrom(classs)) {
try {
if (Hibernate.isInitialized(vvalue) == false) {
pd.getWriteMethod().invoke(source, null);
}
} catch (Exception e) {
}
}
}
}
}
return (T) knownInstances.get(source);
}
@BeforeMapping
public void storeMappedInstance(Object source, @MappingTarget Object target) {
knownInstances.put(source, target);
}
}
并像这样使用它:
CrmClientMapper.INSTANCE.getDto(client, new CycleAvoidingMappingContext());
它将跳过惰性字段,因此您不会得到惰性初始化异常和对 DB 的不必要查询。只是您用于指定要获取的关系的实体图。
推荐阅读
- jestjs - vue test utils SyntaxError: Unexpected token import
- cucumber - Cucumber JVM:如何从带有场景大纲的钩子中的示例部分访问数据?
- django - ip地址的SSL证书[Nginix+django服务器]
- php - 我想在 wordpress 的同一页面上过滤类别明智的帖子
- javascript - 如何从对象数组创建哈希对象
- asp.net - Ruby OpenSSL::Cipher::CipherError(未设置密钥)
- python - Python检索数据框的行索引
- javascript - 如何判断等待的 Service Worker 是否准备就绪?
- react-native - 升级到 RN 0.57 后出现错误,标题为 backgroundColor
- domain-driven-design - 领域驱动设计:“如果 E 存在,做 A,否则做 B”逻辑属于应用服务还是领域服务?