Question

Is there any truly practical way to avoid using DTOs, when passing data through Hibernate-backed transactional service methods? In other words, are DTOs the only non-hacky solution to avoiding lazy initialization problems?

I think the two popular alternatives to DTOs and the reasons I don't really like them are:

  1. Open Session in View pattern. This I don't like as I would like to keep the service methods truly transactional (i.e. the Hibernate session is committed and closed when the method exits). This is mainly because I would like to not have to worry about transactions if I for example need to publish the service as a web service later on.

  2. Passing domain/business objects through service methods instead of DTOs and eager fetching the needed attributes/properties. This is somewhat better. However in a non-trivial domain object hierarchy with complicated entity relations the eager fetching has to stop somewhere. And when it does, I can't see how this wouldn't very quickly turn into a complete hackaton replacing entities with referencing ids all over the place.

Am I missing something or are DTOs in fact the only solid approach from maintainability's point of view?

Was it helpful?

Solution

The only way to really use entities end to end is to use something a little bit more sophisticated than OpenSessionInView. In my experience you're going to have to manage the hibernate session manually at the application level. OpenSessionInView will only give you the same session for one request. After that you'll need to be constantly reattaching to the current session. Take a look at Seam and conversations, or implement your own Hibernate Session management. We currently manually manage our sessions based on when a wizard starts and ends and use Spring AOP to attach sessions to the right threads just in time(Sessions are not thread safe, not a good mix with AJAX)

WebServices on the other hand most certainly are going to need some form of DTO. I don't see a way around that. Entities may look like POJOs but aren't really, serializing them can range from difficult to nearly impossible. Just create DTOs that fit with the goal of the service method and be done with it.

Personally I don't think the DTO pattern is terrible, if you're just making a website it's feasible to go end to end with entities and it may even buy you some performance but if you'd like a more flexible architecture, stick with DTOs.

OTHER TIPS

Repositories, Services, and Controllers should be the places dealing with your application core (Hibernate Session can certainly be used as the entirety of your repository layer, if you like).

Views are not supposed to be dealing with your application core, the domain model. They should not be dealing with the live objects, but with a non-live, tailored representation of the live objects. Views are supposed to be handed just the data they need, in the particular format they need it. You should build DTOs for your views. This pattern is also known as View Model, to contrast with Domain Model.

To make your life easier, there may be libraries or frameworks which can auto-map from your domain model objects to your view model objects, and back. In .NET, there is an open source framework called AutoMapper currently in development; I'm not sure what there is for Java.

If you relax your requirement to close the session, you can still use open session in view and just commit everything in your service transactions. The session will still be available to lazy fetch but all your transactions will be complete. But if you're going to switch to a web service, then you would need to eager load all of your entities anyway. DTOs just force you to consciously eager load and prevent accidental laziness.

So, bottom line, if you're careful, you can skip the DTOs in both environments, but I would probably stick with open session in view and worry about web services when they actually become a requirement.

I love the idea of DTOs, but I always felt that they weren't very well accepted or liked by other developers since implementing that approach properly all the way down to the database usually requires a lot of effort. This is why I created Blaze-Persistence Entity Views which allow you to model DTOs as interfaces that map to the JPA entity model in an efficient manner. You can apply an entity view to a query and the query will be adapted in a way that it will only fetch the actually required state, rather than all the state and map that in Java.

By using entity views you don't need the open session in view anti-pattern, because the desired structure is loaded eagerly. Since there are no entity objects involved, there will also be no lazy loading issues.

Since the entity model often is so similar to the DTO model in early development stages, I often see developers just skip creating a separate DTO model as they try to avoid the hassle. As soon as cross cutting concerns like auditing, statistics or denormalizations land in the entity model or the amount of data in the entity model grows a lot bigger than what you actually need for use cases of the entity, developers run into problems.

You will for sure like a blog post on that matter I wrote some time ago.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top