alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Hibernate example source code file (EntityType.java)

This example Hibernate source code file (EntityType.java) is included in the DevDaily.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Java - Hibernate tags/keywords

class, hibernateexception, hibernateexception, hibernateproxy, io, jdbc, mappingexception, object, object, serializable, serializable, sessionfactoryimplementor, sessionimplementor, sql, string, string, type, util

The Hibernate EntityType.java source code

/*
 * Hibernate, Relational Persistence for Idiomatic Java
 *
 * Copyright (c) 2010, 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.type;

import java.io.Serializable;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Map;

import org.dom4j.Element;
import org.dom4j.Node;

import org.hibernate.AssertionFailure;
import org.hibernate.EntityMode;
import org.hibernate.HibernateException;
import org.hibernate.MappingException;
import org.hibernate.engine.internal.ForeignKeys;
import org.hibernate.engine.spi.EntityUniqueKey;
import org.hibernate.engine.spi.Mapping;
import org.hibernate.engine.spi.PersistenceContext;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.internal.util.ReflectHelper;
import org.hibernate.persister.entity.EntityPersister;
import org.hibernate.persister.entity.Joinable;
import org.hibernate.persister.entity.UniqueKeyLoadable;
import org.hibernate.proxy.HibernateProxy;
import org.hibernate.tuple.ElementWrapper;

/**
 * Base for types which map associations to persistent entities.
 *
 * @author Gavin King
 */
public abstract class EntityType extends AbstractType implements AssociationType {

	private final TypeFactory.TypeScope scope;
	private final String associatedEntityName;
	protected final String uniqueKeyPropertyName;
	protected final boolean isEmbeddedInXML;
	private final boolean eager;
	private final boolean unwrapProxy;

	private transient Class returnedClass;

	/**
	 * Constructs the requested entity type mapping.
	 *
	 * @param scope The type scope
	 * @param entityName The name of the associated entity.
	 * @param uniqueKeyPropertyName The property-ref name, or null if we
	 * reference the PK of the associated entity.
	 * @param eager Is eager fetching enabled.
	 * @param isEmbeddedInXML Should values of this mapping be embedded in XML modes?
	 * @param unwrapProxy Is unwrapping of proxies allowed for this association; unwrapping
	 * says to return the "implementation target" of lazy prooxies; typically only possible
	 * with lazy="no-proxy".
	 */
	protected EntityType(
			TypeFactory.TypeScope scope,
			String entityName,
			String uniqueKeyPropertyName,
			boolean eager,
			boolean isEmbeddedInXML,
			boolean unwrapProxy) {
		this.scope = scope;
		this.associatedEntityName = entityName;
		this.uniqueKeyPropertyName = uniqueKeyPropertyName;
		this.isEmbeddedInXML = isEmbeddedInXML;
		this.eager = eager;
		this.unwrapProxy = unwrapProxy;
	}

	protected TypeFactory.TypeScope scope() {
		return scope;
	}

	/**
	 * An entity type is a type of association type
	 *
	 * @return True.
	 */
	public boolean isAssociationType() {
		return true;
	}

	/**
	 * Explicitly, an entity type is an entity type ;)
	 *
	 * @return True.
	 */
	public final boolean isEntityType() {
		return true;
	}

	/**
	 * {@inheritDoc}
	 */
	public boolean isMutable() {
		return false;
	}

	/**
	 * Generates a string representation of this type.
	 *
	 * @return string rep
	 */
	public String toString() {
		return getClass().getName() + '(' + getAssociatedEntityName() + ')';
	}

	/**
	 * For entity types, the name correlates to the associated entity name.
	 */
	public String getName() {
		return associatedEntityName;
	}

	/**
	 * Does this association foreign key reference the primary key of the other table?
	 * Otherwise, it references a property-ref.
	 *
	 * @return True if this association reference the PK of the associated entity.
	 */
	public boolean isReferenceToPrimaryKey() {
		return uniqueKeyPropertyName==null;
	}

	public String getRHSUniqueKeyPropertyName() {
		return uniqueKeyPropertyName;
	}

	public String getLHSPropertyName() {
		return null;
	}

	public String getPropertyName() {
		return null;
	}

	/**
	 * The name of the associated entity.
	 *
	 * @return The associated entity name.
	 */
	public final String getAssociatedEntityName() {
		return associatedEntityName;
	}

	/**
	 * The name of the associated entity.
	 *
	 * @param factory The session factory, for resolution.
	 * @return The associated entity name.
	 */
	public String getAssociatedEntityName(SessionFactoryImplementor factory) {
		return getAssociatedEntityName();
	}

	/**
	 * Retrieves the {@link Joinable} defining the associated entity.
	 *
	 * @param factory The session factory.
	 * @return The associated joinable
	 * @throws MappingException Generally indicates an invalid entity name.
	 */
	public Joinable getAssociatedJoinable(SessionFactoryImplementor factory) throws MappingException {
		return ( Joinable ) factory.getEntityPersister( associatedEntityName );
	}

	/**
	 * This returns the wrong class for an entity with a proxy, or for a named
	 * entity.  Theoretically it should return the proxy class, but it doesn't.
	 * <p/>
	 * The problem here is that we do not necessarily have a ref to the associated
	 * entity persister (nor to the session factory, to look it up) which is really
	 * needed to "do the right thing" here...
	 *
	 * @return The entiyt class.
	 */
	public final Class getReturnedClass() {
		if ( returnedClass == null ) {
			returnedClass = determineAssociatedEntityClass();
		}
		return returnedClass;
	}

	private Class determineAssociatedEntityClass() {
		try {
			return ReflectHelper.classForName( getAssociatedEntityName() );
		}
		catch ( ClassNotFoundException cnfe ) {
			return java.util.Map.class;
		}
	}

	/**
	 * {@inheritDoc}
	 */
	public Object nullSafeGet(ResultSet rs, String name, SessionImplementor session, Object owner)
	throws HibernateException, SQLException {
		return nullSafeGet( rs, new String[] {name}, session, owner );
	}

	/**
	 * {@inheritDoc}
	 */
	public final Object nullSafeGet(
			ResultSet rs,
			String[] names,
			SessionImplementor session,
			Object owner) throws HibernateException, SQLException {
		return resolve( hydrate(rs, names, session, owner), session, owner );
	}

	/**
	 * Two entities are considered the same when their instances are the same.
	 *
	 *
	 * @param x One entity instance
	 * @param y Another entity instance
	 * @return True if x == y; false otherwise.
	 */
	public final boolean isSame(Object x, Object y) {
		return x == y;
	}

	/**
	 * {@inheritDoc}
	 */
	public int compare(Object x, Object y) {
		return 0; //TODO: entities CAN be compared, by PK, fix this! -> only if/when we can extract the id values....
	}

	/**
	 * {@inheritDoc}
	 */
	public Object deepCopy(Object value, SessionFactoryImplementor factory) {
		return value; //special case ... this is the leaf of the containment graph, even though not immutable
	}

	/**
	 * {@inheritDoc}
	 */
	public Object replace(
			Object original,
			Object target,
			SessionImplementor session,
			Object owner,
			Map copyCache) throws HibernateException {
		if ( original == null ) {
			return null;
		}
		Object cached = copyCache.get(original);
		if ( cached != null ) {
			return cached;
		}
		else {
			if ( original == target ) {
				return target;
			}
			if ( session.getContextEntityIdentifier( original ) == null  &&
					ForeignKeys.isTransient( associatedEntityName, original, Boolean.FALSE, session ) ) {
				final Object copy = session.getFactory().getEntityPersister( associatedEntityName )
						.instantiate( null, session );
				//TODO: should this be Session.instantiate(Persister, ...)?
				copyCache.put( original, copy );
				return copy;
			}
			else {
				Object id = getIdentifier( original, session );
				if ( id == null ) {
					throw new AssertionFailure("non-transient entity has a null id");
				}
				id = getIdentifierOrUniqueKeyType( session.getFactory() )
						.replace(id, null, session, owner, copyCache);
				return resolve( id, session, owner );
			}
		}
	}

	/**
	 * {@inheritDoc}
	 */
	public int getHashCode(Object x, SessionFactoryImplementor factory) {
		EntityPersister persister = factory.getEntityPersister(associatedEntityName);
		if ( !persister.canExtractIdOutOfEntity() ) {
			return super.getHashCode( x );
		}

		final Serializable id;
		if (x instanceof HibernateProxy) {
			id = ( (HibernateProxy) x ).getHibernateLazyInitializer().getIdentifier();
		}
		else {
			final Class mappedClass = persister.getMappedClass();
			if ( mappedClass.isAssignableFrom( x.getClass() ) ) {
				id = persister.getIdentifier( x );
			}
			else {
				id = (Serializable) x;
			}
		}
		return persister.getIdentifierType().getHashCode( id, factory );
	}

	/**
	 * {@inheritDoc}
	 */
	public boolean isEqual(Object x, Object y, SessionFactoryImplementor factory) {
		EntityPersister persister = factory.getEntityPersister(associatedEntityName);
		if ( !persister.canExtractIdOutOfEntity() ) {
			return super.isEqual(x, y );
		}

		final Class mappedClass = persister.getMappedClass();
		Serializable xid;
		if (x instanceof HibernateProxy) {
			xid = ( (HibernateProxy) x ).getHibernateLazyInitializer()
					.getIdentifier();
		}
		else {
			if ( mappedClass.isAssignableFrom( x.getClass() ) ) {
				xid = persister.getIdentifier( x );
			}
			else {
				//JPA 2 case where @IdClass contains the id and not the associated entity
				xid = (Serializable) x;
			}
		}

		Serializable yid;
		if (y instanceof HibernateProxy) {
			yid = ( (HibernateProxy) y ).getHibernateLazyInitializer()
					.getIdentifier();
		}
		else {
			if ( mappedClass.isAssignableFrom( y.getClass() ) ) {
				yid = persister.getIdentifier( y );
			}
			else {
				//JPA 2 case where @IdClass contains the id and not the associated entity
				yid = (Serializable) y;
			}
		}

		return persister.getIdentifierType()
				.isEqual(xid, yid, factory);
	}

	/**
	 * {@inheritDoc}
	 */
	public boolean isEmbeddedInXML() {
		return isEmbeddedInXML;
	}

	/**
	 * {@inheritDoc}
	 */
	public boolean isXMLElement() {
		return isEmbeddedInXML;
	}

	/**
	 * {@inheritDoc}
	 */
	public Object fromXMLNode(Node xml, Mapping factory) throws HibernateException {
		if ( !isEmbeddedInXML ) {
			return getIdentifierType(factory).fromXMLNode(xml, factory);
		}
		else {
			return xml;
		}
	}

	/**
	 * {@inheritDoc}
	 */
	public void setToXMLNode(Node node, Object value, SessionFactoryImplementor factory) throws HibernateException {
		if ( !isEmbeddedInXML ) {
			getIdentifierType(factory).setToXMLNode(node, value, factory);
		}
		else {
			Element elt = (Element) value;
			replaceNode( node, new ElementWrapper(elt) );
		}
	}

	public String getOnCondition(String alias, SessionFactoryImplementor factory, Map enabledFilters)
	throws MappingException {
		if ( isReferenceToPrimaryKey() ) { //TODO: this is a bit arbitrary, expose a switch to the user?
			return "";
		}
		else {
			return getAssociatedJoinable( factory ).filterFragment( alias, enabledFilters );
		}
	}

	/**
	 * Resolve an identifier or unique key value
	 */
	public Object resolve(Object value, SessionImplementor session, Object owner) throws HibernateException {
		if ( isNotEmbedded( session ) ) {
			return value;
		}

		if ( value == null ) {
			return null;
		}
		else {
			if ( isNull( owner, session ) ) {
				return null; //EARLY EXIT!
			}

			if ( isReferenceToPrimaryKey() ) {
				return resolveIdentifier( (Serializable) value, session );
			}
			else {
				return loadByUniqueKey( getAssociatedEntityName(), uniqueKeyPropertyName, value, session );
			}
		}
	}

	public Type getSemiResolvedType(SessionFactoryImplementor factory) {
		return factory.getEntityPersister( associatedEntityName ).getIdentifierType();
	}

	protected final Object getIdentifier(Object value, SessionImplementor session) throws HibernateException {
		if ( isNotEmbedded(session) ) {
			return value;
		}

		if ( isReferenceToPrimaryKey() ) {
			return ForeignKeys.getEntityIdentifierIfNotUnsaved( getAssociatedEntityName(), value, session ); //tolerates nulls
		}
		else if ( value == null ) {
			return null;
		}
		else {
			EntityPersister entityPersister = session.getFactory().getEntityPersister( getAssociatedEntityName() );
			Object propertyValue = entityPersister.getPropertyValue( value, uniqueKeyPropertyName );
			// We now have the value of the property-ref we reference.  However,
			// we need to dig a little deeper, as that property might also be
			// an entity type, in which case we need to resolve its identitifier
			Type type = entityPersister.getPropertyType( uniqueKeyPropertyName );
			if ( type.isEntityType() ) {
				propertyValue = ( ( EntityType ) type ).getIdentifier( propertyValue, session );
			}

			return propertyValue;
		}
	}

	protected boolean isNotEmbedded(SessionImplementor session) {
//		return !isEmbeddedInXML;
		return false;
	}

	/**
	 * Generate a loggable representation of an instance of the value mapped by this type.
	 *
	 * @param value The instance to be logged.
	 * @param factory The session factory.
	 * @return The loggable string.
	 * @throws HibernateException Generally some form of resolution problem.
	 */
	public String toLoggableString(Object value, SessionFactoryImplementor factory) {
		if ( value == null ) {
			return "null";
		}
		
		EntityPersister persister = factory.getEntityPersister( associatedEntityName );
		StringBuffer result = new StringBuffer().append( associatedEntityName );

		if ( persister.hasIdentifierProperty() ) {
			final EntityMode entityMode = persister.getEntityMode();
			final Serializable id;
			if ( entityMode == null ) {
				if ( isEmbeddedInXML ) {
					throw new ClassCastException( value.getClass().getName() );
				}
				id = ( Serializable ) value;
			}
			else {
				id = persister.getIdentifier( value );
			}
			
			result.append( '#' )
				.append( persister.getIdentifierType().toLoggableString( id, factory ) );
		}
		
		return result.toString();
	}

	/**
	 * Is the association modeled here defined as a 1-1 in the database (physical model)?
	 *
	 * @return True if a 1-1 in the database; false otherwise.
	 */
	public abstract boolean isOneToOne();

	/**
	 * Is the association modeled here a 1-1 according to the logical moidel?
	 *
	 * @return True if a 1-1 in the logical model; false otherwise.
	 */
	public boolean isLogicalOneToOne() {
		return isOneToOne();
	}

	/**
	 * Convenience method to locate the identifier type of the associated entity.
	 *
	 * @param factory The mappings...
	 * @return The identifier type
	 */
	Type getIdentifierType(Mapping factory) {
		return factory.getIdentifierType( getAssociatedEntityName() );
	}

	/**
	 * Convenience method to locate the identifier type of the associated entity.
	 *
	 * @param session The originating session
	 * @return The identifier type
	 */
	Type getIdentifierType(SessionImplementor session) {
		return getIdentifierType( session.getFactory() );
	}

	/**
	 * Determine the type of either (1) the identifier if we reference the
	 * associated entity's PK or (2) the unique key to which we refer (i.e.
	 * the property-ref).
	 *
	 * @param factory The mappings...
	 * @return The appropriate type.
	 * @throws MappingException Generally, if unable to resolve the associated entity name
	 * or unique key property name.
	 */
	public final Type getIdentifierOrUniqueKeyType(Mapping factory) throws MappingException {
		if ( isReferenceToPrimaryKey() ) {
			return getIdentifierType(factory);
		}
		else {
			Type type = factory.getReferencedPropertyType( getAssociatedEntityName(), uniqueKeyPropertyName );
			if ( type.isEntityType() ) {
				type = ( ( EntityType ) type).getIdentifierOrUniqueKeyType( factory );
			}
			return type;
		}
	}

	/**
	 * The name of the property on the associated entity to which our FK
	 * refers
	 *
	 * @param factory The mappings...
	 * @return The appropriate property name.
	 * @throws MappingException Generally, if unable to resolve the associated entity name
	 */
	public final String getIdentifierOrUniqueKeyPropertyName(Mapping factory)
	throws MappingException {
		if ( isReferenceToPrimaryKey() ) {
			return factory.getIdentifierPropertyName( getAssociatedEntityName() );
		}
		else {
			return uniqueKeyPropertyName;
		}
	}
	
	protected abstract boolean isNullable();

	/**
	 * Resolve an identifier via a load.
	 *
	 * @param id The entity id to resolve
	 * @param session The orginating session.
	 * @return The resolved identifier (i.e., loaded entity).
	 * @throws org.hibernate.HibernateException Indicates problems performing the load.
	 */
	protected final Object resolveIdentifier(Serializable id, SessionImplementor session) throws HibernateException {
		boolean isProxyUnwrapEnabled = unwrapProxy &&
				session.getFactory()
						.getEntityPersister( getAssociatedEntityName() )
						.isInstrumented();

		Object proxyOrEntity = session.internalLoad(
				getAssociatedEntityName(),
				id,
				eager,
				isNullable() && !isProxyUnwrapEnabled
		);

		if ( proxyOrEntity instanceof HibernateProxy ) {
			( ( HibernateProxy ) proxyOrEntity ).getHibernateLazyInitializer()
					.setUnwrap( isProxyUnwrapEnabled );
		}

		return proxyOrEntity;
	}

	protected boolean isNull(Object owner, SessionImplementor session) {
		return false;
	}

	/**
	 * Load an instance by a unique key that is not the primary key.
	 *
	 * @param entityName The name of the entity to load
	 * @param uniqueKeyPropertyName The name of the property defining the uniqie key.
	 * @param key The unique key property value.
	 * @param session The originating session.
	 * @return The loaded entity
	 * @throws HibernateException generally indicates problems performing the load.
	 */
	public Object loadByUniqueKey(
			String entityName, 
			String uniqueKeyPropertyName, 
			Object key, 
			SessionImplementor session) throws HibernateException {
		final SessionFactoryImplementor factory = session.getFactory();
		UniqueKeyLoadable persister = ( UniqueKeyLoadable ) factory.getEntityPersister( entityName );

		//TODO: implement caching?! proxies?!

		EntityUniqueKey euk = new EntityUniqueKey(
				entityName, 
				uniqueKeyPropertyName, 
				key, 
				getIdentifierOrUniqueKeyType( factory ),
				persister.getEntityMode(),
				session.getFactory()
		);

		final PersistenceContext persistenceContext = session.getPersistenceContext();
		Object result = persistenceContext.getEntity( euk );
		if ( result == null ) {
			result = persister.loadByUniqueKey( uniqueKeyPropertyName, key, session );
		}
		return result == null ? null : persistenceContext.proxyFor( result );
	}

}

Other Hibernate examples (source code examples)

Here is a short list of links related to this Hibernate EntityType.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.