Skip to main content

Reuse JPA Entities as DTO

Note : Major design advantages of JPA Entities are they can detached and used across tiers and networks and later can by merged.

Checkout this new way of querying entities in JPA 2.0


String ql = "SELECT new prepclass2.Employee (e.firstname, e.lastname) FROM Employee e";
List<Employee> dtos = em.createQuery(ql).getResultList();

The above query loads all Employee entities but with subset of data i.e. firstname, lastname.

Employee entity looks like this.

@Entity
@Table(name="emp")
public class Employee implements Serializable {

    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    @Column
    private String firstname;
    @Column
    private String lastname;
    @Column
    private String username;
    @Column
    private String street;
    @Column
    private String city;
    @Column
    private String state;
    @Column
    private String zipcode;
    @Column
    private String country;

    public Employee(){}
    public Employee(String firstname, String lastname){..}
    .
    .
}


Benefits of the above approach

  1. No separate DTO classes are required
  2. Re-Use same Entities for exchanging data in any combinations
  3. You can also create DTO classes and load data but why would you wanna do that when we can reuse entity classes
  4. No need to write converters (i.e. DTO-Assembler) for copying data from entities to dtos and vise-versa
  5. Performance efficient

Sample Load Test Results for loading 50K Employee entities using Hibernate JPA.


  General Way          -->  4621 ms
  Constructor Query -->   309 ms





Contructor Expression Rules
  1. Entity or non-Entity class can be used to load coarse-grained data
  2. Class should have a matching constructor defined with correct argument types
Also you can use Constructor queries with non-entity classes for instance

String ql = "SELECT new prepclass2.EmployeeDto (e.firstname, e.lastname) FROM Employee e";


    I encourage you to write your own test cases to validate performance gains. though I'm more than convince this is a nice way of sharing required data between tiers in a more performance efficient and simple way without introducing more dto classes to digest. 

    Comments

    Anonymous said…
    Aren't the entities created this way detached. If so could that be the reason for the performance gain? Also if that's the case, if you were using optimistic locking (w/@Version) you would have an issue because these entities would not contain the Version field, or the Id field for that matter and violate the ACID principle? Or am I missing something? Thnx.
    Yes you're right these entities are detached, though I was trying to show we no longer need DTO's to share custom data between tiers.
    Bogdan Marian said…
    A JPA entity is not a DTO as it must have an id property, while a DTO has no such constraint. On the other hand, you can use the SELECT new package.DTOClass(...) FROM ... construct to hydrate DTOs.
    In order to avoid manually managing the DTO classes, you could use an annotation processor which will read the annotations from your JPA entity class and generate the appropriate DTO classes. Or, if you do not want to pollute your JPA entities with DTO details, create classes inheriting from them, override their getters and setters and apply the DTO related annotations there. There is a framework, QueryDSL (http://source.mysema.com/display/querydsl/Querydsl) which generates strong type criteria from the JPA entities and they are using annotation processors...
    yes we have been doing this, writing| generating nice DTO classes, why would I wanna write more code or introduce new classes when i can really reuse my Entities, its just because they are called Entities i can't reuse them as DTO's ?
    Anonymous said…
    Reuse of the entity class as a DTO seems messy. The public API of the class (including annotations on public methods) no longer clearly defines the purpose of the contract it is presenting. The class will end up with methods that are only relevant when the class is being used as a DTO and some methods that will only be relavent when the class is being used as an entity. Concerns will not be cleanly separated and things will be more tightly coupled. To me that is a more important design consideration then trying to save on the number of class files created.
    This comment has been removed by the author.
    One of the big advantage of Entity is it can be detached and send across the network, why would I need another class i.e. DTO to do that ?
    Anonymous said…
    There are many scenarios.

    I.e.: you are with a "fat" client in Swing or GWT, you are sending to the client (outside the server control) some fields with sensitive data (please, dont' assume that it's enough tto show hide them in the forms or windows - it's extremely easy to hack a RIA client or the browser to inspect and/or manipulate them)
    Anonymous said…
    DTO is used when you want to transfer many data across the network to avoid many small call due to expensive network data transfer. If the application does not suffer big impact, serializing entity directly over the network makes your programming model much simpler. It embraces the OO practice seamlessly over the network boundary.

    See the article

    http://weblogs.java.net/blog/meeraj/archive/2004/07/rich_domain_mod.html
    Noman Sadiq said…
    using JPA entity as DTO i think we tightly couple the module of application
    Unknown said…
    Which is a good thing. Loose coupling of entities is a big productivity killer.

    Popular posts from this blog

    Access multiple Databases in JPA

    According to JPA specification we can define multiple "persistence-unit" elements (i.e. like below) in persistence.xml file and can easily refer them inside Dao layers as this. public class PolarDaoImpl {     @PersistenceContext(unitName="PolarPU")     protected EntityManager entityManager; -- } public class BearDaoImpl {     @PersistenceContext(unitName="BearPU")     protected EntityManager entityManager; -- } Checkout sample persistence.xml <?xml version="1.0" encoding="UTF-8"?> <persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">     <!-- Database 1 -->     <persistence-unit name="PolarPU" transaction-type="RESOURCE_LOCAL">         <

    JPA 2 new feature @ElementCollection explained

    @ElementCollection is new annotation introduced in JPA 2.0, This will help us get rid of One-Many and Many-One shitty syntax. Example 1: Stores list of Strings in an Entity @Entity public class Users implements Serializable {     private static final long serialVersionUID = 1L;     @Id     @GeneratedValue(strategy = GenerationType.AUTO)     private Long id;     @ElementCollection     private List<String> certifications = new ArrayList <String> ();     public Long getId() {         return id;     }     public void setId(Long id) {         this.id = id;     }     public List <String> getCertifications() {         return certifications;     }     public void setCertifications(List <String> certifications) {         this.certifications = certifications;     } .. }         Users u = new Users();         u.getCertifications().add("Sun Certified Java Programmer");         em.persist(u); Generated Tables    Users    Co