what is a good pattern for converting between hibernate entities and data transfer objects?

19,953

Solution 1

Should I just ignore the DTO pattern and pass entities around?

My preference is usually "yes". I don't like the idea of parallel hierarchies created just for the sake of architectural or layer purity.

The original reason for the DTO pattern was excessive chattiness in EJB 1.0 and 2.0 apps when passing entity EJBs to the view tier. The solution was to put the entity bean state into a DTO.

Another reason that's usually given for creating DTOs is to prohibit modification by the view layer. DTOs are immutable objects in that case, with no behavior. They do nothing but ferry data to the view layer.

I would argue that DTO is a Core J2EE pattern that's become an anti-pattern.

I realize that some people would disagree. I'm simply offering my opinion. It's not the only way to do it, nor necessarily the "right" way. It's my preference.

Solution 2

There needs to be a contrarian view amongst all the jolly kicking of the DTO.

tl;dr - It is sometimes still useful.

The advantage of the DTO is that you don't have to add a zillion annotations to your domain classes.

You start with @Entity. Not so bad. But then you need JAXB so you add @XMLElement etc - and then you need JSON so you add things like @JsonManagedReference for Jackson to do the right thing with relationships then you add etc. etc. etc. ad infinitum.

Pretty soon your POJO ain't so plain any more. Read about "domain driven design" sometime.

In addition you can "filter" some properties that you don't want the view to know about.

Solution 3

We should not forget that entity objects are not easy to handle when they are in managed state. This makes their passing to GUI forms problematic. To be more precise, child objects are handled eagerly. This cannot be done out of session, cousing exceptions. So, they either have to be evicted (detached) from the entity manager of they have to be converted to appropriate DTOs. Unless of cource there is a pattern, which I am not aware of, that I would be very glad to know.

Solution 4

For quickly create a "look-alike" DTO, without a bunch of duplicate get/set code, you can use BeanUtils.copyProperties. That function help you quickly copy the data from DAO to DTO class. Just remember that there are more than one common libraries support BeanUtils.copyProperties, but their syntax are not the same.

Solution 5

I know this is an old question, but thought I would add an answer offering a framework to help in case someone else is tackling this problem.

Our project has JAXB annotated POJOs that are separate from the JPA annotated POJOs. Our team was debating how best to move data between the two objects (actually data structures).

Here is an option for people to consider:

We found and are experimenting with Dozer which handles (1) same name, (2) XML mapping and (3) custom conversions as ways to copy data between two POJOs.

It has been very easy to use so far.

Share:
19,953
D Parsin
Author by

D Parsin

Updated on June 03, 2022

Comments

  • D Parsin
    D Parsin about 2 years

    I have had similar questions and concerns as to how to convert between Hibernate entities and data transfer objects to be returned by a web service as are discussed in this question:

    Is using data transfer objects in ejb3 considered best practice

    One of the factors mentioned here is that if the domain model changes, a set of DTOs will protect consumers in the case of a web service.

    Even though it seems like it will add a substantial amount of code to my project, this reasoning seems sound.

    Is there a good design pattern that I can use to convert a Hibernate entity (which implements an interface) to a DTO that implements the same interface?

    So assuming both of the following implement 'Book', I would need to convert a BookEntity.class to a BookDTO.class so that I can let JAXB serialize and return.

    Again, this whole prospect seems dubious to me, but if there are good patterns out there for helping to deal with this conversion, I would love to get some insight.

    Is there perhaps some interesting way to convert via reflection? Or a 'builder' pattern that I'm not thinking of?

    Should I just ignore the DTO pattern and pass entities around?

  • Tony Ennis
    Tony Ennis over 13 years
    I also generally decline to implement DTOs - not enough bang for the buck. I do implement DAO classes and use Hibernate's tools to generate/reverse-engineer model classes from the database. That's good stuff.
  • D Parsin
    D Parsin over 13 years
    My original hope by posting the question was that there was some interesting or insightful way to convert between entity's and dto's that share an interface that I hadn't encountered before. But I have been convinced that I shouldn't really bother adding that complexity to my services just to keep a separation between layers. Thanks!
  • avanderw
    avanderw almost 12 years
    I think if you have full control over the full stack then yes this is valid. However, having two or more UI's using your service and not separating the layers is dangerous. If you go and make a change to the object you are sending them, it WILL break their calls to your service. You cannot expect all implementors of your service to update their code as you change your layer. Thus the core reason for layer separation, but every context is different. You need to understand that first.
  • duffymo
    duffymo almost 12 years
    Yes, I can expect it. I do understand it. When I write a service I negotiate a contract with my first clients. Subsequent ones have to adhere to it. If it changes, I either have to ask everyone to change or provide a mechanism to allow for a transition period. That's it. And I don't see what DTO does to help that.
  • Hoàng Long
    Hoàng Long almost 9 years
    @duffymo: the DTO objects will let you change interface much more easily. Of course, if your number of interfaces and related applications are small, you can manage it and there's not enough reason to change. However, if you have many interfaces... good luck, your transition would take a lot of time.
  • Hoàng Long
    Hoàng Long almost 9 years
    Another reason of NOT passing Hibernate objects around (like in the question) is that you can simplify your objects with only the properties you need. It will help save some bandwidth, and in some cases reduce the effort of parsing your request/response. Of course, not having to transferring Hibernate properties around help too.