use of org.hibernate.cache.spi.access.EntityDataAccess in project hibernate-orm by hibernate.
the class AbstractEntityPersister method isTransient.
public Boolean isTransient(Object entity, SharedSessionContractImplementor session) throws HibernateException {
final Serializable id;
if (canExtractIdOutOfEntity()) {
id = getIdentifier(entity, session);
} else {
id = null;
}
// identifier or no identifier property is unsaved!
if (id == null) {
return Boolean.TRUE;
}
// check the version unsaved-value, if appropriate
final Object version = getVersion(entity);
if (isVersioned()) {
// let this take precedence if defined, since it works for
// assigned identifiers
Boolean result = entityMetamodel.getVersionProperty().getUnsavedValue().isUnsaved(version);
if (result != null) {
return result;
}
}
// check the id unsaved-value
Boolean result = entityMetamodel.getIdentifierProperty().getUnsavedValue().isUnsaved(id);
if (result != null) {
return result;
}
// check to see if it is in the second-level cache
if (session.getCacheMode().isGetEnabled() && canReadFromCache()) {
final EntityDataAccess cache = getCacheAccessStrategy();
final Object ck = cache.generateCacheKey(id, this, session.getFactory(), session.getTenantIdentifier());
final Object ce = CacheHelper.fromSharedCache(session, ck, getCacheAccessStrategy());
if (ce != null) {
return Boolean.FALSE;
}
}
return null;
}
use of org.hibernate.cache.spi.access.EntityDataAccess in project hibernate-orm by hibernate.
the class BasicStructuredCachingOfConvertedValueTest method basicCacheStructureTest.
@Test
@TestForIssue(jiraKey = "HHH-9615")
@SuppressWarnings("unchecked")
public void basicCacheStructureTest() {
EntityPersister persister = sessionFactory().getMetamodel().entityPersisters().get(Address.class.getName());
DomainDataRegion region = persister.getCacheAccessStrategy().getRegion();
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// test during store...
PostalAreaConverter.clearCounts();
Session session = openSession();
session.getTransaction().begin();
session.save(new Address(1, "123 Main St.", null, PostalArea._78729));
session.getTransaction().commit();
session.close();
{
inSession(s -> {
final EntityDataAccess entityDataAccess = region.getEntityDataAccess(persister.getNavigableRole());
final Object cacheKey = entityDataAccess.generateCacheKey(1, persister, sessionFactory(), null);
final Object cachedItem = entityDataAccess.get(s, cacheKey);
final Map<String, ?> state = (Map) cachedItem;
// this is the point of the Jira.. that this "should be" the converted value
assertThat(state.get("postalArea"), instanceOf(PostalArea.class));
});
}
assertThat(PostalAreaConverter.toDatabaseCallCount, is(1));
assertThat(PostalAreaConverter.toDomainCallCount, is(0));
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// test during load...
PostalAreaConverter.clearCounts();
sessionFactory().getCache().evictAll();
session = openSession();
session.getTransaction().begin();
Address address = session.get(Address.class, 1);
session.getTransaction().commit();
session.close();
{
inSession(s -> {
final EntityDataAccess entityDataAccess = region.getEntityDataAccess(persister.getNavigableRole());
final Object cacheKey = entityDataAccess.generateCacheKey(1, persister, sessionFactory(), null);
final Object cachedItem = entityDataAccess.get(s, cacheKey);
final Map<String, ?> state = (Map) cachedItem;
// this is the point of the Jira.. that this "should be" the converted value
assertThat(state.get("postalArea"), instanceOf(PostalArea.class));
});
}
assertThat(PostalAreaConverter.toDatabaseCallCount, is(0));
assertThat(PostalAreaConverter.toDomainCallCount, is(1));
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// cleanup
session = openSession();
session.getTransaction().begin();
session.delete(address);
session.getTransaction().commit();
session.close();
}
use of org.hibernate.cache.spi.access.EntityDataAccess 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());
}
}
use of org.hibernate.cache.spi.access.EntityDataAccess in project hibernate-orm by hibernate.
the class EntityDeleteAction method execute.
@Override
public void execute() throws HibernateException {
final Serializable id = getId();
final EntityPersister persister = getPersister();
final SharedSessionContractImplementor session = getSession();
final Object instance = getInstance();
final boolean veto = preDelete();
Object version = this.version;
if (persister.isVersionPropertyGenerated()) {
// we need to grab the version value from the entity, otherwise
// we have issues with generated-version entities that may have
// multiple actions queued during the same flush
version = persister.getVersion(instance);
}
final Object ck;
if (persister.canWriteToCache()) {
final EntityDataAccess cache = persister.getCacheAccessStrategy();
ck = cache.generateCacheKey(id, persister, session.getFactory(), session.getTenantIdentifier());
lock = cache.lockItem(session, ck, version);
} else {
ck = null;
}
if (!isCascadeDeleteEnabled && !veto) {
persister.delete(id, version, instance, session);
}
// postDelete:
// After actually deleting a row, record the fact that the instance no longer
// exists on the database (needed for identity-column key generation), and
// remove it from the session cache
final PersistenceContext persistenceContext = session.getPersistenceContext();
final EntityEntry entry = persistenceContext.removeEntry(instance);
if (entry == null) {
throw new AssertionFailure("possible nonthreadsafe access to session");
}
entry.postDelete();
persistenceContext.removeEntity(entry.getEntityKey());
persistenceContext.removeProxy(entry.getEntityKey());
if (persister.canWriteToCache()) {
persister.getCacheAccessStrategy().remove(session, ck);
}
persistenceContext.getNaturalIdHelper().removeSharedNaturalIdCrossReference(persister, id, naturalIdValues);
postDelete();
if (getSession().getFactory().getStatistics().isStatisticsEnabled() && !veto) {
getSession().getFactory().getStatistics().deleteEntity(getPersister().getEntityName());
}
}
use of org.hibernate.cache.spi.access.EntityDataAccess in project hibernate-orm by hibernate.
the class EntityInsertAction method execute.
@Override
public void execute() throws HibernateException {
nullifyTransientReferencesIfNotAlready();
final EntityPersister persister = getPersister();
final SharedSessionContractImplementor session = getSession();
final Object instance = getInstance();
final Serializable id = getId();
final boolean veto = preInsert();
if (!veto) {
persister.insert(id, getState(), instance, session);
PersistenceContext persistenceContext = session.getPersistenceContext();
final EntityEntry entry = persistenceContext.getEntry(instance);
if (entry == null) {
throw new AssertionFailure("possible non-threadsafe access to session");
}
entry.postInsert(getState());
if (persister.hasInsertGeneratedProperties()) {
persister.processInsertGeneratedProperties(id, instance, getState(), session);
if (persister.isVersionPropertyGenerated()) {
version = Versioning.getVersion(getState(), persister);
}
entry.postUpdate(instance, getState(), version);
}
persistenceContext.registerInsertedKey(persister, getId());
}
final SessionFactoryImplementor factory = session.getFactory();
if (isCachePutEnabled(persister, session)) {
final CacheEntry ce = persister.buildCacheEntry(instance, getState(), version, session);
cacheEntry = persister.getCacheEntryStructure().structure(ce);
final EntityDataAccess cache = persister.getCacheAccessStrategy();
final Object ck = cache.generateCacheKey(id, persister, factory, session.getTenantIdentifier());
final boolean put = cacheInsert(persister, ck);
if (put && factory.getStatistics().isStatisticsEnabled()) {
factory.getStatistics().entityCachePut(StatsHelper.INSTANCE.getRootEntityRole(persister), cache.getRegion().getName());
}
}
handleNaturalIdPostSaveNotifications(id);
postInsert();
if (factory.getStatistics().isStatisticsEnabled() && !veto) {
factory.getStatistics().insertEntity(getPersister().getEntityName());
}
markExecuted();
}
Aggregations