Search code examples
jpadozer

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


I met a very strange phenomenon when using dozer in jpa project. I have a UserSupplier object and a Supplier object.

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

In my code I first query a UserSupplier List, then convert it to SupplierList.

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

Then I convert SupplierList to SupplierView List and return it to Caller.

BeanMapper.mapList(supplierList, SupplierView.class);

My dozer configure in these objects like below

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

 SupplierView:
 private int supplierId;

Very funny, supplierId in SupplierView always 0(default int value),but other fileds can convert successfully, only id field fail. I don't why is this, why only id field can't convert to supplierId, but other fields could?

For above problem, there are below solutions

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;

Solution

  • This is probably because JPA uses proxy objects for lazy loading of single entity reference. Proxy object is effectively a subclass of your entity class. I guess that dozer can find @Mapping annotation only on fields declared in the class of given object, and not on fields defined in parent classes. Dozer project states that annotation mapping is experimental. Therefore it is possible that it does not cover mapping class hierarchies well.

    I suggest to try configure mapping of supplierId by other means (XML, dozer mapping API) and see if it works. If all fails, you could write a custom MapperAware converter between Supplier and SupplierView. You would map source object to target object using supplied mapper, and finilize it by copying value of id to supplierId.