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
Sample Load Test Results for loading 50K Employee entities using Hibernate JPA.
General Way --> 4621 ms
Constructor Query --> 309 ms
Contructor Expression Rules
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.
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
- No separate DTO classes are required
- Re-Use same Entities for exchanging data in any combinations
- You can also create DTO classes and load data but why would you wanna do that when we can reuse entity classes
- No need to write converters (i.e. DTO-Assembler) for copying data from entities to dtos and vise-versa
- 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
- Entity or non-Entity class can be used to load coarse-grained data
- Class should have a matching constructor defined with correct argument types
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
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...
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)
See the article
http://weblogs.java.net/blog/meeraj/archive/2004/07/rich_domain_mod.html