This seems like such a basic issue that I would feel foolish bringing it up, except that I've researched it on and off over the past few years, reading many blog posts and forum threads, without drawing any firm conclusions. That is, if there is a general consensus among the Hibernate community and/or the Hibernate developers, I don't know what it is. That may be due to a failure of my research, or it may be because no consensus exists, but either way I thought it would be productive to just ask directly as the amount of Hibernate code in my life is starting to increase.
I am, of course, coming originally from a traditional, JDBC statement-based mindset. However, I'd like to think that I have a good grasp of Hibernate and the notion of state management in general and am just struggling with the practical implications.
Let's take the basic, common situation of a web application: I want to populate a form with data backed by objects, submit the form, bind form values to the objects, validate the form values on the server-side (this may require making a uniqueness check against the database and/or persisting some auditing information), and persist the form values only if the data is valid.
Here are the options as I see them, along with their drawbacks:
Detached Entity Objects in the View
Pass the entity objects out of the scope of the Hibernate session before using them. We can modify these objects freely, and they will never be persisted unless we explicitly pass them to a "saveOrUpdate" method, or the like. Unfortunately, we don't get lazy loading (at least not without ugly workarounds) or dirty checking (this can be mitigated via "select-before-update," but at the cost of extra selects). In essence, we take something very close to a traditional, statement-based approach, and don't take full advantage of what Hibernate has to offer.
Open Session in View With Entity Objects in the View
In this case, we are binding directly from the form to "live" entity objects. We're using Hibernate to the fullest extent, making the best use of lazy loading and dirty checking. However, it is possible that we will bind invalid values to our entities, and that those values will be proactively persisted/state-managed by Hibernate before we have a chance to validate them. (Let's say the object enters the scope of a transaction while we perform some validation against the database, or persist some audit information about the form submission attempt.) This may be avoidable through careful coding, but it strikes me as risky (it'd be very easy for a developer to innocently end up corrupting some data in some rare, easily-forgettable situation) and a bit intrusive, separation of concerns-wise (controllers would have to be coded with Hibernate's behavior in mind).
Data Transfer Objects (DTOs) in the View
Some would say that you should never modify an entity unless you really mean it. That entities are not representations of or copies of the data, but essentially are the data.
I assume that the alternative is to copy the data that you want to "play around with" into some intermediate object, and only get and modify the entity objects when you are actually ready to persist. Basically, treat the entities as you would treat the database itself. This approach has some appeal, as it is very "safe" and gives us a very easy-to-remember rule with clear separation of concerns.
However, we then end up with a potentially large number of similar (redundant?) objects, and a whole lot of copying/mapping of values. Spring binding and Hibernate mapping have largely freed us from that sort of thing, and it feels like a step backwards to introduce another layer of "entityObject.setValue(dtoObject.getValue())" business, or to develop a new set of annotations to handle it "automagically," or whatever.
Some Other Option(s) I Haven't Considered
Of course, I may be missing some other approach entirely. Or perhaps there is some tool or technique that would mitigate the drawbacks I mention above. I may just be thinking about things the wrong way. Any helpful advice or links to useful references would be appreciated!
|