14
\$\begingroup\$

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?

\$\endgroup\$
15
\$\begingroup\$

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 library versions in the sample code are now very out of date as it is many years later but the design and implementation approaches described in detail are IMHO timeless.

There is a use for some DTOs 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 DTO which represents a row on the screen and use JPA select new syntax as described in this answer to join across entities which is translated into a database join query that is efficiently loaded into the DTO object.

We should note that the DTO described above models the search result screen not the business domain. That's an important distinction. The DTO 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 DTOs to an absolute minimum. Screens which work closely with a few entities in detail should work with root entities that control other 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 spread out across UI code. Have the service classes that query and load root entities then call method on the root entities that contain the business logic. That way different service class methods that work with the same root entities won't duplicate logic as the logic will be within the entities that are shared.

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.

Edit I have created a sample project on GitHub that demonstrates some of the ideas in this answer.

\$\endgroup\$
  • \$\begingroup\$ 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 \$\endgroup\$ – simbo1905 Jun 13 '15 at 21:05
  • 2
    \$\begingroup\$ 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. \$\endgroup\$ – simbo1905 Jun 14 '15 at 11:05
  • \$\begingroup\$ i wrote a series of blog posts about JPA and DDD over at simbo1905.wordpress.com/2016/07/18/… \$\endgroup\$ – simbo1905 May 16 '17 at 9:33
  • \$\begingroup\$ I was reading about clean architecture where uncle bob told that response and request object should have not behaviour at all and should be a plain object, I think this summarises things correctly. \$\endgroup\$ – CodeYogi Oct 1 '17 at 20:47
  • \$\begingroup\$ A request and a response are closely aligned to http so I don't think that we can extrapolate that scenario modeling business problems. Technical domains don't seem to be very well modelled using OO \$\endgroup\$ – simbo1905 Oct 5 '17 at 18:17

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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