/** Convience method to retreive an entities next version value */ private Object getNextVersion(FlushEntityEvent event) throws HibernateException { EntityEntry entry = event.getEntityEntry(); EntityPersister persister = entry.getPersister(); if (persister.isVersioned()) { Object[] values = event.getPropertyValues(); if (entry.isBeingReplicated()) { return Versioning.getVersion(values, persister); } else { int[] dirtyProperties = event.getDirtyProperties(); final boolean isVersionIncrementRequired = isVersionIncrementRequired(event, entry, persister, dirtyProperties); final Object nextVersion = isVersionIncrementRequired ? Versioning.increment( entry.getVersion(), persister.getVersionType(), event.getSession()) : entry.getVersion(); // use the current version Versioning.setVersion(values, nextVersion, persister); return nextVersion; } } else { return null; } }
FromElement addFromElement() throws SemanticException { FromClause parentFromClause = fromClause.getParentFromClause(); if (parentFromClause != null) { // Look up class name using the first identifier in the path. String pathAlias = PathHelper.getAlias(path); FromElement parentFromElement = parentFromClause.getFromElement(pathAlias); if (parentFromElement != null) { return createFromElementInSubselect(path, pathAlias, parentFromElement, classAlias); } } EntityPersister entityPersister = fromClause.getSessionFactoryHelper().requireClassPersister(path); FromElement elem = createAndAddFromElement( path, classAlias, entityPersister, (EntityType) ((Queryable) entityPersister).getType(), null); // Add to the query spaces. fromClause.getWalker().addQuerySpaces(entityPersister.getQuerySpaces()); return elem; }
/** * Flushes a single entity's state to the database, by scheduling an update action, if necessary */ public void onFlushEntity(FlushEntityEvent event) throws HibernateException { final Object entity = event.getEntity(); final EntityEntry entry = event.getEntityEntry(); final EventSource session = event.getSession(); final EntityPersister persister = entry.getPersister(); final Status status = entry.getStatus(); final EntityMode entityMode = session.getEntityMode(); final Type[] types = persister.getPropertyTypes(); final boolean mightBeDirty = entry.requiresDirtyCheck(entity); final Object[] values = getValues(entity, entry, entityMode, mightBeDirty, session); event.setPropertyValues(values); // TODO: avoid this for non-new instances where mightBeDirty==false boolean substitute = wrapCollections(session, persister, types, values); if (isUpdateNecessary(event, mightBeDirty)) { substitute = scheduleUpdate(event) || substitute; } if (status != Status.DELETED) { // now update the object .. has to be outside the main if block above (because of collections) if (substitute) persister.setPropertyValues(entity, values, entityMode); // Search for collections by reachability, updating their role. // We don't want to touch collections reachable from a deleted object if (persister.hasCollections()) { new FlushVisitor(session, entity).processEntityPropertyValues(values, types); } } }
private void checkNaturalId( EntityPersister persister, EntityEntry entry, Object[] current, Object[] loaded, EntityMode entityMode, SessionImplementor session) { if (persister.hasNaturalIdentifier() && entry.getStatus() != Status.READ_ONLY) { Object[] snapshot = null; Type[] types = persister.getPropertyTypes(); int[] props = persister.getNaturalIdentifierProperties(); boolean[] updateable = persister.getPropertyUpdateability(); for (int i = 0; i < props.length; i++) { int prop = props[i]; if (!updateable[prop]) { Object loadedVal; if (loaded == null) { if (snapshot == null) { snapshot = session.getPersistenceContext().getNaturalIdSnapshot(entry.getId(), persister); } loadedVal = snapshot[i]; } else { loadedVal = loaded[prop]; } if (!types[prop].isEqual(current[prop], loadedVal, entityMode)) { throw new HibernateException( "immutable natural identifier of an instance of " + persister.getEntityName() + " was altered"); } } } } }
public void noCascade( EventSource session, Object child, Object parent, EntityPersister persister, int propertyIndex) { if (child == null) { return; } Type type = persister.getPropertyTypes()[propertyIndex]; if (type.isEntityType()) { String childEntityName = ((EntityType) type).getAssociatedEntityName(session.getFactory()); if (!isInManagedState(child, session) && !(child instanceof HibernateProxy) // a proxy cannot be transient and it breaks // ForeignKeys.isTransient && ForeignKeys.isTransient(childEntityName, child, null, session)) { String parentEntiytName = persister.getEntityName(); String propertyName = persister.getPropertyNames()[propertyIndex]; throw new TransientObjectException( "object references an unsaved transient instance - " + "save the transient instance before flushing: " + parentEntiytName + "." + propertyName + " -> " + childEntityName); } } }
public Object[] getNaturalIdSnapshot(Serializable id, EntityPersister persister) throws HibernateException { if (!persister.hasNaturalIdentifier()) { return null; } // if the natural-id is marked as non-mutable, it is not retrieved during a // normal database-snapshot operation... int[] props = persister.getNaturalIdentifierProperties(); boolean[] updateable = persister.getPropertyUpdateability(); boolean allNatualIdPropsAreUpdateable = true; for (int i = 0; i < props.length; i++) { if (!updateable[props[i]]) { allNatualIdPropsAreUpdateable = false; break; } } if (allNatualIdPropsAreUpdateable) { // do this when all the properties are updateable since there is // a certain likelihood that the information will already be // snapshot-cached. Object[] entitySnapshot = getDatabaseSnapshot(id, persister); if (entitySnapshot == NO_ROW) { return null; } Object[] naturalIdSnapshot = new Object[props.length]; for (int i = 0; i < props.length; i++) { naturalIdSnapshot[i] = entitySnapshot[props[i]]; } return naturalIdSnapshot; } else { return persister.getNaturalIdentifierSnapshot(id, session); } }
/** * If the existing proxy is insufficiently "narrow" (derived), instantiate a new proxy and * overwrite the registration of the old one. This breaks == and occurs only for "class" proxies * rather than "interface" proxies. Also init the proxy to point to the given target * implementation if necessary. * * @param proxy The proxy instance to be narrowed. * @param persister The persister for the proxied entity. * @param key The internal cache key for the proxied entity. * @param object (optional) the actual proxied entity instance. * @return An appropriately narrowed instance. * @throws HibernateException */ public Object narrowProxy(Object proxy, EntityPersister persister, EntityKey key, Object object) throws HibernateException { boolean alreadyNarrow = persister.getConcreteProxyClass(session.getEntityMode()).isAssignableFrom(proxy.getClass()); if (!alreadyNarrow) { if (PROXY_WARN_LOG.isWarnEnabled()) { PROXY_WARN_LOG.warn( "Narrowing proxy to " + persister.getConcreteProxyClass(session.getEntityMode()) + " - this operation breaks =="); } if (object != null) { proxiesByKey.remove(key); return object; // return the proxied object } else { proxy = persister.createProxy(key.getIdentifier(), session); proxiesByKey.put(key, proxy); // overwrite old proxy return proxy; } } else { if (object != null) { LazyInitializer li = ((HibernateProxy) proxy).getHibernateLazyInitializer(); li.setImplementation(object); } return proxy; } }
/** * Search the persistence context for an owner for the child object, given a collection role. If * <tt>mergeMap</tt> is non-null, also check the detached graph being merged for a parent. */ public Serializable getOwnerId(String entity, String property, Object childEntity, Map mergeMap) { EntityPersister persister = session.getFactory().getEntityPersister(entity); final CollectionPersister collectionPersister = session.getFactory().getCollectionPersister(entity + '.' + property); Iterator entities = entityEntries.entrySet().iterator(); while (entities.hasNext()) { Map.Entry me = (Map.Entry) entities.next(); EntityEntry ee = (EntityEntry) me.getValue(); if (persister.isSubclassEntityName(ee.getEntityName())) { Object instance = me.getKey(); // check if the managed object is the parent boolean found = isFoundInParent(property, childEntity, persister, collectionPersister, instance); if (!found && mergeMap != null) { // check if the detached object being merged is the parent Object unmergedInstance = mergeMap.get(instance); Object unmergedChild = mergeMap.get(childEntity); if (unmergedInstance != null && unmergedChild != null) { found = isFoundInParent( property, unmergedChild, persister, collectionPersister, unmergedInstance); } } if (found) { return ee.getId(); } } } return null; }
@SuppressWarnings("unchecked") @Override /** * Handle the given delete event. This is the cascaded form. * * @param event The delete event. * @param transientEntities The cache of entities already deleted * @throws HibernateException */ public void onDelete(DeleteEvent event, Set transientEntities) throws HibernateException { final EventSource source = event.getSession(); final PersistenceContext persistenceContext = source.getPersistenceContext(); Object entity = persistenceContext.unproxyAndReassociate(event.getObject()); EntityEntry entityEntry = persistenceContext.getEntry(entity); final EntityPersister persister = source.getEntityPersister(event.getEntityName(), entity); final Object version; if (persister.isVersioned()) { version = persister.getVersion(entity, source.getEntityMode()); // Make sure version has not changed on deleted entities if ((entity instanceof TimelineEntity) && !((TimelineEntity) entity).isNew()) { if (!persister.getVersionType().isEqual(version, entityEntry.getVersion())) { throw new StaleObjectStateException(persister.getEntityName(), entityEntry.getId()); } } } super.onDelete(event, transientEntities); }
/** make sure user didn't mangle the id */ public void checkId( Object object, EntityPersister persister, Serializable id, EntityMode entityMode, SessionImplementor session) throws HibernateException { if (id != null && id instanceof DelayedPostInsertIdentifier) { // this is a situation where the entity id is assigned by a post-insert generator // and was saved outside the transaction forcing it to be delayed return; } if (persister.canExtractIdOutOfEntity()) { Serializable oid = persister.getIdentifier(object, session); if (id == null) { throw new AssertionFailure( "null id in " + persister.getEntityName() + " entry (don't flush the Session after an exception occurs)"); } if (!persister.getIdentifierType().isEqual(id, oid, entityMode, session.getFactory())) { throw new HibernateException( "identifier of an instance of " + persister.getEntityName() + " was altered from " + id + " to " + oid); } } }
/** * Register the "hydrated" state of an entity instance, after the first step of 2-phase loading. * * <p>Add the "hydrated state" (an array) of an uninitialized entity to the session. We don't try * to resolve any associations yet, because there might be other entities waiting to be read from * the JDBC result set we are currently processing */ public static void postHydrate( final EntityPersister persister, final Serializable id, final Object[] values, final Object rowId, final Object object, final LockMode lockMode, final boolean lazyPropertiesAreUnfetched, final SessionImplementor session) throws HibernateException { Object version = Versioning.getVersion(values, persister); session .getPersistenceContext() .addEntry( object, Status.LOADING, values, rowId, id, version, lockMode, true, persister, false, lazyPropertiesAreUnfetched); if (log.isTraceEnabled() && version != null) { String versionStr = persister.isVersioned() ? persister.getVersionType().toLoggableString(version, session.getFactory()) : "null"; log.trace("Version: " + versionStr); } }
/** * Handle the given lock event. * * @param event The lock event to be handled. * @throws HibernateException */ public void onLock(LockEvent event) throws HibernateException { if (event.getObject() == null) { throw new NullPointerException("attempted to lock null"); } if (event.getLockMode() == LockMode.WRITE) { throw new HibernateException("Invalid lock mode for lock()"); } SessionImplementor source = event.getSession(); Object entity = source.getPersistenceContext().unproxyAndReassociate(event.getObject()); // TODO: if object was an uninitialized proxy, this is inefficient, // resulting in two SQL selects EntityEntry entry = source.getPersistenceContext().getEntry(entity); if (entry == null) { final EntityPersister persister = source.getEntityPersister(event.getEntityName(), entity); final Serializable id = persister.getIdentifier(entity, source.getEntityMode()); if (!ForeignKeys.isNotTransient(event.getEntityName(), entity, Boolean.FALSE, source)) { throw new TransientObjectException( "cannot lock an unsaved transient instance: " + persister.getEntityName()); } entry = reassociate(event, entity, id, persister); cascadeOnLock(event, persister, entity); } upgradeLock(entity, entry, event.getLockMode(), source); }
public void forceLocked(Object entity, Object nextVersion) { version = nextVersion; loadedState[persister.getVersionProperty()] = version; //noinspection deprecation setLockMode(LockMode.FORCE); // TODO: use LockMode.PESSIMISTIC_FORCE_INCREMENT persister.setPropertyValue(entity, getPersister().getVersionProperty(), nextVersion); }
@Override public void doAfterTransactionCompletion(boolean success, SessionImplementor session) throws CacheException { final EntityPersister persister = getPersister(); if (persister.hasCache()) { final EntityRegionAccessStrategy cache = persister.getCacheAccessStrategy(); final Object ck = cache.generateCacheKey( getId(), persister, session.getFactory(), session.getTenantIdentifier()); if (success && cacheEntry != null /*!persister.isCacheInvalidationRequired()*/) { final boolean put = cacheAfterUpdate(cache, ck); if (put && getSession().getFactory().getStatistics().isStatisticsEnabled()) { getSession() .getFactory() .getStatisticsImplementor() .secondLevelCachePut(cache.getRegion().getName()); } } else { cache.unlockItem(session, ck, lock); } } postCommitUpdate(success); }
/** * Prepares the save call using a newly generated id. * * @param entity The entity to be saved * @param entityName The entity-name for the entity to be saved * @param anything Generally cascade-specific information. * @param source The session which is the source of this save event. * @param requiresImmediateIdAccess does the event context require access to the identifier * immediately after execution of this method (if not, post-insert style id generators may be * postponed if we are outside a transaction). * @return The id used to save the entity; may be null depending on the type of id generator used * and the requiresImmediateIdAccess value */ protected Serializable saveWithGeneratedId( Object entity, String entityName, Object anything, EventSource source, boolean requiresImmediateIdAccess) { EntityPersister persister = source.getEntityPersister(entityName, entity); Serializable generatedId = persister.getIdentifierGenerator().generate(source, entity); if (generatedId == null) { throw new IdentifierGenerationException("null id generated for:" + entity.getClass()); } else if (generatedId == IdentifierGeneratorHelper.SHORT_CIRCUIT_INDICATOR) { return source.getIdentifier(entity); } else if (generatedId == IdentifierGeneratorHelper.POST_INSERT_INDICATOR) { return performSave( entity, null, persister, true, anything, source, requiresImmediateIdAccess); } else { // TODO: define toString()s for generators if (LOG.isDebugEnabled()) { LOG.debugf( "Generated identifier: %s, using strategy: %s", persister.getIdentifierType().toLoggableString(generatedId, source.getFactory()), persister.getIdentifierGenerator().getClass().getName()); } return performSave(entity, generatedId, persister, false, anything, source, true); } }
/** Search the persistence context for an index of the child object, given a collection role */ public Object getIndexInOwner(String entity, String property, Object childEntity, Map mergeMap) { EntityPersister persister = session.getFactory().getEntityPersister(entity); CollectionPersister cp = session.getFactory().getCollectionPersister(entity + '.' + property); Iterator entities = entityEntries.entrySet().iterator(); while (entities.hasNext()) { Map.Entry me = (Map.Entry) entities.next(); EntityEntry ee = (EntityEntry) me.getValue(); if (persister.isSubclassEntityName(ee.getEntityName())) { Object instance = me.getKey(); Object index = getIndexInParent(property, childEntity, persister, cp, instance); if (index == null && mergeMap != null) { Object unmergedInstance = mergeMap.get(instance); Object unmergedChild = mergeMap.get(childEntity); if (unmergedInstance != null && unmergedChild != null) { index = getIndexInParent(property, unmergedChild, persister, cp, unmergedInstance); } } if (index != null) return index; } } return null; }
private Object[] getValues( Object entity, EntityEntry entry, EntityMode entityMode, boolean mightBeDirty, SessionImplementor session) { final Object[] loadedState = entry.getLoadedState(); final Status status = entry.getStatus(); final EntityPersister persister = entry.getPersister(); final Object[] values; if (status == Status.DELETED) { // grab its state saved at deletion values = entry.getDeletedState(); } else if (!mightBeDirty && loadedState != null) { values = loadedState; } else { checkId(entity, persister, entry.getId(), entityMode, session); // grab its current state values = persister.getPropertyValues(entity, entityMode); checkNaturalId(persister, entry, values, loadedState, entityMode, session); } return values; }
private CacheKey buildCacheKey(Serializable identifier, EntityPersister p) { return new CacheKey( identifier, p.getIdentifierType(), p.getRootEntityName(), EntityMode.POJO, SessionFactoryImpl.this); }
public void evictEntityRegion(String entityName) { EntityPersister p = getEntityPersister(entityName); if (p.hasCache()) { if (log.isDebugEnabled()) { log.debug("evicting second-level cache: " + p.getEntityName()); } p.getCacheAccessStrategy().evictAll(); } }
FromElement createElementJoin(QueryableCollection queryableCollection) throws SemanticException { FromElement elem; implied = true; // TODO: always true for now, but not if we later decide to support elements() in the // from clause inElementsFunction = true; Type elementType = queryableCollection.getElementType(); if (!elementType.isEntityType()) { throw new IllegalArgumentException( "Cannot create element join for a collection of non-entities!"); } this.queryableCollection = queryableCollection; SessionFactoryHelper sfh = fromClause.getSessionFactoryHelper(); FromElement destination = null; String tableAlias = null; EntityPersister entityPersister = queryableCollection.getElementPersister(); tableAlias = fromClause.getAliasGenerator().createName(entityPersister.getEntityName()); String associatedEntityName = entityPersister.getEntityName(); EntityPersister targetEntityPersister = sfh.requireClassPersister(associatedEntityName); // Create the FROM element for the target (the elements of the collection). destination = createAndAddFromElement( associatedEntityName, classAlias, targetEntityPersister, (EntityType) queryableCollection.getElementType(), tableAlias); // If the join is implied, then don't include sub-classes on the element. if (implied) { destination.setIncludeSubclasses(false); } fromClause.addCollectionJoinFromElementByPath(path, destination); // origin.addDestination(destination); // Add the query spaces. fromClause.getWalker().addQuerySpaces(entityPersister.getQuerySpaces()); CollectionType type = queryableCollection.getCollectionType(); String role = type.getRole(); String roleAlias = origin.getTableAlias(); String[] targetColumns = sfh.getCollectionElementColumns(role, roleAlias); AssociationType elementAssociationType = sfh.getElementAssociationType(type); // Create the join element under the from element. int joinType = JoinFragment.INNER_JOIN; JoinSequence joinSequence = sfh.createJoinSequence( implied, elementAssociationType, tableAlias, joinType, targetColumns); elem = initializeJoin(path, destination, joinSequence, targetColumns, origin, false); elem.setUseFromFragment( true); // The associated entity is implied, but it must be included in the FROM. elem.setCollectionTableAlias(roleAlias); // The collection alias is the role. return elem; }
/** * Reads the entity hosting the association from the datastore and applies any property changes * from the server side. */ private void updateHostingEntityIfRequired() { if (hostingEntity != null && hostingEntityRequiresReadAfterUpdate()) { EntityPersister entityPersister = getHostingEntityPersister(); entityPersister.processUpdateGeneratedProperties( entityPersister.getIdentifier(hostingEntity, session), hostingEntity, new Object[entityPersister.getPropertyNames().length], session); } }
private void registerEntityNameResolvers(EntityPersister persister) { if (persister.getEntityMetamodel() == null || persister.getEntityMetamodel().getTuplizerMapping() == null) { return; } Iterator itr = persister.getEntityMetamodel().getTuplizerMapping().iterateTuplizers(); while (itr.hasNext()) { final EntityTuplizer tuplizer = (EntityTuplizer) itr.next(); registerEntityNameResolvers(tuplizer); } }
public void evictEntity(String entityName, Serializable identifier) { EntityPersister p = getEntityPersister(entityName); if (p.hasCache()) { if (log.isDebugEnabled()) { log.debug( "evicting second-level cache: " + MessageHelper.infoString(p, identifier, SessionFactoryImpl.this)); } p.getCacheAccessStrategy().evict(buildCacheKey(identifier, p)); } }
/** * Closes the session factory, releasing all held resources. * * <ol> * <li>cleans up used cache regions and "stops" the cache provider. * <li>close the JDBC connection * <li>remove the JNDI binding * </ol> * * Note: Be aware that the sessionfactory instance still can be a "heavy" object memory wise after * close() has been called. Thus it is important to not keep referencing the instance to let the * garbage collector release the memory. */ public void close() throws HibernateException { if (isClosed) { log.trace("already closed"); return; } log.info("closing"); isClosed = true; Iterator iter = entityPersisters.values().iterator(); while (iter.hasNext()) { EntityPersister p = (EntityPersister) iter.next(); if (p.hasCache()) { p.getCacheAccessStrategy().getRegion().destroy(); } } iter = collectionPersisters.values().iterator(); while (iter.hasNext()) { CollectionPersister p = (CollectionPersister) iter.next(); if (p.hasCache()) { p.getCacheAccessStrategy().getRegion().destroy(); } } if (settings.isQueryCacheEnabled()) { queryCache.destroy(); iter = queryCaches.values().iterator(); while (iter.hasNext()) { QueryCache cache = (QueryCache) iter.next(); cache.destroy(); } updateTimestampsCache.destroy(); } settings.getRegionFactory().stop(); if (settings.isAutoDropSchema()) { schemaExport.drop(false, true); } try { settings.getConnectionProvider().close(); } finally { SessionFactoryObjectFactory.removeInstance(uuid, name, properties); } observer.sessionFactoryClosed(this); eventListeners.destroyListeners(); }
@Test @FailureExpectedWithNewMetamodel public void testHibernateSequenceSchema() { EntityPersister persister = sessionFactory().getEntityPersister(HibernateSequenceEntity.class.getName()); IdentifierGenerator generator = persister.getIdentifierGenerator(); Assert.assertTrue(SequenceStyleGenerator.class.isInstance(generator)); SequenceStyleGenerator seqGenerator = (SequenceStyleGenerator) generator; Assert.assertEquals( Table.qualify(null, SCHEMA_NAME, SequenceStyleGenerator.DEF_SEQUENCE_NAME), seqGenerator.getDatabaseStructure().getName()); }
private void synchronizePersisterState(Object entity, EntityPersister persister, Object[] state) { String[] propertyNames = persister.getPropertyNames(); for (int i = 0; i < propertyNames.length; i++) { String p = propertyNames[i]; MetaProperty metaProperty = domainMetaClass.getMetaProperty(p); if (ClosureEventTriggeringInterceptor.IGNORED.contains(p) || metaProperty == null) { continue; } Object value = metaProperty.getProperty(entity); state[i] = value; persister.setPropertyValue(entity, i, value); } }
public FromElement createEntityJoin( String entityClass, String tableAlias, JoinSequence joinSequence, boolean fetchFlag, boolean inFrom, EntityType type, String role, String joinPath) throws SemanticException { FromElement elem = createJoin(entityClass, tableAlias, joinSequence, type, false); elem.setFetch(fetchFlag); if (joinPath != null) { elem.applyTreatAsDeclarations(fromClause.getWalker().getTreatAsDeclarationsByPath(joinPath)); } EntityPersister entityPersister = elem.getEntityPersister(); int numberOfTables = entityPersister.getQuerySpaces().length; if (numberOfTables > 1 && implied && !elem.useFromFragment()) { LOG.debug("createEntityJoin() : Implied multi-table entity join"); elem.setUseFromFragment(true); } // If this is an implied join in a FROM clause, then use ANSI-style joining, and set the // flag on the FromElement that indicates that it was implied in the FROM clause itself. if (implied && inFrom) { joinSequence.setUseThetaStyle(false); elem.setUseFromFragment(true); elem.setImpliedInFromClause(true); } if (elem.getWalker().isSubQuery()) { // two conditions where we need to transform this to a theta-join syntax: // 1) 'elem' is the "root from-element" in correlated subqueries // 2) The DotNode.useThetaStyleImplicitJoins has been set to true // and 'elem' represents an implicit join if (elem.getFromClause() != elem.getOrigin().getFromClause() || // ( implied && DotNode.useThetaStyleImplicitJoins ) ) { PathSeparatorNode.useThetaStyleImplicitJoins) { // the "root from-element" in correlated subqueries do need this piece elem.setType(FROM_FRAGMENT); joinSequence.setUseThetaStyle(true); elem.setUseFromFragment(false); } } elem.setRole(role); return elem; }
/** * Construct a new key for a caching natural identifier resolutions into the second level cache. * Note that an entity name should always be the root entity name, not a subclass entity name. * * @param naturalIdValues The naturalIdValues associated with the cached data * @param persister The persister for the entity * @param session The originating session */ public NaturalIdCacheKey( final Object[] naturalIdValues, final EntityPersister persister, final SessionImplementor session) { this.entityName = persister.getRootEntityName(); this.tenantId = session.getTenantIdentifier(); this.naturalIdValues = new Serializable[naturalIdValues.length]; final SessionFactoryImplementor factory = session.getFactory(); final int[] naturalIdPropertyIndexes = persister.getNaturalIdentifierProperties(); final Type[] propertyTypes = persister.getPropertyTypes(); final int prime = 31; int result = 1; result = prime * result + ((this.entityName == null) ? 0 : this.entityName.hashCode()); result = prime * result + ((this.tenantId == null) ? 0 : this.tenantId.hashCode()); for (int i = 0; i < naturalIdValues.length; i++) { final Type type = propertyTypes[naturalIdPropertyIndexes[i]]; final Object value = naturalIdValues[i]; result = prime * result + (value != null ? type.getHashCode(value, factory) : 0); this.naturalIdValues[i] = type.disassemble(value, session, null); } this.hashCode = result; this.toString = new ValueHolder<String>( new ValueHolder.DeferredInitializer<String>() { @Override public String initialize() { // Complex toString is needed as naturalIds for entities are not simply based on a // single value like primary keys // the only same way to differentiate the keys is to included the disassembled // values in the string. final StringBuilder toStringBuilder = new StringBuilder(entityName).append("##NaturalId["); for (int i = 0; i < naturalIdValues.length; i++) { toStringBuilder.append(naturalIdValues[i]); if (i + 1 < naturalIdValues.length) { toStringBuilder.append(", "); } } toStringBuilder.append("]"); return toStringBuilder.toString(); } }); }
private boolean hasDirtyCollections( FlushEntityEvent event, EntityPersister persister, Status status) { if (isCollectionDirtyCheckNecessary(persister, status)) { DirtyCollectionSearchVisitor visitor = new DirtyCollectionSearchVisitor( event.getSession(), persister.getPropertyVersionability()); visitor.processEntityPropertyValues(event.getPropertyValues(), persister.getPropertyTypes()); boolean hasDirtyCollections = visitor.wasDirtyCollectionFound(); event.setHasDirtyCollection(hasDirtyCollections); return hasDirtyCollections; } else { return false; } }
/** * Returns all the persistent id generators which potentially require the creation of an object in * the schema. */ private Iterable<PersistentNoSqlIdentifierGenerator> getPersistentGenerators() { Map<String, EntityPersister> entityPersisters = factory.getEntityPersisters(); Set<PersistentNoSqlIdentifierGenerator> persistentGenerators = new HashSet<PersistentNoSqlIdentifierGenerator>(entityPersisters.size()); for (EntityPersister persister : entityPersisters.values()) { if (persister.getIdentifierGenerator() instanceof PersistentNoSqlIdentifierGenerator) { persistentGenerators.add( (PersistentNoSqlIdentifierGenerator) persister.getIdentifierGenerator()); } } return persistentGenerators; }