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.
    Intesar said…
    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...
    Intesar said…
    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.
    Intesar said…
    This comment has been removed by the author.
    Intesar said…
    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
    Damien Biggs said…
    Which is a good thing. Loose coupling of entities is a big productivity killer.

    Popular posts from this blog

    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
    Column --> ID
        Row             1

    Users_CERTIFICATIONS

    Validating CSV Files

    What is CsvValidator ?
      A Java framework which validates any CSV files something similar to XML validation using XSD.

    Why should I use this ?
      You don't have to use this and in fact its easy to write something your own and also checkout its source code for reference.

    Why did I write this ?
      Some of our projects integrate with third party application which exchanges information in CSV files so I thought of writing a generic validator which can be hooked in multiple projects or can be used by QA for integration testing.

    What is the license clause ?
    GNU GPL v2

    Are there any JUnit test cases for me checkout ?
     Yes, source

    How to integrate in my existing project ?

    Just add the Jar which can be downloaded from here CsvValidator.jar and you are good.

    Instantiate CsvValidator constructor which takes these 3 arguements

             // filename is the the file to be validated and here is a sample         // list - defines all the fields in the above csv file ( a field has index, type, isOptional, rege…

    ArrayList vs LinkedList vs HashSet Performance Comparision

    ConclusionsInserting & Reading sequentially from Collection prefer LinkedList/ArrayListInserting & Reading/Deleting by Search/equals from Collection prefer HashSetInserting, ArrayList & LinkedList performs best while HashSet takes double the timeReading, HashSet performs best while ArrayList & LinkedList are marginally lessDeleting, HashSet performs 10 times better than ArrayList & ArrayList performs 4 times better than LinkedList. LinkedList is slow because of sequencial search Bottom line : unless you are not going to iterate using for(Integer i : list ) then prefer HashSet
    Inserting/Reading/Deleting integer's from zero till countJDK7Collectionactioncounttime msArrayListInsert1000/1LinkedListInsert1000/1HashSetInsert1000/1ArrayListInsert100005LinkedListInsert100004HashSetInsert100007ArrayListInsert10000011LinkedListInsert10000011HashSetInsert10000021ArrayListGet/Read1000LinkedListGet/Read1000HashSetGet/Read1000ArrayListGet/Read100004LinkedListGet/Read100003Has…