One of the new features in 4.1 will be the addition of an actual API for loading entities by natural id. Yes previous versions had the ability to do natural id loading leveraging criteria queries, but that approach was very limiting. The new API will allow caching at both the Session and SessionFactory level in addition to providing a consistent API. The new approach has been made available for identifier based loading as well, again for consistency.
New methods have been added to the Session contract as a starting point (see source or javadoc for additional discussion):
public IdentifierLoadAccess byId(String entityName); public IdentifierLoadAccess byId(Class entityClass); public NaturalIdLoadAccess byNaturalId(String entityName); public NaturalIdLoadAccess byNaturalId(Class entityClass); public SimpleNaturalIdLoadAccess bySimpleNaturalId(String entityName); public SimpleNaturalIdLoadAccess bySimpleNaturalId(Class entityClass);
All of the load access delegates have methods for getting an entity reference (getReference) and loading an entity (load). The distinction is similar to the older get and load methods on Session; getReference on load access delegates equate to Session.load and load on load access delegates equate to Session.get
public interface IdentifierLoadAccess {
public IdentifierLoadAccess with(LockOptions lockOptions);
public Object getReference(Serializable id);
public Object load(Serializable id);
}
public interface NaturalIdLoadAccess {
public NaturalIdLoadAccess with(LockOptions lockOptions);
public NaturalIdLoadAccess using(String attributeName, Object value);
public Object getReference();
public Object load();
}
public interface SimpleNaturalIdLoadAccess {
public SimpleNaturalIdLoadAccess with(LockOptions lockOptions);
public Object getReference(Object naturalIdValue);
public Object load(Object naturalIdValue);
}
So let's say we have an entity defining a natural id:
@Entity
@Table(name="T_USER")
public class User {
@Id
private Long id;
@NaturalId
private String username;
...
}
we can load instances of that class by natural id as follows:
session.byNaturalId( User.class ).using( "username", "steve" ).load();
That actually makes sure we get back an initialized instance, just like Session.get does. If we just want a possibly uninitialized reference we would use this instead:
session.byNaturalId( User.class ).using( "username", "steve" ).getReference();
Since the natural id here is simple (just a single attribute) we can make this even easier:
session.bySimpleNaturalId( User.class ).load( "steve" );
If I remember correctly, Hibernate 4 need at least Java 1.5. Why is this new API not using generics ? I understant the byId(String entityName) can't know the real type, it could still return a IdentifierLoadAccess<Object>
I thought too that the hibernate 4.0 api would have evolved to use more generics but methods like get/load/merge haven't been parameterized.
The issue is that Hibernate has a feature that causes problems with parameterizing those sigs, @Proxy. Specifically if you specify @Proxy.proxyClass to name an interface Hibernate uses that interface to define proxies used for lazy loading, not the class. The proxies are only castable to the interface (hierarchy), not the class (hierarchy). There is a discussion on the dev mailing list if you care to join in.
How do I arrange that the new byNaturalId loading be L2 cached? (With old criteria approach, setCacheable/setCacheRegion could be used.)
Also is the new approach intelligent enough to know not to perform an (expensive) dirty check/session flush unnecessarily?
Hi Jeremy,
Hi Jeremy,
How do I arrange that the new byNaturalId loading be L2 cached?
Use @NaturalIdCache annotation
Also is the new approach intelligent enough to know not to perform an (expensive) dirty check/session flush unnecessarily?
Currently it is not very intelligent in that sense, for this purpose I opened Hibernate JIRA issue Please take a look at it and, if you like this as enhancement, please vote for it.
Thanks Guenther (although rather belatedly). The JIRA issue addresses my concerns exactly.