HHH-3871:
- not loading proxied objects when not necessary - test git-svn-id: https://svn.jboss.org/repos/hibernate/core/trunk@16393 1b8cb986-b30d-0410-93ca-fae66ebed9b2
This commit is contained in:
parent
0f9a6882b9
commit
ac0889dbd6
|
@ -36,6 +36,7 @@ import org.hibernate.envers.tools.reflection.ReflectionTools;
|
|||
import org.hibernate.collection.PersistentCollection;
|
||||
import org.hibernate.property.Setter;
|
||||
import org.hibernate.util.ReflectHelper;
|
||||
import org.hibernate.engine.SessionImplementor;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
|
@ -63,8 +64,8 @@ public class ComponentPropertyMapper implements PropertyMapper, CompositeMapperB
|
|||
delegate.addComposite(propertyData, propertyMapper);
|
||||
}
|
||||
|
||||
public boolean mapToMapFromEntity(Map<String, Object> data, Object newObj, Object oldObj) {
|
||||
return delegate.mapToMapFromEntity(data, newObj, oldObj);
|
||||
public boolean mapToMapFromEntity(SessionImplementor session, Map<String, Object> data, Object newObj, Object oldObj) {
|
||||
return delegate.mapToMapFromEntity(session, data, newObj, oldObj);
|
||||
}
|
||||
|
||||
public void mapToEntityFromMap(AuditConfiguration verCfg, Object obj, Map data, Object primaryKey, AuditReaderImplementor versionsReader, Number revision) {
|
||||
|
|
|
@ -23,11 +23,13 @@
|
|||
*/
|
||||
package org.hibernate.envers.entities.mapper;
|
||||
|
||||
import org.hibernate.engine.SessionImplementor;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public interface ExtendedPropertyMapper extends PropertyMapper, CompositeMapperBuilder {
|
||||
public boolean map(Map<String, Object> data, String[] propertyNames, Object[] newState, Object[] oldState);
|
||||
public boolean map(SessionImplementor session, Map<String, Object> data, String[] propertyNames, Object[] newState, Object[] oldState);
|
||||
}
|
||||
|
|
|
@ -36,6 +36,7 @@ import org.hibernate.envers.tools.MappingTools;
|
|||
|
||||
import org.hibernate.collection.PersistentCollection;
|
||||
import org.hibernate.property.Getter;
|
||||
import org.hibernate.engine.SessionImplementor;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
|
@ -75,13 +76,13 @@ public class MultiPropertyMapper implements ExtendedPropertyMapper {
|
|||
|
||||
private Object getAtIndexOrNull(Object[] array, int index) { return array == null ? null : array[index]; }
|
||||
|
||||
public boolean map(Map<String, Object> data, String[] propertyNames, Object[] newState, Object[] oldState) {
|
||||
public boolean map(SessionImplementor session, Map<String, Object> data, String[] propertyNames, Object[] newState, Object[] oldState) {
|
||||
boolean ret = false;
|
||||
for (int i=0; i<propertyNames.length; i++) {
|
||||
String propertyName = propertyNames[i];
|
||||
|
||||
if (propertyDatas.containsKey(propertyName)) {
|
||||
ret |= properties.get(propertyDatas.get(propertyName)).mapToMapFromEntity(data,
|
||||
ret |= properties.get(propertyDatas.get(propertyName)).mapToMapFromEntity(session, data,
|
||||
getAtIndexOrNull(newState, i),
|
||||
getAtIndexOrNull(oldState, i));
|
||||
}
|
||||
|
@ -90,7 +91,7 @@ public class MultiPropertyMapper implements ExtendedPropertyMapper {
|
|||
return ret;
|
||||
}
|
||||
|
||||
public boolean mapToMapFromEntity(Map<String, Object> data, Object newObj, Object oldObj) {
|
||||
public boolean mapToMapFromEntity(SessionImplementor session, Map<String, Object> data, Object newObj, Object oldObj) {
|
||||
boolean ret = false;
|
||||
for (PropertyData propertyData : properties.keySet()) {
|
||||
Getter getter;
|
||||
|
@ -102,7 +103,7 @@ public class MultiPropertyMapper implements ExtendedPropertyMapper {
|
|||
return false;
|
||||
}
|
||||
|
||||
ret |= properties.get(propertyData).mapToMapFromEntity(data,
|
||||
ret |= properties.get(propertyData).mapToMapFromEntity(session, data,
|
||||
newObj == null ? null : getter.get(newObj),
|
||||
oldObj == null ? null : getter.get(oldObj));
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@ import org.hibernate.envers.configuration.AuditConfiguration;
|
|||
import org.hibernate.envers.reader.AuditReaderImplementor;
|
||||
|
||||
import org.hibernate.collection.PersistentCollection;
|
||||
import org.hibernate.engine.SessionImplementor;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
|
@ -38,12 +39,13 @@ import org.hibernate.collection.PersistentCollection;
|
|||
public interface PropertyMapper {
|
||||
/**
|
||||
* Maps properties to the given map, basing on differences between properties of new and old objects.
|
||||
* @param data Data to map to.
|
||||
* @param newObj New state of the entity.
|
||||
* @param oldObj Old state of the entity.
|
||||
* @return True if there are any differences between the states represented by newObj and oldObj.
|
||||
* @param session The current session.
|
||||
* @param data Data to map to.
|
||||
* @param newObj New state of the entity.
|
||||
* @param oldObj Old state of the entity.
|
||||
* @return True if there are any differences between the states represented by newObj and oldObj.
|
||||
*/
|
||||
boolean mapToMapFromEntity(Map<String, Object> data, Object newObj, Object oldObj);
|
||||
boolean mapToMapFromEntity(SessionImplementor session, Map<String, Object> data, Object newObj, Object oldObj);
|
||||
|
||||
/**
|
||||
* Maps properties from the given map to the given object.
|
||||
|
|
|
@ -36,6 +36,7 @@ import org.hibernate.envers.tools.reflection.ReflectionTools;
|
|||
|
||||
import org.hibernate.collection.PersistentCollection;
|
||||
import org.hibernate.property.Setter;
|
||||
import org.hibernate.engine.SessionImplementor;
|
||||
|
||||
/**
|
||||
* TODO: diff
|
||||
|
@ -54,7 +55,7 @@ public class SinglePropertyMapper implements PropertyMapper, SimpleMapperBuilder
|
|||
this.propertyData = propertyData;
|
||||
}
|
||||
|
||||
public boolean mapToMapFromEntity(Map<String, Object> data, Object newObj, Object oldObj) {
|
||||
public boolean mapToMapFromEntity(SessionImplementor session, Map<String, Object> data, Object newObj, Object oldObj) {
|
||||
data.put(propertyData.getName(), newObj);
|
||||
|
||||
return !Tools.objectsEqual(newObj, oldObj);
|
||||
|
|
|
@ -32,6 +32,7 @@ import org.hibernate.envers.configuration.AuditConfiguration;
|
|||
import org.hibernate.envers.reader.AuditReaderImplementor;
|
||||
|
||||
import org.hibernate.collection.PersistentCollection;
|
||||
import org.hibernate.engine.SessionImplementor;
|
||||
|
||||
/**
|
||||
* A mapper which maps from a parent mapper and a "main" one, but adds only to the "main". The "main" mapper
|
||||
|
@ -47,16 +48,16 @@ public class SubclassPropertyMapper implements ExtendedPropertyMapper {
|
|||
this.parentMapper = parentMapper;
|
||||
}
|
||||
|
||||
public boolean map(Map<String, Object> data, String[] propertyNames, Object[] newState, Object[] oldState) {
|
||||
boolean parentDiffs = parentMapper.map(data, propertyNames, newState, oldState);
|
||||
boolean mainDiffs = main.map(data, propertyNames, newState, oldState);
|
||||
public boolean map(SessionImplementor session, Map<String, Object> data, String[] propertyNames, Object[] newState, Object[] oldState) {
|
||||
boolean parentDiffs = parentMapper.map(session, data, propertyNames, newState, oldState);
|
||||
boolean mainDiffs = main.map(session, data, propertyNames, newState, oldState);
|
||||
|
||||
return parentDiffs || mainDiffs;
|
||||
}
|
||||
|
||||
public boolean mapToMapFromEntity(Map<String, Object> data, Object newObj, Object oldObj) {
|
||||
boolean parentDiffs = parentMapper.mapToMapFromEntity(data, newObj, oldObj);
|
||||
boolean mainDiffs = main.mapToMapFromEntity(data, newObj, oldObj);
|
||||
public boolean mapToMapFromEntity(SessionImplementor session, Map<String, Object> data, Object newObj, Object oldObj) {
|
||||
boolean parentDiffs = parentMapper.mapToMapFromEntity(session, data, newObj, oldObj);
|
||||
boolean mainDiffs = main.mapToMapFromEntity(session, data, newObj, oldObj);
|
||||
|
||||
return parentDiffs || mainDiffs;
|
||||
}
|
||||
|
|
|
@ -45,6 +45,7 @@ import org.hibernate.envers.tools.reflection.ReflectionTools;
|
|||
|
||||
import org.hibernate.collection.PersistentCollection;
|
||||
import org.hibernate.property.Setter;
|
||||
import org.hibernate.engine.SessionImplementor;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
|
@ -130,7 +131,7 @@ public abstract class AbstractCollectionMapper<T> implements PropertyMapper {
|
|||
return collectionChanges;
|
||||
}
|
||||
|
||||
public boolean mapToMapFromEntity(Map<String, Object> data, Object newObj, Object oldObj) {
|
||||
public boolean mapToMapFromEntity(SessionImplementor session, Map<String, Object> data, Object newObj, Object oldObj) {
|
||||
// Changes are mapped in the "mapCollectionChanges" method.
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -38,6 +38,7 @@ import org.hibernate.envers.reader.AuditReaderImplementor;
|
|||
import org.hibernate.envers.tools.reflection.ReflectionTools;
|
||||
|
||||
import org.hibernate.NonUniqueResultException;
|
||||
import org.hibernate.engine.SessionImplementor;
|
||||
import org.hibernate.collection.PersistentCollection;
|
||||
import org.hibernate.property.Setter;
|
||||
|
||||
|
@ -56,7 +57,7 @@ public class OneToOneNotOwningMapper implements PropertyMapper {
|
|||
this.propertyData = propertyData;
|
||||
}
|
||||
|
||||
public boolean mapToMapFromEntity(Map<String, Object> data, Object newObj, Object oldObj) {
|
||||
public boolean mapToMapFromEntity(SessionImplementor session, Map<String, Object> data, Object newObj, Object oldObj) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -40,6 +40,7 @@ import org.hibernate.envers.tools.reflection.ReflectionTools;
|
|||
|
||||
import org.hibernate.collection.PersistentCollection;
|
||||
import org.hibernate.property.Setter;
|
||||
import org.hibernate.engine.SessionImplementor;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
|
@ -55,13 +56,13 @@ public class ToOneIdMapper implements PropertyMapper {
|
|||
this.referencedEntityName = referencedEntityName;
|
||||
}
|
||||
|
||||
public boolean mapToMapFromEntity(Map<String, Object> data, Object newObj, Object oldObj) {
|
||||
public boolean mapToMapFromEntity(SessionImplementor session, Map<String, Object> data, Object newObj, Object oldObj) {
|
||||
HashMap<String, Object> newData = new HashMap<String, Object>();
|
||||
data.put(propertyData.getName(), newData);
|
||||
|
||||
delegate.mapToMapFromEntity(newData, newObj);
|
||||
|
||||
return !Tools.objectsEqual(newObj, oldObj);
|
||||
return !Tools.entitiesEqual(session, newObj, oldObj);
|
||||
}
|
||||
|
||||
public void mapToEntityFromMap(AuditConfiguration verCfg, Object obj, Map data, Object primaryKey,
|
||||
|
|
|
@ -90,41 +90,49 @@ public class AuditEventListener implements PostInsertEventListener, PostUpdateEv
|
|||
Object oldValue = oldState == null ? null : oldState[i];
|
||||
Object newValue = newState == null ? null : newState[i];
|
||||
|
||||
if (!Tools.objectsEqual(oldValue, newValue)) {
|
||||
if (!Tools.entitiesEqual(session, oldValue, newValue)) {
|
||||
// We have to generate changes both in the old collection (size decreses) and new collection
|
||||
// (size increases).
|
||||
if (newValue != null) {
|
||||
// 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;
|
||||
if(newValue instanceof HibernateProxy) {
|
||||
Serializable id;
|
||||
|
||||
if (newValue instanceof HibernateProxy) {
|
||||
HibernateProxy hibernateProxy = (HibernateProxy) newValue;
|
||||
toEntityName = session.bestGuessEntityName(newValue);
|
||||
newValue = hibernateProxy.getHibernateLazyInitializer().getImplementation();
|
||||
id = hibernateProxy.getHibernateLazyInitializer().getIdentifier();
|
||||
// We've got to initialize the object from the proxy to later read its state.
|
||||
newValue = Tools.getTargetFromProxy(hibernateProxy);
|
||||
} else {
|
||||
toEntityName = session.guessEntityName(newValue);
|
||||
|
||||
IdMapper idMapper = verCfg.getEntCfg().get(toEntityName).getIdMapper();
|
||||
id = (Serializable) idMapper.mapToIdFromEntity(newValue);
|
||||
}
|
||||
|
||||
IdMapper idMapper = verCfg.getEntCfg().get(toEntityName).getIdMapper();
|
||||
|
||||
Serializable id = (Serializable) idMapper.mapToIdFromEntity(newValue);
|
||||
verSync.addWorkUnit(new CollectionChangeWorkUnit(toEntityName, verCfg, id, newValue));
|
||||
verSync.addWorkUnit(new CollectionChangeWorkUnit(session, toEntityName, verCfg, id, newValue));
|
||||
}
|
||||
|
||||
if (oldValue != null) {
|
||||
String toEntityName;
|
||||
Serializable id;
|
||||
|
||||
if(oldValue instanceof HibernateProxy) {
|
||||
HibernateProxy hibernateProxy = (HibernateProxy) oldValue;
|
||||
toEntityName = session.bestGuessEntityName(oldValue);
|
||||
oldValue = hibernateProxy.getHibernateLazyInitializer().getImplementation();
|
||||
id = hibernateProxy.getHibernateLazyInitializer().getIdentifier();
|
||||
// We've got to initialize the object as we'll read it's state anyway.
|
||||
oldValue = Tools.getTargetFromProxy(hibernateProxy);
|
||||
} else {
|
||||
toEntityName = session.guessEntityName(oldValue);
|
||||
}
|
||||
|
||||
IdMapper idMapper = verCfg.getEntCfg().get(toEntityName).getIdMapper();
|
||||
|
||||
Serializable id = (Serializable) idMapper.mapToIdFromEntity(oldValue);
|
||||
verSync.addWorkUnit(new CollectionChangeWorkUnit(toEntityName, verCfg, id, oldValue));
|
||||
IdMapper idMapper = verCfg.getEntCfg().get(toEntityName).getIdMapper();
|
||||
id = (Serializable) idMapper.mapToIdFromEntity(oldValue);
|
||||
}
|
||||
|
||||
verSync.addWorkUnit(new CollectionChangeWorkUnit(session, toEntityName, verCfg, id, oldValue));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -137,8 +145,8 @@ public class AuditEventListener implements PostInsertEventListener, PostUpdateEv
|
|||
if (verCfg.getEntCfg().isVersioned(entityName)) {
|
||||
AuditSync verSync = verCfg.getSyncManager().get(event.getSession());
|
||||
|
||||
verSync.addWorkUnit(new AddWorkUnit(event.getPersister().getEntityName(), verCfg, event.getId(),
|
||||
event.getPersister(), event.getState()));
|
||||
verSync.addWorkUnit(new AddWorkUnit(event.getSession(), event.getPersister().getEntityName(), verCfg,
|
||||
event.getId(), event.getPersister(), event.getState()));
|
||||
|
||||
generateBidirectionalCollectionChangeWorkUnits(verSync, event.getPersister(), entityName, event.getState(),
|
||||
null, event.getSession());
|
||||
|
@ -151,8 +159,8 @@ public class AuditEventListener implements PostInsertEventListener, PostUpdateEv
|
|||
if (verCfg.getEntCfg().isVersioned(entityName)) {
|
||||
AuditSync verSync = verCfg.getSyncManager().get(event.getSession());
|
||||
|
||||
verSync.addWorkUnit(new ModWorkUnit(event.getPersister().getEntityName(), verCfg, event.getId(),
|
||||
event.getPersister(), event.getState(), event.getOldState()));
|
||||
verSync.addWorkUnit(new ModWorkUnit(event.getSession(), event.getPersister().getEntityName(), verCfg,
|
||||
event.getId(), event.getPersister(), event.getState(), event.getOldState()));
|
||||
|
||||
generateBidirectionalCollectionChangeWorkUnits(verSync, event.getPersister(), entityName, event.getState(),
|
||||
event.getOldState(), event.getSession());
|
||||
|
@ -165,7 +173,8 @@ public class AuditEventListener implements PostInsertEventListener, PostUpdateEv
|
|||
if (verCfg.getEntCfg().isVersioned(entityName)) {
|
||||
AuditSync verSync = verCfg.getSyncManager().get(event.getSession());
|
||||
|
||||
verSync.addWorkUnit(new DelWorkUnit(event.getPersister().getEntityName(), verCfg, event.getId()));
|
||||
verSync.addWorkUnit(new DelWorkUnit(event.getSession(), event.getPersister().getEntityName(), verCfg,
|
||||
event.getId()));
|
||||
|
||||
generateBidirectionalCollectionChangeWorkUnits(verSync, event.getPersister(), entityName, null,
|
||||
event.getDeletedState(), event.getSession());
|
||||
|
@ -193,7 +202,8 @@ public class AuditEventListener implements PostInsertEventListener, PostUpdateEv
|
|||
Object relatedObj = changeData.getChangedElement();
|
||||
Serializable relatedId = (Serializable) relatedIdMapper.mapToIdFromEntity(relatedObj);
|
||||
|
||||
verSync.addWorkUnit(new CollectionChangeWorkUnit(relatedEntityName, verCfg, relatedId, relatedObj));
|
||||
verSync.addWorkUnit(new CollectionChangeWorkUnit(event.getSession(), relatedEntityName, verCfg,
|
||||
relatedId, relatedObj));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -205,14 +215,14 @@ public class AuditEventListener implements PostInsertEventListener, PostUpdateEv
|
|||
if (verCfg.getEntCfg().isVersioned(entityName)) {
|
||||
AuditSync verSync = verCfg.getSyncManager().get(event.getSession());
|
||||
|
||||
PersistentCollectionChangeWorkUnit workUnit = new PersistentCollectionChangeWorkUnit(entityName, verCfg,
|
||||
newColl, collectionEntry, oldColl, event.getAffectedOwnerIdOrNull());
|
||||
PersistentCollectionChangeWorkUnit workUnit = new PersistentCollectionChangeWorkUnit(event.getSession(),
|
||||
entityName, verCfg, newColl, collectionEntry, oldColl, event.getAffectedOwnerIdOrNull());
|
||||
verSync.addWorkUnit(workUnit);
|
||||
|
||||
if (workUnit.containsWork()) {
|
||||
// There are some changes: a revision needs also be generated for the collection owner
|
||||
verSync.addWorkUnit(new CollectionChangeWorkUnit(event.getAffectedOwnerEntityName(), verCfg,
|
||||
event.getAffectedOwnerIdOrNull(), event.getAffectedOwnerOrNull()));
|
||||
verSync.addWorkUnit(new CollectionChangeWorkUnit(event.getSession(), event.getAffectedOwnerEntityName(),
|
||||
verCfg, event.getAffectedOwnerIdOrNull(), event.getAffectedOwnerOrNull()));
|
||||
|
||||
generateBidirectionalCollectionChangeWorkUnits(verSync, event, workUnit);
|
||||
}
|
||||
|
|
|
@ -32,11 +32,13 @@ import org.hibernate.envers.configuration.AuditConfiguration;
|
|||
import org.hibernate.envers.configuration.AuditEntitiesConfiguration;
|
||||
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.engine.SessionImplementor;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public abstract class AbstractAuditWorkUnit implements AuditWorkUnit {
|
||||
protected final SessionImplementor sessionImplementor;
|
||||
protected final AuditConfiguration verCfg;
|
||||
protected final Serializable id;
|
||||
|
||||
|
@ -44,7 +46,9 @@ public abstract class AbstractAuditWorkUnit implements AuditWorkUnit {
|
|||
|
||||
private Object performedData;
|
||||
|
||||
protected AbstractAuditWorkUnit(String entityName, AuditConfiguration verCfg, Serializable id) {
|
||||
protected AbstractAuditWorkUnit(SessionImplementor sessionImplementor, String entityName, AuditConfiguration verCfg,
|
||||
Serializable id) {
|
||||
this.sessionImplementor = sessionImplementor;
|
||||
this.verCfg = verCfg;
|
||||
this.id = id;
|
||||
this.entityName = entityName;
|
||||
|
|
|
@ -31,6 +31,7 @@ import org.hibernate.envers.RevisionType;
|
|||
import org.hibernate.envers.configuration.AuditConfiguration;
|
||||
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.engine.SessionImplementor;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
|
||||
/**
|
||||
|
@ -40,9 +41,9 @@ public class AddWorkUnit extends AbstractAuditWorkUnit implements AuditWorkUnit
|
|||
private final Object[] state;
|
||||
private final String[] propertyNames;
|
||||
|
||||
public AddWorkUnit(String entityName, AuditConfiguration verCfg, Serializable id,
|
||||
EntityPersister entityPersister, Object[] state) {
|
||||
super(entityName, verCfg, id);
|
||||
public AddWorkUnit(SessionImplementor sessionImplementor, String entityName, AuditConfiguration verCfg,
|
||||
Serializable id, EntityPersister entityPersister, Object[] state) {
|
||||
super(sessionImplementor, entityName, verCfg, id);
|
||||
|
||||
this.state = state;
|
||||
this.propertyNames = entityPersister.getPropertyNames();
|
||||
|
@ -56,7 +57,8 @@ public class AddWorkUnit extends AbstractAuditWorkUnit implements AuditWorkUnit
|
|||
Map<String, Object> data = new HashMap<String, Object>();
|
||||
fillDataWithId(data, revisionData, RevisionType.ADD);
|
||||
|
||||
verCfg.getEntCfg().get(getEntityName()).getPropertyMapper().map(data, propertyNames, state, null);
|
||||
verCfg.getEntCfg().get(getEntityName()).getPropertyMapper().map(sessionImplementor, data,
|
||||
propertyNames, state, null);
|
||||
|
||||
session.save(verCfg.getAuditEntCfg().getAuditEntityName(getEntityName()), data);
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@ import org.hibernate.envers.RevisionType;
|
|||
import org.hibernate.envers.configuration.AuditConfiguration;
|
||||
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.engine.SessionImplementor;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
|
@ -38,8 +39,9 @@ import org.hibernate.Session;
|
|||
public class CollectionChangeWorkUnit extends AbstractAuditWorkUnit implements AuditWorkUnit {
|
||||
private final Object entity;
|
||||
|
||||
public CollectionChangeWorkUnit(String entityName, AuditConfiguration verCfg, Serializable id, Object entity) {
|
||||
super(entityName, verCfg, id);
|
||||
public CollectionChangeWorkUnit(SessionImplementor session, String entityName, AuditConfiguration verCfg,
|
||||
Serializable id, Object entity) {
|
||||
super(session, entityName, verCfg, id);
|
||||
|
||||
this.entity = entity;
|
||||
}
|
||||
|
@ -52,7 +54,8 @@ public class CollectionChangeWorkUnit extends AbstractAuditWorkUnit implements A
|
|||
Map<String, Object> data = new HashMap<String, Object>();
|
||||
fillDataWithId(data, revisionData, RevisionType.MOD);
|
||||
|
||||
verCfg.getEntCfg().get(getEntityName()).getPropertyMapper().mapToMapFromEntity(data, entity, null);
|
||||
verCfg.getEntCfg().get(getEntityName()).getPropertyMapper().mapToMapFromEntity(sessionImplementor,
|
||||
data, entity, null);
|
||||
|
||||
session.save(verCfg.getAuditEntCfg().getAuditEntityName(getEntityName()), data);
|
||||
|
||||
|
|
|
@ -31,13 +31,14 @@ import org.hibernate.envers.RevisionType;
|
|||
import org.hibernate.envers.configuration.AuditConfiguration;
|
||||
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.engine.SessionImplementor;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public class DelWorkUnit extends AbstractAuditWorkUnit implements AuditWorkUnit {
|
||||
public DelWorkUnit(String entityName, AuditConfiguration verCfg, Serializable id) {
|
||||
super(entityName, verCfg, id);
|
||||
public DelWorkUnit(SessionImplementor sessionImplementor, String entityName, AuditConfiguration verCfg, Serializable id) {
|
||||
super(sessionImplementor, entityName, verCfg, id);
|
||||
}
|
||||
|
||||
public boolean containsWork() {
|
||||
|
|
|
@ -31,6 +31,7 @@ import org.hibernate.envers.RevisionType;
|
|||
import org.hibernate.envers.configuration.AuditConfiguration;
|
||||
|
||||
import org.hibernate.Session;
|
||||
import org.hibernate.engine.SessionImplementor;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
|
||||
/**
|
||||
|
@ -40,13 +41,13 @@ public class ModWorkUnit extends AbstractAuditWorkUnit implements AuditWorkUnit
|
|||
private final Map<String, Object> data;
|
||||
private final boolean changes;
|
||||
|
||||
public ModWorkUnit(String entityName, AuditConfiguration verCfg, Serializable id,
|
||||
EntityPersister entityPersister, Object[] newState, Object[] oldState) {
|
||||
super(entityName, verCfg, id);
|
||||
public ModWorkUnit(SessionImplementor sessionImplementor, String entityName, AuditConfiguration verCfg,
|
||||
Serializable id, EntityPersister entityPersister, Object[] newState, Object[] oldState) {
|
||||
super(sessionImplementor, entityName, verCfg, id);
|
||||
|
||||
data = new HashMap<String, Object>();
|
||||
changes = verCfg.getEntCfg().get(getEntityName()).getPropertyMapper().map(data, entityPersister.getPropertyNames(),
|
||||
newState, oldState);
|
||||
changes = verCfg.getEntCfg().get(getEntityName()).getPropertyMapper().map(sessionImplementor, data,
|
||||
entityPersister.getPropertyNames(), newState, oldState);
|
||||
}
|
||||
|
||||
public boolean containsWork() {
|
||||
|
|
|
@ -34,6 +34,7 @@ import org.hibernate.envers.entities.mapper.PersistentCollectionChangeData;
|
|||
import org.hibernate.Session;
|
||||
import org.hibernate.persister.collection.AbstractCollectionPersister;
|
||||
import org.hibernate.engine.CollectionEntry;
|
||||
import org.hibernate.engine.SessionImplementor;
|
||||
import org.hibernate.collection.PersistentCollection;
|
||||
|
||||
/**
|
||||
|
@ -43,10 +44,10 @@ public class PersistentCollectionChangeWorkUnit extends AbstractAuditWorkUnit im
|
|||
private final List<PersistentCollectionChangeData> collectionChanges;
|
||||
private final String referencingPropertyName;
|
||||
|
||||
public PersistentCollectionChangeWorkUnit(String entityName, AuditConfiguration verCfg,
|
||||
PersistentCollection collection, CollectionEntry collectionEntry,
|
||||
Serializable snapshot, Serializable id) {
|
||||
super(entityName, verCfg, null);
|
||||
public PersistentCollectionChangeWorkUnit(SessionImplementor sessionImplementor, String entityName,
|
||||
AuditConfiguration verCfg, PersistentCollection collection,
|
||||
CollectionEntry collectionEntry, Serializable snapshot, Serializable id) {
|
||||
super(sessionImplementor, entityName, verCfg, null);
|
||||
|
||||
String ownerEntityName = ((AbstractCollectionPersister) collectionEntry.getLoadedPersister()).getOwnerEntityName();
|
||||
referencingPropertyName = collectionEntry.getRole().substring(ownerEntityName.length() + 1);
|
||||
|
|
|
@ -23,6 +23,10 @@
|
|||
*/
|
||||
package org.hibernate.envers.tools;
|
||||
|
||||
import org.hibernate.proxy.HibernateProxy;
|
||||
import org.hibernate.engine.SessionImplementor;
|
||||
import org.hibernate.Session;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
|
@ -41,6 +45,42 @@ public class Tools {
|
|||
return new LinkedHashMap<K,V>();
|
||||
}
|
||||
|
||||
public static boolean entitiesEqual(SessionImplementor session, Object obj1, Object obj2) {
|
||||
Object id1 = getIdentifier(session, obj1);
|
||||
Object id2 = getIdentifier(session, obj2);
|
||||
|
||||
return objectsEqual(id1, id2);
|
||||
}
|
||||
|
||||
public static Object getIdentifier(SessionImplementor session, Object obj) {
|
||||
if (obj == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (obj instanceof HibernateProxy) {
|
||||
HibernateProxy hibernateProxy = (HibernateProxy) obj;
|
||||
return hibernateProxy.getHibernateLazyInitializer().getIdentifier();
|
||||
}
|
||||
|
||||
|
||||
return session.getEntityPersister(null, obj).getIdentifier(obj, session.getEntityMode());
|
||||
}
|
||||
|
||||
public static Object getTargetFromProxy(HibernateProxy proxy) {
|
||||
if (!proxy.getHibernateLazyInitializer().isUninitialized()) {
|
||||
return proxy.getHibernateLazyInitializer().getImplementation();
|
||||
}
|
||||
|
||||
Session tempSession = proxy.getHibernateLazyInitializer().getSession().getFactory().openTemporarySession();
|
||||
try {
|
||||
proxy.getHibernateLazyInitializer().setSession((SessionImplementor) tempSession);
|
||||
proxy.getHibernateLazyInitializer().initialize();
|
||||
return proxy.getHibernateLazyInitializer().getImplementation();
|
||||
} finally {
|
||||
tempSession.close();
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean objectsEqual(Object obj1, Object obj2) {
|
||||
if (obj1 == null) {
|
||||
return obj2 == null;
|
||||
|
|
|
@ -0,0 +1,150 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Middleware LLC.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.envers.test.integration.reference;
|
||||
|
||||
import org.hibernate.ejb.Ejb3Configuration;
|
||||
import org.hibernate.envers.test.AbstractEntityTest;
|
||||
import org.hibernate.envers.test.tools.TestTools;
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public class BidirectionalReference extends AbstractEntityTest {
|
||||
private Long set1_id;
|
||||
private Long set2_id;
|
||||
|
||||
private Long g1_id;
|
||||
|
||||
public void configure(Ejb3Configuration cfg) {
|
||||
cfg.addAnnotatedClass(GreetingPO.class);
|
||||
cfg.addAnnotatedClass(GreetingSetPO.class);
|
||||
}
|
||||
|
||||
@BeforeClass(dependsOnMethods = "init")
|
||||
public void initData() {
|
||||
EntityManager em = getEntityManager();
|
||||
|
||||
GreetingSetPO set1 = new GreetingSetPO();
|
||||
set1.setName("a1");
|
||||
|
||||
GreetingSetPO set2 = new GreetingSetPO();
|
||||
set2.setName("a2");
|
||||
|
||||
// Revision 1
|
||||
em.getTransaction().begin();
|
||||
|
||||
em.persist(set1);
|
||||
em.persist(set2);
|
||||
|
||||
set1_id = set1.getId();
|
||||
set2_id = set2.getId();
|
||||
|
||||
em.getTransaction().commit();
|
||||
em.clear();
|
||||
|
||||
// Revision 2
|
||||
em.getTransaction().begin();
|
||||
|
||||
GreetingPO g1 = new GreetingPO();
|
||||
g1.setGreeting("g1");
|
||||
g1.setGreetingSet(em.getReference(GreetingSetPO.class, set1_id));
|
||||
|
||||
em.persist(g1);
|
||||
g1_id = g1.getId();
|
||||
|
||||
em.getTransaction().commit();
|
||||
em.clear();
|
||||
|
||||
// Revision 3
|
||||
em.getTransaction().begin();
|
||||
|
||||
g1 = em.find(GreetingPO.class, g1_id);
|
||||
|
||||
g1.setGreetingSet(em.getReference(GreetingSetPO.class, set2_id));
|
||||
|
||||
em.getTransaction().commit();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRevisionsCounts() {
|
||||
assert Arrays.asList(2, 3).equals(getAuditReader().getRevisions(GreetingPO.class, g1_id));
|
||||
|
||||
assert Arrays.asList(1, 2, 3).equals(getAuditReader().getRevisions(GreetingSetPO.class, set1_id));
|
||||
assert Arrays.asList(1, 3).equals(getAuditReader().getRevisions(GreetingSetPO.class, set2_id));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHistoryOfG1() {
|
||||
GreetingPO rev1 = getAuditReader().find(GreetingPO.class, g1_id, 1);
|
||||
GreetingPO rev2 = getAuditReader().find(GreetingPO.class, g1_id, 2);
|
||||
GreetingPO rev3 = getAuditReader().find(GreetingPO.class, g1_id, 3);
|
||||
|
||||
assert rev1 == null;
|
||||
assert rev2.getGreetingSet().getName().equals("a1");
|
||||
assert rev3.getGreetingSet().getName().equals("a2");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHistoryOfSet1() {
|
||||
GreetingSetPO rev1 = getAuditReader().find(GreetingSetPO.class, set1_id, 1);
|
||||
GreetingSetPO rev2 = getAuditReader().find(GreetingSetPO.class, set1_id, 2);
|
||||
GreetingSetPO rev3 = getAuditReader().find(GreetingSetPO.class, set1_id, 3);
|
||||
|
||||
assert rev1.getName().equals("a1");
|
||||
assert rev2.getName().equals("a1");
|
||||
assert rev3.getName().equals("a1");
|
||||
|
||||
GreetingPO g1 = new GreetingPO();
|
||||
g1.setId(g1_id);
|
||||
g1.setGreeting("g1");
|
||||
|
||||
assert rev1.getGreetings().size() == 0;
|
||||
assert rev2.getGreetings().equals(TestTools.makeSet(g1));
|
||||
assert rev3.getGreetings().size() == 0;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHistoryOfSet2() {
|
||||
GreetingSetPO rev1 = getAuditReader().find(GreetingSetPO.class, set2_id, 1);
|
||||
GreetingSetPO rev2 = getAuditReader().find(GreetingSetPO.class, set2_id, 2);
|
||||
GreetingSetPO rev3 = getAuditReader().find(GreetingSetPO.class, set2_id, 3);
|
||||
|
||||
assert rev1.getName().equals("a2");
|
||||
assert rev2.getName().equals("a2");
|
||||
assert rev3.getName().equals("a2");
|
||||
|
||||
GreetingPO g1 = new GreetingPO();
|
||||
g1.setId(g1_id);
|
||||
g1.setGreeting("g1");
|
||||
|
||||
assert rev1.getGreetings().size() == 0;
|
||||
assert rev2.getGreetings().size() == 0;
|
||||
assert rev3.getGreetings().equals(TestTools.makeSet(g1));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,65 @@
|
|||
package org.hibernate.envers.test.integration.reference;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.ManyToOne;
|
||||
|
||||
import org.hibernate.envers.Audited;
|
||||
|
||||
@Entity
|
||||
@Audited
|
||||
public class GreetingPO {
|
||||
@Id
|
||||
@GeneratedValue
|
||||
private Long id;
|
||||
|
||||
private String theGreeting;
|
||||
|
||||
@ManyToOne
|
||||
private GreetingSetPO greetingSet;
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getGreeting() {
|
||||
return theGreeting;
|
||||
}
|
||||
|
||||
public void setGreeting(String greeting) {
|
||||
this.theGreeting = greeting;
|
||||
}
|
||||
|
||||
public GreetingSetPO getGreetingSet() {
|
||||
return greetingSet;
|
||||
}
|
||||
|
||||
public void setGreetingSet(GreetingSetPO greetingSet) {
|
||||
this.greetingSet = greetingSet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof GreetingPO)) return false;
|
||||
|
||||
GreetingPO that = (GreetingPO) o;
|
||||
|
||||
if (id != null ? !id.equals(that.id) : that.id != null) return false;
|
||||
if (theGreeting != null ? !theGreeting.equals(that.theGreeting) : that.theGreeting != null) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = id != null ? id.hashCode() : 0;
|
||||
result = 31 * result + (theGreeting != null ? theGreeting.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
package org.hibernate.envers.test.integration.reference;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.OneToMany;
|
||||
|
||||
import org.hibernate.envers.Audited;
|
||||
|
||||
@Entity
|
||||
@Audited
|
||||
public class GreetingSetPO {
|
||||
@Id
|
||||
@GeneratedValue
|
||||
private Long id;
|
||||
|
||||
private String name;
|
||||
|
||||
@OneToMany(mappedBy = "greetingSet")
|
||||
private Set<GreetingPO> greetings;
|
||||
|
||||
public Long getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Long id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public Set<GreetingPO> getGreetings() {
|
||||
return greetings;
|
||||
}
|
||||
|
||||
public void setGreetings(Set<GreetingPO> greetings) {
|
||||
this.greetings = greetings;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof GreetingSetPO)) return false;
|
||||
|
||||
GreetingSetPO that = (GreetingSetPO) o;
|
||||
|
||||
if (id != null ? !id.equals(that.id) : that.id != null) return false;
|
||||
if (name != null ? !name.equals(that.name) : that.name != null) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = id != null ? id.hashCode() : 0;
|
||||
result = 31 * result + (name != null ? name.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
}
|
|
@ -45,6 +45,7 @@
|
|||
<package name="org.hibernate.envers.test.integration.properties" />
|
||||
<package name="org.hibernate.envers.test.integration.query" />
|
||||
<package name="org.hibernate.envers.test.integration.query.ids" />
|
||||
<package name="org.hibernate.envers.test.integration.reference" />
|
||||
<package name="org.hibernate.envers.test.integration.reventity" />
|
||||
<package name="org.hibernate.envers.test.integration.revfordate" />
|
||||
<package name="org.hibernate.envers.test.integration.sameids" />
|
||||
|
|
Loading…
Reference in New Issue