在jpa项目中使用推土机时出现奇怪的现象,为什么在延迟加载对象中映射注释无法正常工作?

时间:2015-10-21 09:58:41

标签: jpa dozer

在jpa项目中使用dozer时遇到了一个非常奇怪的现象。 我有一个UserSupplier对象和一个Supplier对象。

UserSupplier:
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "supplier_id", nullable = false)
private Supplier supplier;

在我的代码中,我首先查询UserSupplier列表,然后将其转换为SupplierList。

List<Supplier> supplierList = new ArrayList<>(usList.size());
usList.forEach(us -> supplierList.add(us.getSupplier()));

然后我将SupplierList转换为SupplierView List并将其返回给Caller。

BeanMapper.mapList(supplierList, SupplierView.class);

我的推土机在这些对象中进行配置,如下所示

 Supplier:
 @Id
 @GeneratedValue
 @Mapping("supplierId")
 private int id;

 SupplierView:
 private int supplierId;

非常有趣,SupplierView中的supplierId始终为0(默认int值),但其他文件可以成功转换,只有id字段失败。我不知道为什么这样,为什么只有id字段无法转换为supplierId,但其他字段可以?

对于上述问题,有以下解决方案

1. Change field name (supplierId to id):

 Supplier:
 // @Mapping("supplierId")
 private int id;

 SupplierView:
 private int id;

but Caller(front-end) have to change code.

2. Change fetchType to eager:

 UserSupplier:
 @ManyToOne
 private Supplier supplier;

2 个答案:

答案 0 :(得分:1)

阅读推土机文档后,我发现了一些事情。尝试之后,我得到了另一个解决方案。 那就是在类路径中添加一个dozer.properties,里面的内容是

org.dozer.util.DozerProxyResolver=org.dozer.util.HibernateProxyResolver

更多细节请看 this

答案 1 :(得分:0)

这可能是因为JPA使用代理对象来延迟加载单个实体引用。代理对象实际上是实体类的子类。我猜这个推土机只能在给定对象的类中声明的字段上找到@Mapping注释,而不能在父类中定义的字段上找到。 Dozer项目声明注释映射为experimental。因此,它可能不会很好地覆盖映射类层次结构。

我建议尝试通过其他方式(XML,推土机映射API)配置supplierId的映射,看看它是否有效。如果全部失败,您可以在SupplierSupplierView之间编写自定义MapperAware转换器。您可以使用提供的映射器将源对象映射到目标对象,并通过将id的值复制到supplierId来确定它。