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

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

杭柏
2023-03-14

我正在尝试使用ModelMapper将实体映射到DTO。当@JoinCollie未加载(延迟加载)时,问题就出现了。ModelMapper尝试访问延迟加载实体的属性,然后抛出LazyLaunalizationException。

我已经有了解决这个问题的策略,但我找不到一个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。匹配称为上下文已经存在,因此它拥有源。如果ModelMapper也有一个ConditionalContextConverter接口,该接口在match方法中传递上下文,该怎么办?只是一个想法。

共有1个答案

狄钧
2023-03-14

我刚刚找到了我需要的!秘诀是检查父实体的属性。之后,我能够利用默认映射,如果需要,还可以使用我自己的工厂。

这是我的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;
    }
}
 类似资料:
  • 假设我有一个表customer(int id,类型varchar,首选项jsonb)。类型可以是、等。根据列类型值,首选项JSON结构将有所不同。 在从数据库加载客户记录时,如果type=regular我希望将其转换为对象类型,如果type=premium我希望将其转换为对象类型。 我已经阅读了几篇关于使用JOOQ JSON转换器/绑定的教程。但是它们是一对一映射,不是基于条件的(取决于另一个列值

  • 我在严格模式下使用ModelMapper 地图(来源:学生到目的地:学生Dto) 为了在地址为空时转义映射,我设置了以下条件 问题是:即使地址不为null,我也要使街道和城市等于null。如何使用严格的映射来解决这个问题

  • 问题内容: 假设我有一个表 customer(int id,类型varchar,首选项jsonb) 。的 类型 可以是,基于该列类型值偏好JSON结构将是不同的等等。 从数据库加载客户记录时,如果 type = REGULAR, 我想将其转换为对象类型,如果 type = PREMIUM, 我想将其转换为对象类型。 我已经看过几本有关使用JOOQ JSON转换器/绑定的教程。但是它们是一对一的映射

  • 问题内容: 假设我有某种类型: 现在我想基于这种类型创建一个临时表,我该怎么做? 同样,从此:基于用户定义的类型创建表: 问题答案: [\Pure.Krome的答案)显示了如何使用表变量而不是#temp表。如果您确实想要基于已知表类型的#temp表(而不必知道列名/定义),则可以说: 现在,应与表类型的表结构匹配,减去约束(以及从SQL Server 2014开始的边际有用的二级索引)。 当然,随

  • 我正在使用OpenApi生成器为我的angular项目创建服务和模型。 这是我的 Json 的一个示例: 当我生成文件时,上传日期被转换为字符串而不是日期。 看: 有没有办法添加配置并使用Date作为格式为date-time的类型创建模型? 这是我用来启动生成的脚本:

  • 我有一个数据帧(df),看起来像这样: 现在,我的目标是,对于列中的每个,应将列中关联的-值替换为字符串。 到目前为止我做了什么 我偶然发现了,它替换了每个(这不是我要找的),缺少值和,这似乎是我想要的,但不起作用。此外,我尝试了这个: 缺少索引或某种迭代器来访问列中的等效值 我试过这个: 这显然不起作用。 我看了几个问题,但不能基于答案中的建议。布莱克的问题西蒙的问题szli的问题扬·威廉斯·图