我正在尝试使用ModelMapper将实体映射到DTO。当未加载@JoinColumn(延迟加载)时,就会出现问题。 ModelMapper尝试访问延迟加载实体的属性,然后引发LazyInitializationException。
我已经有解决此问题的策略,但是我找不到一个可以满足我需要的ModelMapper功能。
这是我需要做的: 对于每个未加载的实体,我将使用工厂创建一个新的目标对象。如果加载了对象,则必须应用默认映射。
下面的示例是一个ModelMapper功能,如果它不提供源代码(仅提供源代码类型)而不能完全满足我的需求,则可以:
public static class MyConverter implements ConditionalConverter<Object, Object> {
private EntityManager em;
public MyConverter(EntityManager em) {
this.em = em;
}
@Override
public MatchResult match(Class<?> sourceType, Class<?> destinationType) {
Object source = null; // I need the source instead of its type.
PersistenceUnitUtil persistenceUnitUtil = em.getEntityManagerFactory().getPersistenceUnitUtil();
return persistenceUnitUtil.isLoaded(source) ? MatchResult.NONE : MatchResult.FULL;
}
@Override
public Object convert(MappingContext<Object, Object> context) {
return LazyEntityProxyFactory.factory(context.getSource(), context.getDestinationType()); // Creates the target object
}
}
你们提供我需要的任何ModelMapper功能吗?还是黑客?
* Obs:我研究了ModelMapper的代码,并注意到调用ConditionalConverter.match时上下文已经存在,因此拥有源。如果ModelMapper还具有ConditionalContextConverter接口,该接口在match方法中传递上下文,该怎么办?只是一个主意。
答案 0 :(得分:0)
我刚刚找到了我所需要的!秘密是从父实体检查属性。之后,我可以利用默认映射,并在需要时使用自己的工厂。
这是我的ConditionalConverter:
public static class MyConverter implements ConditionalConverter<Object, Object> {
private EntityManager em;
public MyConverter(EntityManager em) {
this.em = em;
}
@Override
public MatchResult match(Class<?> sourceType, Class<?> destinationType) {
return MatchResult.FULL;
}
@Override
public Object convert(MappingContext<Object, Object> context) {
Object source = context.getSource();
Object destination = context.getMappingEngine().createDestination(context);
try {
Field[] sourceFields = context.getSourceType().getDeclaredFields();
Field[] destinationFields = context.getDestinationType().getDeclaredFields();
for (Field sourceField : sourceFields) {
sourceField.setAccessible(true);
for (Field destinationField : destinationFields) {
destinationField.setAccessible(true);
if (sourceField.getName().equals(destinationField.getName())) {
Object sourceFieldValue = sourceField.get(source);
PersistenceUnitUtil persistenceUnitUtil = em.getEntityManagerFactory().getPersistenceUnitUtil();
if (persistenceUnitUtil.isLoaded(sourceFieldValue)) {
MappingContext<?, ?> myContext = context.create(sourceFieldValue, destinationField.getType());
Object destinationValue = context.getMappingEngine().map(myContext);
destinationField.set(destination, destinationValue);
} else {
// Here is your factory call;
destinationField.set(destination, SomeFactory.factory(sourceFieldValue, destinationField.getType()));
}
break;
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return destination;
}
}