use of org.hibernate.envers.internal.synchronization.work.CollectionChangeWorkUnit in project hibernate-orm by hibernate.
the class BaseEnversCollectionEventListener method generateBidirectionalCollectionChangeWorkUnits.
private void generateBidirectionalCollectionChangeWorkUnits(AuditProcess auditProcess, AbstractCollectionEvent event, PersistentCollectionChangeWorkUnit workUnit, RelationDescription rd) {
// Checking if this is enabled in configuration ...
if (!getEnversService().getGlobalConfiguration().isGenerateRevisionsForCollections()) {
return;
}
// relDesc can be null if this is a collection of simple values (not a relation).
if (rd != null && rd.isBidirectional()) {
final String relatedEntityName = rd.getToEntityName();
final IdMapper relatedIdMapper = getEnversService().getEntitiesConfigurations().get(relatedEntityName).getIdMapper();
final Set<String> toPropertyNames = getEnversService().getEntitiesConfigurations().getToPropertyNames(event.getAffectedOwnerEntityName(), rd.getFromPropertyName(), relatedEntityName);
final String toPropertyName = toPropertyNames.iterator().next();
for (PersistentCollectionChangeData changeData : workUnit.getCollectionChanges()) {
final Object relatedObj = changeData.getChangedElement();
final Serializable relatedId = (Serializable) relatedIdMapper.mapToIdFromEntity(relatedObj);
auditProcess.addWorkUnit(new CollectionChangeWorkUnit(event.getSession(), event.getSession().bestGuessEntityName(relatedObj), toPropertyName, getEnversService(), relatedId, relatedObj));
}
}
}
use of org.hibernate.envers.internal.synchronization.work.CollectionChangeWorkUnit in project hibernate-orm by hibernate.
the class BaseEnversCollectionEventListener method generateFakeBidirecationalRelationWorkUnits.
private void generateFakeBidirecationalRelationWorkUnits(AuditProcess auditProcess, PersistentCollection newColl, Serializable oldColl, String collectionEntityName, String referencingPropertyName, AbstractCollectionEvent event, RelationDescription rd) {
// First computing the relation changes
final List<PersistentCollectionChangeData> collectionChanges = getEnversService().getEntitiesConfigurations().get(collectionEntityName).getPropertyMapper().mapCollectionChanges(event.getSession(), referencingPropertyName, newColl, oldColl, event.getAffectedOwnerIdOrNull());
// Getting the id mapper for the related entity, as the work units generated will correspond to the related
// entities.
final String relatedEntityName = rd.getToEntityName();
final IdMapper relatedIdMapper = getEnversService().getEntitiesConfigurations().get(relatedEntityName).getIdMapper();
// For each collection change, generating the bidirectional work unit.
for (PersistentCollectionChangeData changeData : collectionChanges) {
final Object relatedObj = changeData.getChangedElement();
final Serializable relatedId = (Serializable) relatedIdMapper.mapToIdFromEntity(relatedObj);
final RevisionType revType = (RevisionType) changeData.getData().get(getEnversService().getAuditEntitiesConfiguration().getRevisionTypePropName());
// This can be different from relatedEntityName, in case of inheritance (the real entity may be a subclass
// of relatedEntityName).
final String realRelatedEntityName = event.getSession().bestGuessEntityName(relatedObj);
// By default, the nested work unit is a collection change work unit.
final AuditWorkUnit nestedWorkUnit = new CollectionChangeWorkUnit(event.getSession(), realRelatedEntityName, rd.getMappedByPropertyName(), getEnversService(), relatedId, relatedObj);
auditProcess.addWorkUnit(new FakeBidirectionalRelationWorkUnit(event.getSession(), realRelatedEntityName, getEnversService(), relatedId, referencingPropertyName, event.getAffectedOwnerOrNull(), rd, revType, changeData.getChangedElementIndex(), nestedWorkUnit));
}
// We also have to generate a collection change work unit for the owning entity.
auditProcess.addWorkUnit(new CollectionChangeWorkUnit(event.getSession(), collectionEntityName, referencingPropertyName, getEnversService(), event.getAffectedOwnerIdOrNull(), event.getAffectedOwnerOrNull()));
}
use of org.hibernate.envers.internal.synchronization.work.CollectionChangeWorkUnit in project hibernate-orm by hibernate.
the class BaseEnversEventListener method addCollectionChangeWorkUnit.
private void addCollectionChangeWorkUnit(AuditProcess auditProcess, SessionImplementor session, String fromEntityName, RelationDescription relDesc, Object value) {
// relDesc.getToEntityName() doesn't always return the entity name of the value - in case
// of subclasses, this will be root class, no the actual class. So it can't be used here.
String toEntityName;
Serializable id;
if (value instanceof HibernateProxy) {
final HibernateProxy hibernateProxy = (HibernateProxy) value;
id = hibernateProxy.getHibernateLazyInitializer().getIdentifier();
// We've got to initialize the object from the proxy to later read its state.
value = EntityTools.getTargetFromProxy(session.getFactory(), hibernateProxy);
// HHH-7249
// This call must occur after the proxy has been initialized or the returned name will
// be to the base class which will impact the discriminator value chosen when using an
// inheritance strategy with discriminators.
toEntityName = session.bestGuessEntityName(value);
} else {
toEntityName = session.guessEntityName(value);
final IdMapper idMapper = enversService.getEntitiesConfigurations().get(toEntityName).getIdMapper();
id = (Serializable) idMapper.mapToIdFromEntity(value);
}
final Set<String> toPropertyNames = enversService.getEntitiesConfigurations().getToPropertyNames(fromEntityName, relDesc.getFromPropertyName(), toEntityName);
final String toPropertyName = toPropertyNames.iterator().next();
auditProcess.addWorkUnit(new CollectionChangeWorkUnit(session, toEntityName, toPropertyName, enversService, id, value));
}
use of org.hibernate.envers.internal.synchronization.work.CollectionChangeWorkUnit in project hibernate-orm by hibernate.
the class BaseEnversCollectionEventListener method onCollectionAction.
protected final void onCollectionAction(AbstractCollectionEvent event, PersistentCollection newColl, Serializable oldColl, CollectionEntry collectionEntry) {
if (shouldGenerateRevision(event)) {
checkIfTransactionInProgress(event.getSession());
final AuditProcess auditProcess = getEnversService().getAuditProcessManager().get(event.getSession());
final String entityName = event.getAffectedOwnerEntityName();
final String ownerEntityName = ((AbstractCollectionPersister) collectionEntry.getLoadedPersister()).getOwnerEntityName();
final String referencingPropertyName = collectionEntry.getRole().substring(ownerEntityName.length() + 1);
// Checking if this is not a "fake" many-to-one bidirectional relation. The relation description may be
// null in case of collections of non-entities.
final RelationDescription rd = searchForRelationDescription(entityName, referencingPropertyName);
if (rd != null && rd.getMappedByPropertyName() != null) {
generateFakeBidirecationalRelationWorkUnits(auditProcess, newColl, oldColl, entityName, referencingPropertyName, event, rd);
} else {
final PersistentCollectionChangeWorkUnit workUnit = new PersistentCollectionChangeWorkUnit(event.getSession(), entityName, getEnversService(), newColl, collectionEntry, oldColl, event.getAffectedOwnerIdOrNull(), referencingPropertyName);
auditProcess.addWorkUnit(workUnit);
if (workUnit.containsWork()) {
// There are some changes: a revision needs also be generated for the collection owner
auditProcess.addWorkUnit(new CollectionChangeWorkUnit(event.getSession(), event.getAffectedOwnerEntityName(), referencingPropertyName, getEnversService(), event.getAffectedOwnerIdOrNull(), event.getAffectedOwnerOrNull()));
generateBidirectionalCollectionChangeWorkUnits(auditProcess, event, workUnit, rd);
}
}
}
}
Aggregations