Save This Page
Home » hibernate-distribution-3.3.1.GA-dist » org.hibernate » type » [javadoc | source]
    1   /*
    2    * Hibernate, Relational Persistence for Idiomatic Java
    3    *
    4    * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
    5    * indicated by the @author tags or express copyright attribution
    6    * statements applied by the authors.  All third-party contributions are
    7    * distributed under license by Red Hat Middleware LLC.
    8    *
    9    * This copyrighted material is made available to anyone wishing to use, modify,
   10    * copy, or redistribute it subject to the terms and conditions of the GNU
   11    * Lesser General Public License, as published by the Free Software Foundation.
   12    *
   13    * This program is distributed in the hope that it will be useful,
   14    * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
   15    * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
   16    * for more details.
   17    *
   18    * You should have received a copy of the GNU Lesser General Public License
   19    * along with this distribution; if not, write to:
   20    * Free Software Foundation, Inc.
   21    * 51 Franklin Street, Fifth Floor
   22    * Boston, MA  02110-1301  USA
   23    *
   24    */
   25   package org.hibernate.type;
   26   
   27   import java.io.Serializable;
   28   import java.sql.PreparedStatement;
   29   import java.sql.ResultSet;
   30   import java.sql.SQLException;
   31   import java.util.Arrays;
   32   
   33   import org.hibernate.AssertionFailure;
   34   import org.hibernate.HibernateException;
   35   import org.hibernate.MappingException;
   36   import org.hibernate.engine.EntityKey;
   37   import org.hibernate.engine.ForeignKeys;
   38   import org.hibernate.engine.Mapping;
   39   import org.hibernate.engine.SessionImplementor;
   40   import org.hibernate.persister.entity.EntityPersister;
   41   
   42   /**
   43    * A many-to-one association to an entity.
   44    *
   45    * @author Gavin King
   46    */
   47   public class ManyToOneType extends EntityType {
   48   	
   49   	private final boolean ignoreNotFound;
   50   
   51   	public ManyToOneType(String className) {
   52   		this( className, false );
   53   	}
   54   
   55   	public ManyToOneType(String className, boolean lazy) {
   56   		super( className, null, !lazy, true, false );
   57   		this.ignoreNotFound = false;
   58   	}
   59   
   60   	public ManyToOneType(
   61   			String entityName,
   62   			String uniqueKeyPropertyName,
   63   			boolean lazy,
   64   			boolean unwrapProxy,
   65   			boolean isEmbeddedInXML,
   66   			boolean ignoreNotFound) {
   67   		super( entityName, uniqueKeyPropertyName, !lazy, isEmbeddedInXML, unwrapProxy );
   68   		this.ignoreNotFound = ignoreNotFound;
   69   	}
   70   
   71   	protected boolean isNullable() {
   72   		return ignoreNotFound;
   73   	}
   74   
   75   	public boolean isAlwaysDirtyChecked() {
   76   		// If we have <tt>not-found="ignore"</tt> association mapped to a
   77   		// formula, we always need to dirty check it, so we can update the
   78   		// second-level cache
   79   		return ignoreNotFound;
   80   	}
   81   
   82   	public boolean isOneToOne() {
   83   		return false;
   84   	}
   85   	
   86   	public int getColumnSpan(Mapping mapping) throws MappingException {
   87   		// our column span is the number of columns in the PK
   88   		return getIdentifierOrUniqueKeyType( mapping ).getColumnSpan( mapping );
   89   	}
   90   
   91   	public int[] sqlTypes(Mapping mapping) throws MappingException {
   92   		return getIdentifierOrUniqueKeyType( mapping ).sqlTypes( mapping );
   93   	}
   94   
   95   	public void nullSafeSet(
   96   			PreparedStatement st,
   97   			Object value,
   98   			int index,
   99   			boolean[] settable,
  100   			SessionImplementor session) throws HibernateException, SQLException {
  101   		getIdentifierOrUniqueKeyType( session.getFactory() )
  102   				.nullSafeSet( st, getIdentifier( value, session ), index, settable, session );
  103   	}
  104   
  105   	public void nullSafeSet(
  106   			PreparedStatement st,
  107   			Object value,
  108   			int index,
  109   			SessionImplementor session) throws HibernateException, SQLException {
  110   		getIdentifierOrUniqueKeyType( session.getFactory() )
  111   				.nullSafeSet( st, getIdentifier( value, session ), index, session );
  112   	}
  113   
  114   	public ForeignKeyDirection getForeignKeyDirection() {
  115   		return ForeignKeyDirection.FOREIGN_KEY_FROM_PARENT;
  116   	}
  117   
  118   	public Object hydrate(
  119   			ResultSet rs,
  120   			String[] names,
  121   			SessionImplementor session,
  122   			Object owner) throws HibernateException, SQLException {
  123   		// return the (fully resolved) identifier value, but do not resolve
  124   		// to the actual referenced entity instance
  125   		// NOTE: the owner of the association is not really the owner of the id!
  126   		Serializable id = (Serializable) getIdentifierOrUniqueKeyType( session.getFactory() )
  127   				.nullSafeGet( rs, names, session, null );
  128   		scheduleBatchLoadIfNeeded( id, session );
  129   		return id;
  130   	}
  131   
  132   	/**
  133   	 * Register the entity as batch loadable, if enabled
  134   	 */
  135   	private void scheduleBatchLoadIfNeeded(
  136   			Serializable id,
  137   			SessionImplementor session) throws MappingException {
  138   		//cannot batch fetch by unique key (property-ref associations)
  139   		if ( uniqueKeyPropertyName == null && id != null ) {
  140   			EntityPersister persister = session.getFactory().getEntityPersister( getAssociatedEntityName() );
  141   			EntityKey entityKey = new EntityKey( id, persister, session.getEntityMode() );
  142   			if ( !session.getPersistenceContext().containsEntity( entityKey ) ) {
  143   				session.getPersistenceContext()
  144   						.getBatchFetchQueue()
  145   						.addBatchLoadableEntityKey( entityKey );
  146   			}
  147   		}
  148   	}
  149   	
  150   	public boolean useLHSPrimaryKey() {
  151   		return false;
  152   	}
  153   
  154   	public boolean isModified(
  155   			Object old,
  156   			Object current,
  157   			boolean[] checkable,
  158   			SessionImplementor session) throws HibernateException {
  159   		if ( current == null ) {
  160   			return old!=null;
  161   		}
  162   		if ( old == null ) {
  163   			// we already know current is not null...
  164   			return true;
  165   		}
  166   		// the ids are fully resolved, so compare them with isDirty(), not isModified()
  167   		return getIdentifierOrUniqueKeyType( session.getFactory() )
  168   				.isDirty( old, getIdentifier( current, session ), session );
  169   	}
  170   
  171   	public Serializable disassemble(
  172   			Object value,
  173   			SessionImplementor session,
  174   			Object owner) throws HibernateException {
  175   
  176   		if ( isNotEmbedded( session ) ) {
  177   			return getIdentifierType( session ).disassemble( value, session, owner );
  178   		}
  179   		
  180   		if ( value == null ) {
  181   			return null;
  182   		}
  183   		else {
  184   			// cache the actual id of the object, not the value of the
  185   			// property-ref, which might not be initialized
  186   			Object id = ForeignKeys.getEntityIdentifierIfNotUnsaved( 
  187   					getAssociatedEntityName(), 
  188   					value, 
  189   					session
  190   			);
  191   			if ( id == null ) {
  192   				throw new AssertionFailure(
  193   						"cannot cache a reference to an object with a null id: " + 
  194   						getAssociatedEntityName()
  195   				);
  196   			}
  197   			return getIdentifierType( session ).disassemble( id, session, owner );
  198   		}
  199   	}
  200   
  201   	public Object assemble(
  202   			Serializable oid,
  203   			SessionImplementor session,
  204   			Object owner) throws HibernateException {
  205   		
  206   		//TODO: currently broken for unique-key references (does not detect
  207   		//      change to unique key property of the associated object)
  208   		
  209   		Serializable id = assembleId( oid, session );
  210   
  211   		if ( isNotEmbedded( session ) ) {
  212   			return id;
  213   		}
  214   		
  215   		if ( id == null ) {
  216   			return null;
  217   		}
  218   		else {
  219   			return resolveIdentifier( id, session );
  220   		}
  221   	}
  222   
  223   	private Serializable assembleId(Serializable oid, SessionImplementor session) {
  224   		//the owner of the association is not the owner of the id
  225   		return ( Serializable ) getIdentifierType( session ).assemble( oid, session, null );
  226   	}
  227   
  228   	public void beforeAssemble(Serializable oid, SessionImplementor session) {
  229   		scheduleBatchLoadIfNeeded( assembleId( oid, session ), session );
  230   	}
  231   	
  232   	public boolean[] toColumnNullness(Object value, Mapping mapping) {
  233   		boolean[] result = new boolean[ getColumnSpan( mapping ) ];
  234   		if ( value != null ) {
  235   			Arrays.fill( result, true );
  236   		}
  237   		return result;
  238   	}
  239   	
  240   	public boolean isDirty(
  241   			Object old,
  242   			Object current,
  243   			SessionImplementor session) throws HibernateException {
  244   		if ( isSame( old, current, session.getEntityMode() ) ) {
  245   			return false;
  246   		}
  247   		Object oldid = getIdentifier( old, session );
  248   		Object newid = getIdentifier( current, session );
  249   		return getIdentifierType( session ).isDirty( oldid, newid, session );
  250   	}
  251   
  252   	public boolean isDirty(
  253   			Object old,
  254   			Object current,
  255   			boolean[] checkable,
  256   			SessionImplementor session) throws HibernateException {
  257   		if ( isAlwaysDirtyChecked() ) {
  258   			return isDirty( old, current, session );
  259   		}
  260   		else {
  261   			if ( isSame( old, current, session.getEntityMode() ) ) {
  262   				return false;
  263   			}
  264   			Object oldid = getIdentifier( old, session );
  265   			Object newid = getIdentifier( current, session );
  266   			return getIdentifierType( session ).isDirty( oldid, newid, checkable, session );
  267   		}
  268   		
  269   	}
  270   
  271   }

Save This Page
Home » hibernate-distribution-3.3.1.GA-dist » org.hibernate » type » [javadoc | source]