diff --git a/hibernate-core/src/main/java/org/hibernate/IdentifierLoadAccess.java b/hibernate-core/src/main/java/org/hibernate/IdentifierLoadAccess.java new file mode 100644 index 0000000000..26fa2260d4 --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/IdentifierLoadAccess.java @@ -0,0 +1,56 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2008-2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate; + +import java.io.Serializable; + +/** + * Loads an entity by its primary identifier + * + * @author Eric Dalquist + * @version $Revision$ + */ +public interface IdentifierLoadAccess { + /** + * Set the {@link LockOptions} to use when retrieving the entity. + */ + public IdentifierLoadAccess with(LockOptions lockOptions); + + /** + * Same behavior as {@link Session#load(Class, java.io.Serializable)} + * + * @param id The primary key of the entity + * @return The entity + * @throws HibernateException if the entity does not exist + */ + public T getReference(Serializable id); + + /** + * Same behavior as {@link Session#get(Class, java.io.Serializable)} + * + * @param id The primary key of the entity + * @return The entity or null if it does not exist + */ + public T load(Serializable id); +} diff --git a/hibernate-core/src/main/java/org/hibernate/NaturalIdLoadAccess.java b/hibernate-core/src/main/java/org/hibernate/NaturalIdLoadAccess.java new file mode 100644 index 0000000000..4507a8e50d --- /dev/null +++ b/hibernate-core/src/main/java/org/hibernate/NaturalIdLoadAccess.java @@ -0,0 +1,63 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2008-2011, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate; + + +/** + * Loads an entity by its natural identifier + * + * @author Eric Dalquist + * @version $Revision$ + * @see org.hibernate.annotations.NaturalId + */ +public interface NaturalIdLoadAccess { + /** + * Set the {@link LockOptions} to use when retrieving the entity. + */ + public NaturalIdLoadAccess with(LockOptions lockOptions); + + /** + * Add a NaturalId attribute value. + * + * @param attributeName The entity attribute name that is marked as a NaturalId + * @param value The value of the attribute + */ + public NaturalIdLoadAccess using(String attributeName, Object value); + + /** + * Same behavior as {@link Session#load(Class, java.io.Serializable)} + * + * @return The entity + * @throws HibernateException if the entity does not exist + */ + public T getReference(); + + /** + * Same behavior as {@link Session#get(Class, java.io.Serializable)} + * + * @return The entity or null if it does not exist + */ + public T load(); + +} diff --git a/hibernate-core/src/main/java/org/hibernate/Session.java b/hibernate-core/src/main/java/org/hibernate/Session.java index 70723fce59..b4eb38d5f5 100644 --- a/hibernate-core/src/main/java/org/hibernate/Session.java +++ b/hibernate-core/src/main/java/org/hibernate/Session.java @@ -770,6 +770,42 @@ public interface Session extends SharedSessionContract { * @throws HibernateException */ public String getEntityName(Object object) throws HibernateException; + + /** + * Create an {@link IdentifierLoadAccess} instance to retrieve the specified entity by + * primary key. + * + * @param entityName The name of the entity that will be retrieved + * @throws HibernateException If the specified entity name is not found + */ + public IdentifierLoadAccess byId(String entityName); + + /** + * Create an {@link IdentifierLoadAccess} instance to retrieve the specified entity by + * primary key. + * + * @param entityClass The type of the entity that will be retrieved + * @throws HibernateException If the specified Class is not an entity + */ + public IdentifierLoadAccess byId(Class entityClass); + + /** + * Create an {@link NaturalIdLoadAccess} instance to retrieve the specified entity by + * its natural id. + * + * @param entityName The name of the entity that will be retrieved + * @throws HibernateException If the specified entity name is not found or if the entity does not have a natural id specified + */ + public NaturalIdLoadAccess byNaturalKey(String entityName); + + /** + * Create an {@link NaturalIdLoadAccess} instance to retrieve the specified entity by + * its natural id. + * + * @param entityClass The type of the entity that will be retrieved + * @throws HibernateException If the specified Class is not an entity or if the entity does not have a natural id specified + */ + public NaturalIdLoadAccess byNaturalKey(Class entityClass); /** * Enable the named filter for this current session. diff --git a/hibernate-core/src/main/java/org/hibernate/internal/SessionImpl.java b/hibernate-core/src/main/java/org/hibernate/internal/SessionImpl.java index a6f1783958..6baa5f0e3c 100644 --- a/hibernate-core/src/main/java/org/hibernate/internal/SessionImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/internal/SessionImpl.java @@ -39,12 +39,11 @@ import java.sql.SQLException; import java.util.Collections; import java.util.HashSet; import java.util.Iterator; +import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Set; -import org.jboss.logging.Logger; - import org.hibernate.AssertionFailure; import org.hibernate.CacheMode; import org.hibernate.ConnectionReleaseMode; @@ -54,11 +53,13 @@ import org.hibernate.EntityNameResolver; import org.hibernate.Filter; import org.hibernate.FlushMode; import org.hibernate.HibernateException; +import org.hibernate.IdentifierLoadAccess; import org.hibernate.Interceptor; import org.hibernate.LobHelper; import org.hibernate.LockMode; import org.hibernate.LockOptions; import org.hibernate.MappingException; +import org.hibernate.NaturalIdLoadAccess; import org.hibernate.ObjectDeletedException; import org.hibernate.Query; import org.hibernate.QueryException; @@ -144,6 +145,7 @@ import org.hibernate.stat.SessionStatistics; import org.hibernate.stat.internal.SessionStatisticsImpl; import org.hibernate.type.SerializationException; import org.hibernate.type.Type; +import org.jboss.logging.Logger; /** * Concrete implementation of a Session. @@ -946,8 +948,40 @@ public final class SessionImpl extends AbstractSessionImpl implements EventSourc fireLoad( event, LoadEventListener.GET ); return event.getResult(); } + + /* (non-Javadoc) + * @see org.hibernate.Session#byId(java.lang.String) + */ + @Override + public IdentifierLoadAccess byId(String entityName) { + return new IdentifierLoadAccessByName(entityName); + } - private void fireLoad(LoadEvent event, LoadType loadType) { + /* (non-Javadoc) + * @see org.hibernate.Session#byId(java.lang.Class) + */ + @Override + public IdentifierLoadAccess byId(Class entityClass) { + return new IdentifierLoadAccessByClass(entityClass); + } + + /* (non-Javadoc) + * @see org.hibernate.Session#byNaturalKey(java.lang.String) + */ + @Override + public NaturalIdLoadAccess byNaturalKey(String entityName) { + return new NaturalIdLoadAccessByName(entityName); + } + + /* (non-Javadoc) + * @see org.hibernate.Session#byNaturalKey(java.lang.Class) + */ + @Override + public NaturalIdLoadAccess byNaturalKey(Class entityClass) { + return new NaturalIdLoadAccessByClass(entityClass); + } + + private void fireLoad(LoadEvent event, LoadType loadType) { errorIfClosed(); checkTransactionSynchStatus(); for ( LoadEventListener listener : listeners( EventType.LOAD ) ) { @@ -2164,4 +2198,259 @@ public final class SessionImpl extends AbstractSessionImpl implements EventSourc fireLock( object, lockOptions ); } } + + private abstract class AbstractIdentifierLoadAccess implements IdentifierLoadAccess { + private LockOptions lockOptions; + + /* (non-Javadoc) + * @see org.hibernate.IdentifierLoadAccess#with(org.hibernate.LockOptions) + */ + @Override + public final IdentifierLoadAccess with(LockOptions lockOptions) { + this.lockOptions = lockOptions; + return this; + } + + /* (non-Javadoc) + * @see org.hibernate.IdentifierLoadAccess#getReference(java.io.Serializable) + */ + @Override + public final T getReference(Serializable id) { + if (this.lockOptions != null) { + return getReferenceInternal(id, lockOptions); + } + + return getReferenceInternal(id); + } + + /* (non-Javadoc) + * @see org.hibernate.IdentifierLoadAccess#load(java.io.Serializable) + */ + @Override + public final T load(Serializable id) { + if (this.lockOptions != null) { + return loadInternal(id, lockOptions); + } + + return loadInternal(id); + } + + protected abstract T getReferenceInternal(Serializable id, LockOptions lockOptions); + protected abstract T getReferenceInternal(Serializable id); + protected abstract T loadInternal(Serializable id, LockOptions lockOptions); + protected abstract T loadInternal(Serializable id); + } + + private class IdentifierLoadAccessByName extends AbstractIdentifierLoadAccess { + private final String entityName; + + public IdentifierLoadAccessByName(String entityName) { + this.entityName = entityName; + } + + /* (non-Javadoc) + * @see org.hibernate.internal.SessionImpl.AbstractIdentifierLoadAccess#getReferenceInternal(java.io.Serializable, org.hibernate.LockOptions) + */ + @Override + protected Object getReferenceInternal(Serializable id, LockOptions lockOptions) { + return SessionImpl.this.load(entityName, id, lockOptions); + } + + /* (non-Javadoc) + * @see org.hibernate.internal.SessionImpl.AbstractIdentifierLoadAccess#getReferenceInternal(java.io.Serializable) + */ + @Override + protected Object getReferenceInternal(Serializable id) { + return SessionImpl.this.load(entityName, id); + } + + /* (non-Javadoc) + * @see org.hibernate.internal.SessionImpl.AbstractIdentifierLoadAccess#loadInternal(java.io.Serializable, org.hibernate.LockOptions) + */ + @Override + protected Object loadInternal(Serializable id, LockOptions lockOptions) { + return SessionImpl.this.get(entityName, id, lockOptions); + } + + /* (non-Javadoc) + * @see org.hibernate.internal.SessionImpl.AbstractIdentifierLoadAccess#loadInternal(java.io.Serializable) + */ + @Override + protected Object loadInternal(Serializable id) { + return SessionImpl.this.get(entityName, id); + } + } + + private class IdentifierLoadAccessByClass extends AbstractIdentifierLoadAccess { + private final Class entityClass; + + public IdentifierLoadAccessByClass(Class entityName) { + this.entityClass = entityName; + } + + /* (non-Javadoc) + * @see org.hibernate.internal.SessionImpl.AbstractIdentifierLoadAccess#getReferenceInternal(java.io.Serializable, org.hibernate.LockOptions) + */ + @Override + protected T getReferenceInternal(Serializable id, LockOptions lockOptions) { + return entityClass.cast(SessionImpl.this.load(entityClass, id, lockOptions)); + } + + /* (non-Javadoc) + * @see org.hibernate.internal.SessionImpl.AbstractIdentifierLoadAccess#getReferenceInternal(java.io.Serializable) + */ + @Override + protected T getReferenceInternal(Serializable id) { + return entityClass.cast(SessionImpl.this.load(entityClass, id)); + } + + /* (non-Javadoc) + * @see org.hibernate.internal.SessionImpl.AbstractIdentifierLoadAccess#loadInternal(java.io.Serializable, org.hibernate.LockOptions) + */ + @Override + protected T loadInternal(Serializable id, LockOptions lockOptions) { + return entityClass.cast(SessionImpl.this.get(entityClass, id, lockOptions)); + } + + /* (non-Javadoc) + * @see org.hibernate.internal.SessionImpl.AbstractIdentifierLoadAccess#loadInternal(java.io.Serializable) + */ + @Override + protected T loadInternal(Serializable id) { + return entityClass.cast(SessionImpl.this.get(entityClass, id)); + } + } + + + private abstract class AbstractNaturalIdLoadAccess implements NaturalIdLoadAccess { + private final Map naturalIdParameters = new LinkedHashMap(); + private LockOptions lockOptions; + + /* (non-Javadoc) + * @see org.hibernate.IdentifierLoadAccess#with(org.hibernate.LockOptions) + */ + @Override + public final NaturalIdLoadAccess with(LockOptions lockOptions) { + this.lockOptions = lockOptions; + return this; + } + + /* (non-Javadoc) + * @see org.hibernate.NaturalIdLoadAccess#using(java.lang.String, java.lang.Object) + */ + @Override + public NaturalIdLoadAccess using(String attributeName, Object value) { + naturalIdParameters.put(attributeName, value); + return this; + } + + /* (non-Javadoc) + * @see org.hibernate.NaturalIdLoadAccess#getReference() + */ + @Override + public final T getReference() { + if (this.lockOptions != null) { + return getReferenceInternal(naturalIdParameters, lockOptions); + } + + return getReferenceInternal(naturalIdParameters); + } + + /* (non-Javadoc) + * @see org.hibernate.NaturalIdLoadAccess#load() + */ + @Override + public final T load() { + if (this.lockOptions != null) { + return loadInternal(naturalIdParameters, lockOptions); + } + + return loadInternal(naturalIdParameters); + } + + protected abstract T getReferenceInternal(Map naturalIdParameters, LockOptions lockOptions); + protected abstract T getReferenceInternal(Map naturalIdParameters); + protected abstract T loadInternal(Map naturalIdParameters, LockOptions lockOptions); + protected abstract T loadInternal(Map naturalIdParameters); + } + + private class NaturalIdLoadAccessByName extends AbstractNaturalIdLoadAccess { + private final String entityName; + + public NaturalIdLoadAccessByName(String entityName) { + this.entityName = entityName; + } + + /* (non-Javadoc) + * @see org.hibernate.internal.SessionImpl.AbstractNaturalIdLoadAccess#getReferenceInternal(java.util.Map, org.hibernate.LockOptions) + */ + @Override + protected Object getReferenceInternal(Map naturalIdParameters, LockOptions lockOptions) { + throw new UnsupportedOperationException("Not Implemented Yet"); + } + + /* (non-Javadoc) + * @see org.hibernate.internal.SessionImpl.AbstractNaturalIdLoadAccess#getReferenceInternal(java.util.Map) + */ + @Override + protected Object getReferenceInternal(Map naturalIdParameters) { + throw new UnsupportedOperationException("Not Implemented Yet"); + } + + /* (non-Javadoc) + * @see org.hibernate.internal.SessionImpl.AbstractNaturalIdLoadAccess#loadInternal(java.util.Map, org.hibernate.LockOptions) + */ + @Override + protected Object loadInternal(Map naturalIdParameters, LockOptions lockOptions) { + throw new UnsupportedOperationException("Not Implemented Yet"); + } + + /* (non-Javadoc) + * @see org.hibernate.internal.SessionImpl.AbstractNaturalIdLoadAccess#loadInternal(java.util.Map) + */ + @Override + protected Object loadInternal(Map naturalIdParameters) { + throw new UnsupportedOperationException("Not Implemented Yet"); + } + } + + private class NaturalIdLoadAccessByClass extends AbstractNaturalIdLoadAccess { + private final Class entityClass; + + public NaturalIdLoadAccessByClass(Class entityName) { + this.entityClass = entityName; + } + + /* (non-Javadoc) + * @see org.hibernate.internal.SessionImpl.AbstractNaturalIdLoadAccess#getReferenceInternal(java.util.Map, org.hibernate.LockOptions) + */ + @Override + protected T getReferenceInternal(Map naturalIdParameters, LockOptions lockOptions) { + throw new UnsupportedOperationException("Not Implemented Yet"); + } + + /* (non-Javadoc) + * @see org.hibernate.internal.SessionImpl.AbstractNaturalIdLoadAccess#getReferenceInternal(java.util.Map) + */ + @Override + protected T getReferenceInternal(Map naturalIdParameters) { + throw new UnsupportedOperationException("Not Implemented Yet"); + } + + /* (non-Javadoc) + * @see org.hibernate.internal.SessionImpl.AbstractNaturalIdLoadAccess#loadInternal(java.util.Map, org.hibernate.LockOptions) + */ + @Override + protected T loadInternal(Map naturalIdParameters, LockOptions lockOptions) { + throw new UnsupportedOperationException("Not Implemented Yet"); + } + + /* (non-Javadoc) + * @see org.hibernate.internal.SessionImpl.AbstractNaturalIdLoadAccess#loadInternal(java.util.Map) + */ + @Override + protected T loadInternal(Map naturalIdParameters) { + throw new UnsupportedOperationException("Not Implemented Yet"); + } + } }