use of org.hibernate.engine.spi.PersistenceContext in project hibernate-orm by hibernate.
the class TestAutoFlushBeforeQueryExecution method testAutoflushIsNotRequiredWithUnrelatedCollectionChange.
@Test
public void testAutoflushIsNotRequiredWithUnrelatedCollectionChange() {
Session s = openSession();
Transaction txn = s.beginTransaction();
Publisher publisher = new Publisher();
publisher.setName("name");
s.save(publisher);
assertTrue("autoflush entity create", s.createQuery("from Publisher p").list().size() == 1);
publisher.setName("name");
assertTrue("autoflush entity update", s.createQuery("from Publisher p where p.name='name'").list().size() == 1);
UnrelatedEntity unrelatedEntity = new UnrelatedEntity();
s.save(unrelatedEntity);
txn.commit();
s.close();
s = openSession();
txn = s.beginTransaction();
unrelatedEntity = (UnrelatedEntity) s.get(UnrelatedEntity.class, unrelatedEntity.getId());
publisher = (Publisher) s.get(Publisher.class, publisher.getId());
assertTrue(publisher.getAuthors().isEmpty());
final PersistenceContext persistenceContext = ((SessionImplementor) s).getPersistenceContext();
final ActionQueue actionQueue = ((SessionImpl) s).getActionQueue();
assertEquals(1, persistenceContext.getCollectionEntries().size());
assertEquals(1, persistenceContext.getCollectionsByKey().size());
assertTrue(persistenceContext.getCollectionEntries().containsKey(publisher.getAuthors()));
assertTrue(persistenceContext.getCollectionsByKey().values().contains(publisher.getAuthors()));
assertEquals(0, actionQueue.numberOfCollectionRemovals());
Author author1 = new Author();
author1.setPublisher(publisher);
publisher.getAuthors().add(author1);
assertTrue(s.createQuery("from UnrelatedEntity").list().size() == 1);
assertEquals(2, persistenceContext.getCollectionEntries().size());
assertEquals(1, persistenceContext.getCollectionsByKey().size());
assertTrue(persistenceContext.getCollectionEntries().containsKey(publisher.getAuthors()));
assertTrue(persistenceContext.getCollectionEntries().containsKey(author1.getBooks()));
assertTrue(persistenceContext.getCollectionsByKey().values().contains(publisher.getAuthors()));
assertEquals(0, actionQueue.numberOfCollectionRemovals());
author1.setPublisher(null);
s.delete(author1);
publisher.getAuthors().clear();
assertEquals(0, actionQueue.numberOfCollectionRemovals());
assertTrue(s.createQuery("from UnrelatedEntity").list().size() == 1);
assertEquals(2, persistenceContext.getCollectionEntries().size());
assertEquals(1, persistenceContext.getCollectionsByKey().size());
assertTrue(persistenceContext.getCollectionEntries().containsKey(publisher.getAuthors()));
assertTrue(persistenceContext.getCollectionEntries().containsKey(author1.getBooks()));
assertTrue(persistenceContext.getCollectionsByKey().values().contains(publisher.getAuthors()));
assertEquals(0, actionQueue.numberOfCollectionRemovals());
Set<Author> authorsOld = publisher.getAuthors();
publisher.setAuthors(new HashSet<Author>());
Author author2 = new Author();
author2.setName("author2");
author2.setPublisher(publisher);
publisher.getAuthors().add(author2);
List results = s.createQuery("from UnrelatedEntity").list();
assertEquals(1, results.size());
assertEquals(4, persistenceContext.getCollectionEntries().size());
assertEquals(1, persistenceContext.getCollectionsByKey().size());
assertTrue(persistenceContext.getCollectionEntries().containsKey(publisher.getAuthors()));
assertTrue(persistenceContext.getCollectionEntries().containsKey(author2.getBooks()));
assertTrue(persistenceContext.getCollectionEntries().containsKey(authorsOld));
assertTrue(persistenceContext.getCollectionEntries().containsKey(author1.getBooks()));
assertTrue(persistenceContext.getCollectionsByKey().values().contains(authorsOld));
assertEquals(0, actionQueue.numberOfCollectionRemovals());
s.flush();
assertEquals(2, persistenceContext.getCollectionEntries().size());
assertEquals(2, persistenceContext.getCollectionsByKey().size());
assertTrue(persistenceContext.getCollectionEntries().containsKey(publisher.getAuthors()));
assertTrue(persistenceContext.getCollectionEntries().containsKey(author2.getBooks()));
assertTrue(persistenceContext.getCollectionsByKey().values().contains(publisher.getAuthors()));
assertTrue(persistenceContext.getCollectionsByKey().values().contains(author2.getBooks()));
assertEquals(0, actionQueue.numberOfCollectionRemovals());
s.delete(publisher);
assertTrue("autoflush delete", s.createQuery("from UnrelatedEntity").list().size() == 1);
s.delete(unrelatedEntity);
txn.commit();
s.close();
}
use of org.hibernate.engine.spi.PersistenceContext in project hibernate-orm by hibernate.
the class AbstractCollectionPersister method getSubselectInitializer.
private CollectionInitializer getSubselectInitializer(Serializable key, SharedSessionContractImplementor session) {
if (!isSubselectLoadable()) {
return null;
}
final PersistenceContext persistenceContext = session.getPersistenceContext();
SubselectFetch subselect = persistenceContext.getBatchFetchQueue().getSubselect(session.generateEntityKey(key, getOwnerEntityPersister()));
if (subselect == null) {
return null;
} else {
// Take care of any entities that might have
// been evicted!
Iterator iter = subselect.getResult().iterator();
while (iter.hasNext()) {
if (!persistenceContext.containsEntity((EntityKey) iter.next())) {
iter.remove();
}
}
// Run a subquery loader
return createSubselectInitializer(subselect, session);
}
}
use of org.hibernate.engine.spi.PersistenceContext in project hibernate-orm by hibernate.
the class CollectionReferenceInitializerImpl method finishUpRow.
@Override
public void finishUpRow(ResultSet resultSet, ResultSetProcessingContextImpl context) {
try {
// read the collection key for this reference for the current row.
final PersistenceContext persistenceContext = context.getSession().getPersistenceContext();
final Serializable collectionRowKey = (Serializable) collectionReference.getCollectionPersister().readKey(resultSet, aliases.getCollectionColumnAliases().getSuffixedKeyAliases(), context.getSession());
if (collectionRowKey != null) {
if (log.isDebugEnabled()) {
log.debugf("Found row of collection: %s", MessageHelper.collectionInfoString(collectionReference.getCollectionPersister(), collectionRowKey, context.getSession().getFactory()));
}
Object collectionOwner = findCollectionOwner(collectionRowKey, resultSet, context);
PersistentCollection rowCollection = persistenceContext.getLoadContexts().getCollectionLoadContext(resultSet).getLoadingCollection(collectionReference.getCollectionPersister(), collectionRowKey);
if (rowCollection != null) {
rowCollection.readFrom(resultSet, collectionReference.getCollectionPersister(), aliases.getCollectionColumnAliases(), collectionOwner);
}
} else {
final Serializable optionalKey = findCollectionOwnerKey(context);
if (optionalKey != null) {
// since what we have is an empty collection
if (log.isDebugEnabled()) {
log.debugf("Result set contains (possibly empty) collection: %s", MessageHelper.collectionInfoString(collectionReference.getCollectionPersister(), optionalKey, context.getSession().getFactory()));
}
// handle empty collection
persistenceContext.getLoadContexts().getCollectionLoadContext(resultSet).getLoadingCollection(collectionReference.getCollectionPersister(), optionalKey);
}
}
// else no collection element, but also no owner
} catch (SQLException sqle) {
// TODO: would be nice to have the SQL string that failed...
throw context.getSession().getFactory().getSQLExceptionHelper().convert(sqle, "could not read next row of results");
}
}
use of org.hibernate.engine.spi.PersistenceContext in project hibernate-orm by hibernate.
the class TwoPhaseLoad method postLoad.
/**
* PostLoad cannot occur during initializeEntity, as that call occurs *before*
* the Set collections are added to the persistence context by Loader.
* Without the split, LazyInitializationExceptions can occur in the Entity's
* postLoad if it acts upon the collection.
*
* HHH-6043
*
* @param entity The entity
* @param session The Session
* @param postLoadEvent The (re-used) post-load event
*/
public static void postLoad(final Object entity, final SharedSessionContractImplementor session, final PostLoadEvent postLoadEvent) {
if (session.isEventSource()) {
final PersistenceContext persistenceContext = session.getPersistenceContext();
final EntityEntry entityEntry = persistenceContext.getEntry(entity);
postLoadEvent.setEntity(entity).setId(entityEntry.getId()).setPersister(entityEntry.getPersister());
final EventListenerGroup<PostLoadEventListener> listenerGroup = session.getFactory().getServiceRegistry().getService(EventListenerRegistry.class).getEventListenerGroup(EventType.POST_LOAD);
for (PostLoadEventListener listener : listenerGroup.listeners()) {
listener.onPostLoad(postLoadEvent);
}
}
}
use of org.hibernate.engine.spi.PersistenceContext in project hibernate-orm by hibernate.
the class TwoPhaseLoad method doInitializeEntity.
private static void doInitializeEntity(final Object entity, final EntityEntry entityEntry, final boolean readOnly, final SharedSessionContractImplementor session, final PreLoadEvent preLoadEvent) throws HibernateException {
final PersistenceContext persistenceContext = session.getPersistenceContext();
final EntityPersister persister = entityEntry.getPersister();
final Serializable id = entityEntry.getId();
final Object[] hydratedState = entityEntry.getLoadedState();
final boolean debugEnabled = LOG.isDebugEnabled();
if (debugEnabled) {
LOG.debugf("Resolving associations for %s", MessageHelper.infoString(persister, id, session.getFactory()));
}
String entityName = persister.getEntityName();
String[] propertyNames = persister.getPropertyNames();
final Type[] types = persister.getPropertyTypes();
for (int i = 0; i < hydratedState.length; i++) {
final Object value = hydratedState[i];
Boolean overridingEager = getOverridingEager(session, entityName, propertyNames[i], types[i]);
if (value == LazyPropertyInitializer.UNFETCHED_PROPERTY) {
// No resolution is necessary, unless the lazy property is a collection.
if (types[i].isCollectionType()) {
// IMPLEMENTATION NOTE: this is a lazy collection property on a bytecode-enhanced entity.
// HHH-10989: We need to resolve the collection so that a CollectionReference is added to StatefulPersistentContext.
// As mentioned above, hydratedState[i] needs to remain LazyPropertyInitializer.UNFETCHED_PROPERTY
// so do not assign the resolved, unitialized PersistentCollection back to hydratedState[i].
types[i].resolve(value, session, entity, overridingEager);
}
} else if (value != PropertyAccessStrategyBackRefImpl.UNKNOWN) {
// we know value != LazyPropertyInitializer.UNFETCHED_PROPERTY
hydratedState[i] = types[i].resolve(value, session, entity, overridingEager);
}
}
// Must occur after resolving identifiers!
if (session.isEventSource()) {
preLoadEvent.setEntity(entity).setState(hydratedState).setId(id).setPersister(persister);
final EventListenerGroup<PreLoadEventListener> listenerGroup = session.getFactory().getServiceRegistry().getService(EventListenerRegistry.class).getEventListenerGroup(EventType.PRE_LOAD);
for (PreLoadEventListener listener : listenerGroup.listeners()) {
listener.onPreLoad(preLoadEvent);
}
}
persister.setPropertyValues(entity, hydratedState);
final SessionFactoryImplementor factory = session.getFactory();
if (persister.canWriteToCache() && session.getCacheMode().isPutEnabled()) {
if (debugEnabled) {
LOG.debugf("Adding entity to second-level cache: %s", MessageHelper.infoString(persister, id, session.getFactory()));
}
final Object version = Versioning.getVersion(hydratedState, persister);
final CacheEntry entry = persister.buildCacheEntry(entity, hydratedState, version, session);
final EntityDataAccess cache = persister.getCacheAccessStrategy();
final Object cacheKey = cache.generateCacheKey(id, persister, factory, session.getTenantIdentifier());
// we need to be careful not to clobber the lock here in the cache so that it can be rolled back if need be
if (session.getPersistenceContext().wasInsertedDuringTransaction(persister, id)) {
cache.update(session, cacheKey, persister.getCacheEntryStructure().structure(entry), version, version);
} else {
final SessionEventListenerManager eventListenerManager = session.getEventListenerManager();
try {
eventListenerManager.cachePutStart();
final boolean put = cache.putFromLoad(session, cacheKey, persister.getCacheEntryStructure().structure(entry), version, useMinimalPuts(session, entityEntry));
if (put && factory.getStatistics().isStatisticsEnabled()) {
factory.getStatistics().entityCachePut(StatsHelper.INSTANCE.getRootEntityRole(persister), cache.getRegion().getName());
}
} finally {
eventListenerManager.cachePutEnd();
}
}
}
if (persister.hasNaturalIdentifier()) {
persistenceContext.getNaturalIdHelper().cacheNaturalIdCrossReferenceFromLoad(persister, id, persistenceContext.getNaturalIdHelper().extractNaturalIdValues(hydratedState, persister));
}
boolean isReallyReadOnly = readOnly;
if (!persister.isMutable()) {
isReallyReadOnly = true;
} else {
final Object proxy = persistenceContext.getProxy(entityEntry.getEntityKey());
if (proxy != null) {
// there is already a proxy for this impl
// only set the status to read-only if the proxy is read-only
isReallyReadOnly = ((HibernateProxy) proxy).getHibernateLazyInitializer().isReadOnly();
}
}
if (isReallyReadOnly) {
// no need to take a snapshot - this is a
// performance optimization, but not really
// important, except for entities with huge
// mutable property values
persistenceContext.setEntryStatus(entityEntry, Status.READ_ONLY);
} else {
// take a snapshot
TypeHelper.deepCopy(hydratedState, persister.getPropertyTypes(), persister.getPropertyUpdateability(), // after setting values to object
hydratedState, session);
persistenceContext.setEntryStatus(entityEntry, Status.MANAGED);
}
persister.afterInitialize(entity, session);
if (debugEnabled) {
LOG.debugf("Done materializing entity %s", MessageHelper.infoString(persister, id, session.getFactory()));
}
if (factory.getStatistics().isStatisticsEnabled()) {
factory.getStatistics().loadEntity(persister.getEntityName());
}
}
Aggregations