Code Review Stack Exchange is a question and answer site for peer programmer code reviews. It's 100% free, no registration required.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I am quite new in web application back-end development and I have an architectural question. I have defined Hibernate entities in my application and I want to send them to client. Currently for each entity I have defined data transfer object, that is almost the same as entity. Is it good practice to create DTO for each entity? Or should I send Hibernate entity for it? I find it quite redundant to make another class that is the same, but on the other hand - it is for different purpose. Here is the example of what I mean:

User user = userPreferenceService.getUser(userLogin.getEmail(), userLogin.getPassword());
        UserDto userDto = new UserDto();
        userDto.setId(user.getId());
        userDto.setName(user.getName());
        userDto.setSurname(user.getSurname());
        userDto.setEmail(user.getEmail());
        userDto.setPhone(user.getPhone());
        userDto.setCountryId(user.getCountry().getId());

Here the User object is entity in database and userDto is the one that I send to the client. They contain the same info. Should I do it that way? Or should I just send the User?

share|improve this question
1  
Please state only the code's purpose in the title. Specific questions are only for the post body. – Jamal Jun 13 '15 at 15:57
up vote 4 down vote accepted

Short answer:

Don't create a DTO per entity. Use the exposed domain model pattern instead.

Very long answer:

When you say "send to the client," as it is a webapp, this really means render to the browser (or mobile app) in the servlet tier. In which case, it's typically your own teams code and there is little or no value to copying entities into DTOs. There is overhead to copying into DTOs which is a reason not to do it. The exposed domain model pattern considers copying to DTOs as an anti-pattern. The POJOs In Action book by Chris Richardson is old, but still excellent and covers the exposed domain model pattern. The sample code is very out of date but the design and implementation approaches described in detail are IMHO timeless.

There is a use for "Value Objects" when writing code with entities. The canonical use is a search results screen which is, say, a grid with many columns which come from many entities. An example would be a summary of customer orders. That would have each row be taken from entities such as customers, addresses, products, orders etc. In such a case it is wasteful and slow to load all the entities to memory to render them in the flat search results screen. In that case you can create a value object which represents a row on the screen and use JPA select new syntax as described in this answer to join across entities and pull specific fields off them into a value object. JPA maps the query result set directly into the value object. Note that a value object can be called a DTO but I avoid that name to distinguish careful use of few value objects from the old "copy all entities to value objects" approach.

We should note that the value object described above models the search result screen not the business domain. That's an important distinction. The value object may change completely if the screen changes or be deleted if the screen is deleted. What you really want to do is model the business problem as entities and mature that model carefully and keep value objects to a minimum. Screens which work closely with a few entities in detail should work with those entities directly.

I would strongly recommend putting as much business logic as you can into entities as public methods, and try to have all the code which creates and connects entities default/package protected and as hidden as possible. When you do that you get better OO design. An example would be the Order entity has a method getOrderItems to list the OrderItem entities but a protected setOrderItems method. The client would invoke a public method on the Order called addItem which took all the fields needed to construct the OrderItem entry internally using a protected constructor and add it into its list of order items. The Order becomes a "root/aggregate entity" which manages the relations and business logic of subordinate entities. This is a more naturally OO design than having "behaviourless" DTOs with the business logic entirely in service classes; or worse in spread out across client code.

If your entities are dumb with no logic then they are just DTOs which is the Anemic Domain Model anti-pattern. If your entities are strong with business logic then copying the entities to DTOs would make no way for a client to use that business logic.

Given all this advice, it may seem strange that so much j2ee code still copies all entities into DTOs. One reason for this may be that the original "Core J2EE Design Patterns" book published by Sun had DTOs as a core pattern. That was required reading for a decade at the turn of the century. It's still around on the Oracle site, but that version makes it clear that it's to abstract over JDBC or LDAP and clearly JPA is the modern and standards compliant way of abstracting over a database; therefore, that page is obsolete.

share|improve this answer
    
I would advise not using raw hibernate use its JPA version. Also use Spring to create the general CRUD code so you can focus on the query logic only. I wrote a demo app which uses an zk Ajax frontend with spring and hibernate JPA you might want to checkout at github.com/simbo1905/ZkToDo2 – simbo1905 Jun 13 '15 at 21:05
    
An interesting article about going "beyond JPA" which points out some weaknesses is covered by a great series of articles by John Sullivan at scabl.blogspot.co.uk/2015/03/aeddd-5.html He has some good patterns and recommendations when using JPA which I would recommend such as aggregate roots. – simbo1905 Jun 14 '15 at 11:05

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.