5

There are many articles stating that using DTOs is not necessary with JPA/hibernate

Use the open session in view pattern, or a disciplined assembly phase to avoid problems with unfetched data.Hibernate frees the developer from writing tedious Data Transfer Objects (DTO)... The above lines are from https://docs.jboss.org/hibernate/orm/3.5/reference/en/html/best-practices.html

Also In an article by a SO member Bohzo I read DTO's are rarely required

Even in articles against exposing entities state that there is no need of having a DTO when Entities do not have any behavior (when they are POJOs) as in the anemic domain model

Let's Say there is an Entity class

class Department{
    List<Employee> employees //lazily loaded collection 

Each object in the collection contains another lazily loaded collection

 class Employee{
    List<Account> accounts

There is a getDepartment() method which is used by a restful service to provide Json information of the Department.

The possible solutions are

Solution 1) As per hibernate documentation opening and closing the hibernate session per request (that is the uppermost method in controller is transactional?) or better using Spring's OpenSessionInViewFilter as per this SO post

Why can't hibernate re-open a session and fetch the lazily loaded object instead of throwing an exception?Is there a way to configure this with JPA/hibernate?

Solution 2) Again as in hibernate doc another way is to have an assembly phase.What exactly does it mean ? Break down the getDepartment API into different API's of the DAO ?

Solution 3)Use DTO's Even with DTO's how can the persistence layer know whether view needs a fully loaded Department or not.This leads to breaking the API into getDepartmentOnly() getDepartmentWithEmployees() and others saying whether to get 100% of the department object or a part of it One API broke down into many and one entity mapped to many DTO's

Solution 4) As in bohzo's article with paginated views avoid lazy loading and have queries to fetch limited results

Please correct Solution 2 and explain what is intended in the hibernate documentation?

Community
  • 1
  • 1
rakesh99
  • 1,234
  • 19
  • 34
  • 2
    See my [answer to this question](http://stackoverflow.com/questions/31165016/dto-and-entity-in-one-object/31171996#31171996). Yes, EJB3 promised that DTOs were no longer required. We trusted that 'mantra' when we started out with EJB3 8 years ago. After creating 300+ Entities we realised it just wasn't going to work, and we needed DTOs. As I said, see my answer to the other question. – DuncanKinnear Jul 19 '15 at 21:40
  • 1
    Thanks but my question was not whether DTO's are 'always' required.That appears to be opinion based.My question is about their correct usage. – rakesh99 Jul 20 '15 at 03:59
  • 1
    Exposing the model in a restful web service is considered bad practise. What is more, the API should NEVER be designed according to the needs of the view. So, if your API is restful, you should use DTOs. Otherwise, you're just doing RPC. – fps Jul 20 '15 at 04:40
  • 1
    Please understand that my question is not that which is a better practice.How to achive what the documentation states about not using DTO and how to structure DTO's for this example – rakesh99 Jul 20 '15 at 05:52
  • Using DTO's doesn't make a service restful.By exposing entities ,a representation of the entity is sent which may or may not be same as the entity itself.If the DTO is just replicating the entity what point does it make? Here you can find entity used in jax-rs services http://www.adam-bien.com/roller/abien/entry/javaee_7_retired_the_dto This is a blog from a member of jpa2 jcp and jsrs . 'Always' is not always right – rakesh99 Jul 26 '15 at 15:54

1 Answers1

3

Assembly phase in the Hibernate documentation means:

public Department getDepartmentWithEmployees(Long departmentId) {
   Department result = em.find(Department.class, departmentId);
   Hibernate.initialize(result.getEmployees());
   return result;
}

Or:

public Department getDepartmentWithEmployees(Long departmentId) {
   String query = "select d from Department d join fetch d.employees where d.id = :departmentId";
   ...
}

Or ...

Basically, it's up to you to fetch the necessary data to provide the balance between code readability and maintainability vs performance (the number of different APIs vs the amount of data fetched).

This is not a JPA/Hibernate specific issue; you would need to consider this with any other persistence framework (or with direct JDBC) as well.

Dragan Bozanovic
  • 23,102
  • 5
  • 43
  • 110
  • In JPA is there any not hibernate specific way to fetch the lazily loaded entities? Also came across http://stackoverflow.com/questions/16833893/how-to-serialize-lazy-loaded-entities-with-jackson-module-hibernate which gets rid of exception in lazy loading during json conversion or another way I had thought to to set the lazy collections to null in api's which didn't need to fetch them – rakesh99 Jul 26 '15 at 08:14
  • But here also there will be two methods one in which lazy collection will be initialized and other in which it will be a proxy which hibernate jackson module can ignore or I can explicitly set it to null.So using DTO's just to get rid of lazy loading exception outside transaction isn't justified? – rakesh99 Jul 26 '15 at 11:30
  • Yes, you can just invoke a method on an uninitialized proxy to trigger its initialization. But I prefer `Hibernate.initialize` because it's more explicit and I don't have to care whether the proxy is really fully initialized (for example calling `.size()` on Hibernate extra lazy collection will just initialize the size of the collection, not its elements). – Dragan Bozanovic Jul 26 '15 at 15:16
  • I agree, using DTOs just to get rid of lazy loading exception outside transaction isn't justified. – Dragan Bozanovic Jul 26 '15 at 15:18