Hi,
Here's a proposed solution to the limitations of the OneToOne discussed in the following Hibernate article:
http://www.hibernate.org/162.html#A3.
How about introducing a generic wrapper class that would be used when we want a lazy loading OneToOne? For instance:
Code:
@Entity
public EntityA {
private OneToOneWrapper<EntityB> entityB;
@OneToOne(fetch=LAZY, optional=true)
public OneToOneWrapper<EntityB> getEntityB() {
return this.entityB;
}
private void setEntityB(OneToOneWrapper<EntityB> entityB) {
this.entityB = entityB;
}
}
The contract of such a relationship would be that the getter NEVER returns null. Instead, the wrapper class would contain a "isNull" method that would try to lazy load the entity that it wraps and then tell us if something was found or not.
Code:
EntityA a = em.find(EntityA.class, thePkValue);
if (a.getEntityB().isNull()) { // the call to isNull would trigger a query if the entity is not already loaded
// do something...
}
To read/write the value, we would use a getValue/setValue defined on the wrapper class:
Code:
EntityA a = em.find(EntityA.class, thePkValue);
EntityB b = a.getEntityB().getValue(); // with the use of generics, no need for casting
...
EntityB newB = new EntityB();
a.getEntityB().setValue(newB);
This is why the setter (setEntityB) is private. We always go through the wrapper class to get/set the value of the relationship. Just like the "isNull" method, the "getValue" and "setValue" method of the wrapper would trigger a query when needed.
The limitations that exist right now is because we have the entity itself as the target of the relationship. If we replace that with a wrapper class that has a clear contract, I think it would solve the problem. What do you guys think?