Sunday, July 27, 2014

Concept of owning entity in EJB and Hibernate

The owning entity concept confuses many of the early adopters of Hibernate and JPA aka Entity beans in EJB3.0. We often confuse with the notion that we have to tell which of the entity is the owner.
Before we delve deeper into this question let's understand why this whole notion of ownership comes into picture. The persistence provider gives us a lot of goodies in terms of saving us from handling low level sql handling and coding in terms of rows and columns. Even we get into this let's move one more level above and understand that ORM framework provide us a way to think in terms of objects. The thinking model with which Java programmers are comfortable with. OOAD is a very powerful notion as it helps us in
thinking in terms of real world. ATM, Customer, Item, Bid, Auction become reusable notions in software world. However to provide that notion to Software world, ORM does a lot of dirty work (dirty checking !!!) for us.
The most important feature that an ORM provides is transparent persistence. However to provide that the ORM framework does a lot of work under the hood. For example Hibernate keeps a copy of original entity from the database and before flushing does a dirty checking (Ahh I have heard this before). It will compare the values with the working entity and in case of changes will generate the SQL.
Now let's take a concrete example of User and Address both having one to one and bidirectional relationship. That means we have Address reference from User and User reference from Address. (It does not matter whether we put the Fk on User side or Address side..Actually it matters with the kind of Sql the ORM tool will generate to materialize the relationship). Let's say for this example the foreign key is on User side.
Now as a good Java Programmer whenever we have to change the address of a user we will do following:'
user.setAddress(add);
add.setUser(user);


If you are an EJB2.1 guy than please look into the EJB3.0. It's more work but with very simple programming model and high portability.
Now ORM frameworks will do the dirty checking and it will figure out that User and Address both has changed so it will issue a call to update both address and user.
For User it will be
update user set address_id =?
and for address it will be similar call. So for almost all bidirectional relationship ORM framework will generate double update calls. This is a performance bottleneck Dr. Watson.
So what we do. We as a programmer tell that which side is the owning, which means for the relationship to take into effect only one side of the dirty checking for the relationship needs to be done. If we put inverse or mapped by on address than for the relationship to take effect we need to do
user.setAddress(add);
If we just do add.setUser(add) the change will not be propagated into the database. However as a good programmer we should wire both side of the relationship.
Now let's think for a moment. Can ORM framework cannot handle this is some way? Think over it, it can be done but will be a lot of bookkeeping and will complicate the frameworks a lot complex. Food for thought!!!

More write-ups on Hibernate

3 comments:

  1. "user.setAddress(add);
    add.setUser(add);"
    I think you mean :
    "user.setAddress(add);
    add.setUser(user);"

    ReplyDelete