I am looking for a good way to create Data Transfer Objects (DTO) from a JPA Entity and vice versa. I want to send the DTO as JSON to a client, then receive the modified DTO and save it back to the database. It would be the most ease to perform the merge method from the EntityManager on the received object after it has been parsed from JSON to it's Java class.
For example there is the following Entity and the Rest method for saving the modified object:
@Entity
@Table(name="CUSTOMER")
public class Customer {
@Id
Long id;
@Version
Long version;
String name;
String address;
String login;
String password;
String creditCardNumber;
@OneToMany(cascade = CascadeType.ALL)
List<Foo> fooList;
... Getter() and Setter()
}
private EntityManager em;
@POST
@Path("/saveCustomer")
public void saveCustomer ( Customer customer) {
em.merge(customer);
return;
}
This works fine as long as I send the whole Entity Class as JSON and receive the whole Entity back. Then the EntityManager will merge the modified object to the database. But when I only want to provide a subset of the Entity (like only name and address of the customer) there will be problems:
What would be the best way to create a subset of an Entity?
-Writing the DTOs for the Entity by hand? This will generate duplicate code for every subset of the entity, which has to be maintained.
How to merge a DTO which is a subset of an Entity, back to the database?
-Using the merge() method of the EntityManager doesn't work. At first the DTO is no entity hence it can't be merged. And Just creating an Entity from the DTO, will have some unset values in the Entity. After a merge the values will be NULL in the database.
One idea I came up with, was to specify additional Entities for each subset I want to have for an entity. (Like a database view) This would be duplicate code, but it could solve the problem with the merging of the DTO to the database. (And maybe this code can be auto-generated)
For example the Entity CustomerView1 links to the same table as the Customer class, but only provides the name and address of the customer. It's a DTO for the real Customer class, which can be sent as JSON and modified outside of the server. This class can then also be merged to the database by the EntityManager.
@Entity
@Table(name="CUSTOMER")
public class CustomerView1 {
@Id
Long id;
@Version
Long version;
String name;
String address;
... Getter() and Setter()
}
But I have doubts about this solution, I don't know if this will mess with the JPA's caching of Entities and may cause some problems.
My Question is, is there a pattern to solve code duplication for DTOs and merging the DTOs back to the database?
Or is there a library for this purpose? - Something, like auto-generation for the DTOs and copying the DTOs back to the real Entity, to make it possible to merge them with the EntityManager.
If the size difference between the entity and the DTO is not considerable, you can opt for sending the Entity.
When using DTOs, to overcome concurrency issues like lost update, you have to incorporate the entity version in your DTO.
If you don't use the Entity version, and the underlying row is changed between the REST GET and PUT methods, you will override changes the end-user was not really aware of.
Whenever I have to alter an Entity (Create, Update, Delete), I rely on the JPA and Hibernate Optimistic Locking mechanism.
For UI lists, tables, search results DTOs are a viable option, since you are only interested in a projection of your originating Entity. This way you speed-up retrievals and you can benefit from other SQL features (window-functions) that are not supported by JPA.