1 package org.hibernate.engine; 3 4 import java.io.Serializable ; 5 6 import org.hibernate.HibernateException; 7 import org.hibernate.TransientObjectException; 8 import org.hibernate.intercept.LazyPropertyInitializer; 9 import org.hibernate.persister.entity.EntityPersister; 10 import org.hibernate.proxy.HibernateProxy; 11 import org.hibernate.proxy.LazyInitializer; 12 import org.hibernate.type.AbstractComponentType; 13 import org.hibernate.type.EntityType; 14 import org.hibernate.type.Type; 15 16 21 public final class ForeignKeys { 22 23 private ForeignKeys() {} 24 25 public static class Nullifier { 26 27 private final boolean isDelete; 28 private final boolean isEarlyInsert; 29 private final SessionImplementor session; 30 private final Object self; 31 32 public Nullifier(Object self, boolean isDelete, boolean isEarlyInsert, SessionImplementor session) { 33 this.isDelete = isDelete; 34 this.isEarlyInsert = isEarlyInsert; 35 this.session = session; 36 this.self = self; 37 } 38 39 44 public void nullifyTransientReferences(final Object [] values, final Type[] types) 45 throws HibernateException { 46 for ( int i = 0; i < types.length; i++ ) { 47 values[i] = nullifyTransientReferences( values[i], types[i] ); 48 } 49 } 50 51 57 private Object nullifyTransientReferences(final Object value, final Type type) 58 throws HibernateException { 59 if ( value == null ) { 60 return null; 61 } 62 else if ( type.isEntityType() ) { 63 EntityType entityType = (EntityType) type; 64 if ( entityType.isOneToOne() ) { 65 return value; 66 } 67 else { 68 String entityName = entityType.getAssociatedEntityName(); 69 return isNullifiable(entityName, value) ? null : value; 70 } 71 } 72 else if ( type.isAnyType() ) { 73 return isNullifiable(null, value) ? null : value; 74 } 75 else if ( type.isComponentType() ) { 76 AbstractComponentType actype = (AbstractComponentType) type; 77 Object [] subvalues = actype.getPropertyValues(value, session); 78 Type[] subtypes = actype.getSubtypes(); 79 boolean substitute = false; 80 for ( int i = 0; i < subvalues.length; i++ ) { 81 Object replacement = nullifyTransientReferences( subvalues[i], subtypes[i] ); 82 if ( replacement != subvalues[i] ) { 83 substitute = true; 84 subvalues[i] = replacement; 85 } 86 } 87 if (substitute) actype.setPropertyValues( value, subvalues, session.getEntityMode() ); 88 return value; 89 } 90 else { 91 return value; 92 } 93 } 94 95 99 private boolean isNullifiable(final String entityName, Object object) 100 throws HibernateException { 101 102 if (object==LazyPropertyInitializer.UNFETCHED_PROPERTY) return false; 104 if ( object instanceof HibernateProxy ) { 105 LazyInitializer li = ( (HibernateProxy) object ).getHibernateLazyInitializer(); 107 if ( li.getImplementation(session) == null ) { 108 return false; 109 } 112 else { 113 object = li.getImplementation(); 115 } 116 } 117 118 if ( object == self ) { 122 return isEarlyInsert || ( 123 isDelete && 124 session.getFactory() 125 .getDialect() 126 .hasSelfReferentialForeignKeyBug() 127 ); 128 } 129 130 135 EntityEntry entityEntry = session.getPersistenceContext().getEntry(object); 136 if ( entityEntry==null ) { 137 return isTransient(entityName, object, null, session); 138 } 139 else { 140 return entityEntry.isNullifiable(isEarlyInsert, session); 141 } 142 143 } 144 145 } 146 147 153 public static boolean isNotTransient(String entityName, Object entity, Boolean assumed, SessionImplementor session) 154 throws HibernateException { 155 if (entity instanceof HibernateProxy) return true; 156 if ( session.getPersistenceContext().isEntryFor(entity) ) return true; 157 return !isTransient(entityName, entity, assumed, session); 158 } 159 160 166 public static boolean isTransient(String entityName, Object entity, Boolean assumed, SessionImplementor session) 167 throws HibernateException { 168 169 if (entity==LazyPropertyInitializer.UNFETCHED_PROPERTY) { 170 return false; 173 } 174 175 Boolean isUnsaved = session.getInterceptor().isTransient(entity); 177 if (isUnsaved!=null) return isUnsaved.booleanValue(); 178 179 EntityPersister persister = session.getEntityPersister(entityName, entity); 181 isUnsaved = persister.isTransient(entity, session); 182 if (isUnsaved!=null) return isUnsaved.booleanValue(); 183 184 if (assumed!=null) return assumed.booleanValue(); 187 188 Object [] snapshot = session.getPersistenceContext() 190 .getDatabaseSnapshot( persister.getIdentifier( entity, session.getEntityMode() ), persister ); 191 return snapshot==null; 192 193 } 194 195 204 public static Serializable getEntityIdentifierIfNotUnsaved( 205 final String entityName, 206 final Object object, 207 final SessionImplementor session) 208 throws HibernateException { 209 if ( object == null ) { 210 return null; 211 } 212 else { 213 Serializable id = session.getContextEntityIdentifier(object); 214 if ( id==null ) { 215 if ( isTransient(entityName, object, Boolean.FALSE, session) ) { 216 throw new TransientObjectException( 217 "object references an unsaved transient instance - save the transient instance before flushing: " + 218 session.guessEntityName(object) 219 ); 220 } 221 id = session.getEntityPersister(entityName, object) 222 .getIdentifier( object, session.getEntityMode() ); 223 } 224 return id; 225 } 226 } 227 228 } 229 | Popular Tags |