⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 foreignkeys.java

📁 一个Java持久层类库
💻 JAVA
字号:
//$Id: ForeignKeys.java 10133 2006-07-24 10:35:25Z max.andersen@jboss.com $package org.hibernate.engine;import java.io.Serializable;import org.hibernate.HibernateException;import org.hibernate.TransientObjectException;import org.hibernate.intercept.LazyPropertyInitializer;import org.hibernate.persister.entity.EntityPersister;import org.hibernate.proxy.HibernateProxy;import org.hibernate.proxy.LazyInitializer;import org.hibernate.type.AbstractComponentType;import org.hibernate.type.EntityType;import org.hibernate.type.Type;/** * Algorithms related to foreign key constraint transparency *  * @author Gavin King */public final class ForeignKeys {		private ForeignKeys() {}		public static class Nullifier {			private final boolean isDelete;		private final boolean isEarlyInsert;		private final SessionImplementor session;		private final Object self;				public Nullifier(Object self, boolean isDelete, boolean isEarlyInsert, SessionImplementor session) {			this.isDelete = isDelete;			this.isEarlyInsert = isEarlyInsert;			this.session = session;			this.self = self;		}				/**		 * Nullify all references to entities that have not yet 		 * been inserted in the database, where the foreign key		 * points toward that entity		 */		public void nullifyTransientReferences(final Object[] values, final Type[] types) 		throws HibernateException {			for ( int i = 0; i < types.length; i++ ) {				values[i] = nullifyTransientReferences( values[i], types[i] );			}		}			/**		 * Return null if the argument is an "unsaved" entity (ie. 		 * one with no existing database row), or the input argument 		 * otherwise. This is how Hibernate avoids foreign key constraint		 * violations.		 */		private Object nullifyTransientReferences(final Object value, final Type type) 		throws HibernateException {			if ( value == null ) {				return null;			}			else if ( type.isEntityType() ) {				EntityType entityType = (EntityType) type;				if ( entityType.isOneToOne() ) {					return value;				}				else {					String entityName = entityType.getAssociatedEntityName();					return isNullifiable(entityName, value) ? null : value;				}			}			else if ( type.isAnyType() ) {				return isNullifiable(null, value) ? null : value;			}			else if ( type.isComponentType() ) {				AbstractComponentType actype = (AbstractComponentType) type;				Object[] subvalues = actype.getPropertyValues(value, session);				Type[] subtypes = actype.getSubtypes();				boolean substitute = false;				for ( int i = 0; i < subvalues.length; i++ ) {					Object replacement = nullifyTransientReferences( subvalues[i], subtypes[i] );					if ( replacement != subvalues[i] ) {						substitute = true;						subvalues[i] = replacement;					}				}				if (substitute) actype.setPropertyValues( value, subvalues, session.getEntityMode() );				return value;			}			else {				return value;			}		}			/**		 * Determine if the object already exists in the database, 		 * using a "best guess"		 */		private boolean isNullifiable(final String entityName, Object object) 		throws HibernateException {						if (object==LazyPropertyInitializer.UNFETCHED_PROPERTY) return false; //this is kinda the best we can do...						if ( object instanceof HibernateProxy ) {				// if its an uninitialized proxy it can't be transient				LazyInitializer li = ( (HibernateProxy) object ).getHibernateLazyInitializer();				if ( li.getImplementation(session) == null ) {					return false;					// ie. we never have to null out a reference to					// an uninitialized proxy				}				else {					//unwrap it					object = li.getImplementation();				}			}				// if it was a reference to self, don't need to nullify			// unless we are using native id generation, in which			// case we definitely need to nullify			if ( object == self ) {				return isEarlyInsert || (					isDelete &&					session.getFactory()						.getDialect()						.hasSelfReferentialForeignKeyBug()				);			}				// See if the entity is already bound to this session, if not look at the			// entity identifier and assume that the entity is persistent if the			// id is not "unsaved" (that is, we rely on foreign keys to keep			// database integrity)				EntityEntry entityEntry = session.getPersistenceContext().getEntry(object);			if ( entityEntry==null ) {				return isTransient(entityName, object, null, session);			}			else {				return entityEntry.isNullifiable(isEarlyInsert, session);			}			}			}		/**	 * Is this instance persistent or detached?	 * If <tt>assumed</tt> is non-null, don't hit the database to make the 	 * determination, instead assume that value; the client code must be 	 * prepared to "recover" in the case that this assumed result is incorrect.	 */	public static boolean isNotTransient(String entityName, Object entity, Boolean assumed, SessionImplementor session) 	throws HibernateException {		if (entity instanceof HibernateProxy) return true;		if ( session.getPersistenceContext().isEntryFor(entity) ) return true;		return !isTransient(entityName, entity, assumed, session);	}		/**	 * Is this instance, which we know is not persistent, actually transient?	 * If <tt>assumed</tt> is non-null, don't hit the database to make the 	 * determination, instead assume that value; the client code must be 	 * prepared to "recover" in the case that this assumed result is incorrect.	 */	public static boolean isTransient(String entityName, Object entity, Boolean assumed, SessionImplementor session) 	throws HibernateException {				if (entity==LazyPropertyInitializer.UNFETCHED_PROPERTY) {			// an unfetched association can only point to			// an entity that already exists in the db			return false;		}				// let the interceptor inspect the instance to decide		Boolean isUnsaved = session.getInterceptor().isTransient(entity);		if (isUnsaved!=null) return isUnsaved.booleanValue();				// let the persister inspect the instance to decide		EntityPersister persister = session.getEntityPersister(entityName, entity);		isUnsaved = persister.isTransient(entity, session);		if (isUnsaved!=null) return isUnsaved.booleanValue();		// we use the assumed value, if there is one, to avoid hitting		// the database		if (assumed!=null) return assumed.booleanValue();				// hit the database, after checking the session cache for a snapshot		Object[] snapshot = session.getPersistenceContext()		        .getDatabaseSnapshot( persister.getIdentifier( entity, session.getEntityMode() ), persister );		return snapshot==null;	}	/**	 * Return the identifier of the persistent or transient object, or throw	 * an exception if the instance is "unsaved"	 *	 * Used by OneToOneType and ManyToOneType to determine what id value should 	 * be used for an object that may or may not be associated with the session. 	 * This does a "best guess" using any/all info available to use (not just the 	 * EntityEntry).	 */	public static Serializable getEntityIdentifierIfNotUnsaved(			final String entityName, 			final Object object, 			final SessionImplementor session) 	throws HibernateException {		if ( object == null ) {			return null;		}		else {			Serializable id = session.getContextEntityIdentifier( object );			if ( id == null ) {				// context-entity-identifier returns null explicitly if the entity				// is not associated with the persistence context; so make some				// deeper checks...				if ( isTransient(entityName, object, Boolean.FALSE, session) ) {					throw new TransientObjectException(							"object references an unsaved transient instance - save the transient instance before flushing: " +							(entityName == null ? session.guessEntityName( object ) : entityName)					);				}				id = session.getEntityPersister( entityName, object ).getIdentifier( object, session.getEntityMode() );			}			return id;		}	}}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -