jpa项目中使用dozer的一个奇怪现象,为什么在lazy load对象中的Mapping注解不起作用?

A strange phenomenon when use dozer in jpa project,why Mapping annotation in lazy load object can't work?

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

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

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

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

然后我将 SupplierList 转换为 SupplierView List,然后 return 将其转换为 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;

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

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

来完成它

阅读推土机文档后,我发现了一些东西。尝试之后,我得到了另一种解决方案。 即在classpath中加入一个dozer.properties,里面的内容为

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

更多详情请看 http://dozer.sourceforge.net/documentation/proxyhandling.html