Red Hat
Jan 24, 2012
by Steve Ebersole

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:

public class User {
    private Long id;
    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" );
Original Post