首页 文章

如何使用ModelMapper基于源值而不是其类型创建条件转换器?

提问于
浏览
0

我正在尝试使用ModelMapper将实体映射到DTO . 当没有加载@JoinColumn(延迟加载)时出现问题 . ModelMapper尝试访问延迟加载实体的属性,然后抛出LazyInitializationException .

我已经有了解决这个问题的策略,但我找不到能够满足我需要的单一ModelMapper功能 .

Here is what I need to do: 对于每个未加载的实体,我将使用我的工厂创建一个新的目标对象 . 如果加载了对象,则必须应用默认映射 .

以下示例是一个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:我是've looked into ModelMapper'的代码并注意到当调用ConditionalConverter.match时,上下文已经存在,因此它拥有源代码 . 如果ModelMapper还有一个ConditionalContextConverter接口传递match方法中的上下文怎么办?只是一个想法 .

1 回答

  • 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;
        }
    }
    

相关问题