Single-ended association proxies With Fetching Strategies by R4R Team

In the Fetching Strategies Lazy fetching for collections is implemented using Hibernate's own implementation of persistent collections. The  different mechanism is needed for lazy behavior in single-ended associations. In this method the target entity of the association must be proxied. But Hibernate implements lazy initializing proxies for persistent objects using runtime bytecode enhancement which is accessed via the CGLIB library.

In the starting of Hibernate it generates proxies by default for all persistent classes and uses them to enable lazy fetching of many-to-one and one-to-one associations. The mapping file may declare an interface to use as the proxy interface for that class, with the proxy attribute. In the Hibernate, By default Hibernate uses a subclass of the class. The proxied class must implement a default constructor with at least package visibility. This constructor is recommended for all persistent classes. There are potential problems to note when extending this approach to polymorphic classes.

For example:

<class name="Cater" proxy="Cater">
    ......
    <subclass name="DomesticCater">
        .....
    </subclass>
</class>

In the first of all instances of Cater will never be castable to DomesticCater, even if the underlying instance is an instance of DomesticCater:

Cater cater = (Cater) session.load(Cater.class, id);  // instantiate a proxy (does not hit the db)
if ( cater.isDomesticCater() ) {                  // hit the db to initialize the proxy
    DomesticCater dc = (DomesticCater) cater;       // Error!
    ....
}

And the another step comes on the second level, it is possible to break proxy ==:

Cater cater = (Cater) session.load(Cater.class, id);            // instantiate a Cat proxy
DomesticCat dc = (DomesticCat) session.load(DomesticCat.class, id);  // acquire new DomesticCat proxy!
System.out.println(cater==dc);                            // false

To understand this situation is not quite as bad as it looks. Whenever we now have two references to different proxy objects, the underlying instance will still be the same object:

cater.setWeight(11.0);  // hit the db to initialize the proxy
System.out.println( dc.getWeight() );  // 11.0

And the Third, cannot use a CGLIB proxy for a final class or a class with any final methods. And in the finally if persistent object acquires any resources upon instantiation (in initializers or default constructor), then those resources will also be acquired by the proxy. The proxy class is an actual subclass of the persistent class. These problems are all due to fundamental limitations in Java's single inheritance model. To avoid these problems your persistent classes must each implement an interface that declares its business methods. You should specify these interfaces in the mapping file where CaterImpl implements the interface Cater and DomesticCaterImpl implements the interface DomesticCat. 

For example:

<class name="CaterImpl" proxy="Cater">
    ......
    <subclass name="DomesticCaterImpl" proxy="DomesticCater">
        .....
    </subclass>
</class>

Then proxies for instances of Cater and DomesticCater can be returned by load() or iterate().

Cater cater = (Cater) session.load(CatImpl.class, catid);
Iterator iter = session.createQuery("from CatImpl as cat where cat.name='fritz'").iterate();
Cater fritz = (Cater) iter.next();

We have to remember that list() does not usually return proxies. Relationships are also lazily initialized. This means you must declare any properties to be of type Cater, not CatImpl.

Certain operations do not require proxy initialization:

1. equals(): if the persistent class does not override equals()
2. hashCode(): if the persistent class does not override hashCode()
3. The identifier getter method

Hibernate will detect persistent classes that override equals() or hashCode().

By choosing lazy="no-proxy" instead of the default lazy="proxy", you can avoid problems associated with typecasting. However, buildtime bytecode instrumentation is required, and all operations will result in immediate proxy initialization.
Leave a Comment:
Search
Categories
R4R Team
R4Rin Top Tutorials are Core Java,Hibernate ,Spring,Sturts.The content on R4R.in website is done by expert team not only with the help of books but along with the strong professional knowledge in all context like coding,designing, marketing,etc!