HHH-4694:
- support for indexed "fake" bidirectional relations - adding a field-calculation-phase, after all metadata is read from annotations, but before any audit entities generation is done git-svn-id: https://svn.jboss.org/repos/hibernate/core/trunk@18236 1b8cb986-b30d-0410-93ca-fae66ebed9b2
This commit is contained in:
parent
5a6686810b
commit
a90cf3e5eb
|
@ -1,7 +1,12 @@
|
|||
package org.hibernate.envers.configuration;
|
||||
|
||||
import org.hibernate.envers.configuration.metadata.reader.ClassAuditingData;
|
||||
import org.hibernate.envers.configuration.metadata.reader.PropertyAuditingData;
|
||||
import org.hibernate.envers.tools.MappingTools;
|
||||
import org.hibernate.mapping.PersistentClass;
|
||||
import org.hibernate.MappingException;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
@ -13,6 +18,8 @@ import java.util.LinkedHashMap;
|
|||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public class ClassesAuditingData {
|
||||
private static final Logger log = LoggerFactory.getLogger(ClassesAuditingData.class);
|
||||
|
||||
private final Map<String, ClassAuditingData> entityNameToAuditingData = new HashMap<String, ClassAuditingData>();
|
||||
private final Map<PersistentClass, ClassAuditingData> persistentClassToAuditingData = new LinkedHashMap<PersistentClass, ClassAuditingData>();
|
||||
|
||||
|
@ -40,4 +47,50 @@ public class ClassesAuditingData {
|
|||
public ClassAuditingData getClassAuditingData(String entityName) {
|
||||
return entityNameToAuditingData.get(entityName);
|
||||
}
|
||||
|
||||
/**
|
||||
* After all meta-data is read, updates calculated fields. This includes:
|
||||
* <ul>
|
||||
* <li>setting {@code forceInsertable} to {@code true} for properties specified by {@code @AuditMappedBy}</li>
|
||||
* </ul>
|
||||
*/
|
||||
public void updateCalculatedFields() {
|
||||
for (Map.Entry<PersistentClass, ClassAuditingData> classAuditingDataEntry : persistentClassToAuditingData.entrySet()) {
|
||||
PersistentClass pc = classAuditingDataEntry.getKey();
|
||||
ClassAuditingData classAuditingData = classAuditingDataEntry.getValue();
|
||||
for (String propertyName : classAuditingData.getPropertyNames()) {
|
||||
PropertyAuditingData propertyAuditingData = classAuditingData.getPropertyAuditingData(propertyName);
|
||||
// If a property had the @AuditMappedBy annotation, setting the referenced fields to be always insertable.
|
||||
if (propertyAuditingData.getAuditMappedBy() != null) {
|
||||
String referencedEntityName = MappingTools.getReferencedEntityName(pc.getProperty(propertyName).getValue());
|
||||
|
||||
ClassAuditingData referencedClassAuditingData = entityNameToAuditingData.get(referencedEntityName);
|
||||
|
||||
forcePropertyInsertable(referencedClassAuditingData, propertyAuditingData.getAuditMappedBy(),
|
||||
pc.getEntityName(), referencedEntityName);
|
||||
|
||||
forcePropertyInsertable(referencedClassAuditingData, propertyAuditingData.getPositionMappedBy(),
|
||||
pc.getEntityName(), referencedEntityName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void forcePropertyInsertable(ClassAuditingData classAuditingData, String propertyName,
|
||||
String entityName, String referencedEntityName) {
|
||||
if (propertyName != null) {
|
||||
if (classAuditingData.getPropertyAuditingData(propertyName) == null) {
|
||||
throw new MappingException("@AuditMappedBy points to a property that doesn't exist: " +
|
||||
referencedEntityName + "." + propertyName);
|
||||
}
|
||||
|
||||
log.debug("Non-insertable property " + referencedEntityName + "." + propertyName +
|
||||
" will be made insertable because a matching @AuditMappedBy was found in the " +
|
||||
entityName + " entity.");
|
||||
|
||||
classAuditingData
|
||||
.getPropertyAuditingData(propertyName)
|
||||
.setForceInsertable(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -80,6 +80,9 @@ public class EntitiesConfigurator {
|
|||
classesAuditingData.addClassAuditingData(pc, auditData);
|
||||
}
|
||||
|
||||
// Now that all information is read we can update the calculated fields.
|
||||
classesAuditingData.updateCalculatedFields();
|
||||
|
||||
AuditMetadataGenerator auditMetaGen = new AuditMetadataGenerator(cfg, globalCfg, verEntCfg,
|
||||
revisionInfoRelationMapping, auditEntityNameRegister, classesAuditingData);
|
||||
|
||||
|
|
|
@ -66,7 +66,7 @@ public final class BasicMetadataGenerator {
|
|||
Value value, SimpleMapperBuilder mapper, boolean insertable, boolean key) {
|
||||
if (parent != null) {
|
||||
Element prop_mapping = MetadataTools.addProperty(parent, propertyAuditingData.getName(),
|
||||
value.getType().getName(), insertable, key);
|
||||
value.getType().getName(), propertyAuditingData.isForceInsertable() || insertable, key);
|
||||
MetadataTools.addColumns(prop_mapping, (Iterator<Column>) value.getColumnIterator());
|
||||
}
|
||||
|
||||
|
|
|
@ -43,13 +43,10 @@ import org.hibernate.envers.entities.IdMappingData;
|
|||
import org.hibernate.envers.entities.PropertyData;
|
||||
import org.hibernate.envers.entities.mapper.CompositeMapperBuilder;
|
||||
import org.hibernate.envers.entities.mapper.PropertyMapper;
|
||||
import org.hibernate.envers.entities.mapper.SinglePropertyMapper;
|
||||
import org.hibernate.envers.entities.mapper.id.IdMapper;
|
||||
import org.hibernate.envers.entities.mapper.relation.*;
|
||||
import org.hibernate.envers.entities.mapper.relation.component.MiddleDummyComponentMapper;
|
||||
import org.hibernate.envers.entities.mapper.relation.component.MiddleMapKeyIdComponentMapper;
|
||||
import org.hibernate.envers.entities.mapper.relation.component.MiddleMapKeyPropertyComponentMapper;
|
||||
import org.hibernate.envers.entities.mapper.relation.component.MiddleRelatedComponentMapper;
|
||||
import org.hibernate.envers.entities.mapper.relation.component.MiddleSimpleComponentMapper;
|
||||
import org.hibernate.envers.entities.mapper.relation.component.*;
|
||||
import org.hibernate.envers.entities.mapper.relation.lazy.proxy.ListProxy;
|
||||
import org.hibernate.envers.entities.mapper.relation.lazy.proxy.MapProxy;
|
||||
import org.hibernate.envers.entities.mapper.relation.lazy.proxy.SetProxy;
|
||||
|
@ -68,7 +65,6 @@ import org.hibernate.mapping.OneToMany;
|
|||
import org.hibernate.mapping.PersistentClass;
|
||||
import org.hibernate.mapping.Property;
|
||||
import org.hibernate.mapping.Table;
|
||||
import org.hibernate.mapping.ToOne;
|
||||
import org.hibernate.mapping.Value;
|
||||
import org.hibernate.type.BagType;
|
||||
import org.hibernate.type.ListType;
|
||||
|
@ -132,17 +128,7 @@ public final class CollectionMetadataGenerator {
|
|||
throw new MappingException("Unable to read auditing configuration for " + referencingEntityName + "!");
|
||||
}
|
||||
|
||||
referencedEntityName = getReferencedEntityName(propertyValue.getElement());
|
||||
}
|
||||
|
||||
private String getReferencedEntityName(Value value) {
|
||||
if (value instanceof ToOne) {
|
||||
return ((ToOne) value).getReferencedEntityName();
|
||||
} else if (value instanceof OneToMany) {
|
||||
return ((OneToMany) value).getReferencedEntityName();
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
referencedEntityName = MappingTools.getReferencedEntityName(propertyValue.getElement());
|
||||
}
|
||||
|
||||
void addCollection() {
|
||||
|
@ -206,10 +192,8 @@ public final class CollectionMetadataGenerator {
|
|||
propertyAuditingData.getPropertyData(),
|
||||
referencingIdData, queryGenerator);
|
||||
|
||||
// Checking the type of the collection and adding an appropriate mapper.
|
||||
addMapper(commonCollectionMapperData, elementComponentData, indexComponentData);
|
||||
|
||||
PropertyMapper fakeBidirectionalRelationMapper;
|
||||
PropertyMapper fakeBidirectionalRelationIndexMapper;
|
||||
if (fakeOneToManyBidirectional) {
|
||||
// In case of a fake many-to-one bidirectional relation, we have to generate a mapper which maps
|
||||
// the mapped-by property name to the id of the related entity (which is the owner of the collection).
|
||||
|
@ -225,13 +209,29 @@ public final class CollectionMetadataGenerator {
|
|||
// when constructing the PropertyData.
|
||||
new PropertyData(auditMappedBy, null, null, null),
|
||||
referencedEntityName, false);
|
||||
|
||||
// Checking if there's an index defined. If so, adding a mapper for it.
|
||||
if (propertyAuditingData.getPositionMappedBy() != null) {
|
||||
String positionMappedBy = propertyAuditingData.getPositionMappedBy();
|
||||
fakeBidirectionalRelationIndexMapper = new SinglePropertyMapper(new PropertyData(positionMappedBy, null, null, null));
|
||||
|
||||
// Also, overwriting the index component data to properly read the index.
|
||||
indexComponentData = new MiddleComponentData(new MiddleStraightComponentMapper(positionMappedBy), 0);
|
||||
} else {
|
||||
fakeBidirectionalRelationIndexMapper = null;
|
||||
}
|
||||
} else {
|
||||
fakeBidirectionalRelationMapper = null;
|
||||
fakeBidirectionalRelationIndexMapper = null;
|
||||
}
|
||||
|
||||
// Checking the type of the collection and adding an appropriate mapper.
|
||||
addMapper(commonCollectionMapperData, elementComponentData, indexComponentData);
|
||||
|
||||
// Storing information about this relation.
|
||||
referencingEntityConfiguration.addToManyNotOwningRelation(propertyName, mappedBy,
|
||||
referencedEntityName, referencingIdData.getPrefixedMapper(), fakeBidirectionalRelationMapper);
|
||||
referencedEntityName, referencingIdData.getPrefixedMapper(), fakeBidirectionalRelationMapper,
|
||||
fakeBidirectionalRelationIndexMapper);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -257,7 +257,7 @@ public final class CollectionMetadataGenerator {
|
|||
if (value.getElement() instanceof OneToMany && !value.isInverse()) {
|
||||
// This must be a @JoinColumn+@OneToMany mapping. Generating the table name, as Hibernate doesn't use a
|
||||
// middle table for mapping this relation.
|
||||
return StringTools.getLastComponent(entityName) + "_" + StringTools.getLastComponent(getReferencedEntityName(value.getElement()));
|
||||
return StringTools.getLastComponent(entityName) + "_" + StringTools.getLastComponent(MappingTools.getReferencedEntityName(value.getElement()));
|
||||
} else {
|
||||
// Hibernate uses a middle table for mapping this relation, so we get it's name directly.
|
||||
return value.getCollectionTable().getName();
|
||||
|
@ -421,7 +421,7 @@ public final class CollectionMetadataGenerator {
|
|||
if (type instanceof ManyToOneType) {
|
||||
String prefixRelated = prefix + "_";
|
||||
|
||||
String referencedEntityName = getReferencedEntityName(value);
|
||||
String referencedEntityName = MappingTools.getReferencedEntityName(value);
|
||||
|
||||
IdMappingData referencedIdMapping = mainGenerator.getReferencedIdMappingData(referencingEntityName,
|
||||
referencedEntityName, propertyAuditingData, true);
|
||||
|
@ -447,7 +447,7 @@ public final class CollectionMetadataGenerator {
|
|||
} else {
|
||||
// Last but one parameter: collection components are always insertable
|
||||
boolean mapped = mainGenerator.getBasicMetadataGenerator().addBasic(xmlMapping,
|
||||
new PropertyAuditingData(prefix, "field", ModificationStore.FULL, RelationTargetAuditMode.AUDITED, null, null),
|
||||
new PropertyAuditingData(prefix, "field", ModificationStore.FULL, RelationTargetAuditMode.AUDITED, null, null, false),
|
||||
value, null, true, true);
|
||||
|
||||
if (mapped) {
|
||||
|
@ -533,31 +533,14 @@ public final class CollectionMetadataGenerator {
|
|||
return middleEntityXmlId;
|
||||
}
|
||||
|
||||
private String getMappedByCommon(PersistentClass referencedClass) {
|
||||
// If there's an @AuditMappedBy specified, returning it directly.
|
||||
String auditMappedBy = propertyAuditingData.getAuditMappedBy();
|
||||
if (auditMappedBy != null) {
|
||||
// Checking that the property exists.
|
||||
try {
|
||||
referencedClass.getProperty(auditMappedBy);
|
||||
} catch (MappingException me) {
|
||||
throw new MappingException("@AuditMappedBy points to a property that can be read: " +
|
||||
referencedClass.getEntityName() + "." + auditMappedBy, me);
|
||||
}
|
||||
|
||||
return auditMappedBy;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
private String getMappedBy(Collection collectionValue) {
|
||||
PersistentClass referencedClass = ((OneToMany) collectionValue.getElement()).getAssociatedClass();
|
||||
|
||||
String mappedByCommon = getMappedByCommon(referencedClass);
|
||||
if (mappedByCommon != null) {
|
||||
return mappedByCommon;
|
||||
// If there's an @AuditMappedBy specified, returning it directly.
|
||||
String auditMappedBy = propertyAuditingData.getAuditMappedBy();
|
||||
if (auditMappedBy != null) {
|
||||
return auditMappedBy;
|
||||
}
|
||||
|
||||
Iterator<Property> assocClassProps = referencedClass.getPropertyIterator();
|
||||
|
@ -577,9 +560,10 @@ public final class CollectionMetadataGenerator {
|
|||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
private String getMappedBy(Table collectionTable, PersistentClass referencedClass) {
|
||||
String mappedByCommon = getMappedByCommon(referencedClass);
|
||||
if (mappedByCommon != null) {
|
||||
return mappedByCommon;
|
||||
// If there's an @AuditMappedBy specified, returning it directly.
|
||||
String auditMappedBy = propertyAuditingData.getAuditMappedBy();
|
||||
if (auditMappedBy != null) {
|
||||
return auditMappedBy;
|
||||
}
|
||||
|
||||
Iterator<Property> properties = referencedClass.getPropertyIterator();
|
||||
|
|
|
@ -139,6 +139,6 @@ public final class IdMetadataGenerator {
|
|||
|
||||
private PropertyAuditingData getIdPersistentPropertyAuditingData(Property property) {
|
||||
return new PropertyAuditingData(property.getName(), property.getPropertyAccessorName(),
|
||||
ModificationStore.FULL, RelationTargetAuditMode.AUDITED, null, null);
|
||||
ModificationStore.FULL, RelationTargetAuditMode.AUDITED, null, null, false);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,6 +24,8 @@
|
|||
package org.hibernate.envers.configuration.metadata;
|
||||
|
||||
import org.dom4j.Element;
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.envers.configuration.metadata.reader.PropertyAuditingData;
|
||||
import org.hibernate.envers.entities.EntityConfiguration;
|
||||
import org.hibernate.envers.entities.IdMappingData;
|
||||
import org.hibernate.envers.entities.PropertyData;
|
||||
|
@ -31,24 +33,16 @@ import org.hibernate.envers.entities.mapper.CompositeMapperBuilder;
|
|||
import org.hibernate.envers.entities.mapper.id.IdMapper;
|
||||
import org.hibernate.envers.entities.mapper.relation.OneToOneNotOwningMapper;
|
||||
import org.hibernate.envers.entities.mapper.relation.ToOneIdMapper;
|
||||
import org.hibernate.envers.configuration.metadata.reader.PropertyAuditingData;
|
||||
import org.hibernate.envers.configuration.metadata.reader.ClassAuditingData;
|
||||
import org.hibernate.envers.tools.MappingTools;
|
||||
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.mapping.OneToOne;
|
||||
import org.hibernate.mapping.ToOne;
|
||||
import org.hibernate.mapping.Value;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Generates metadata for to-one relations (reference-valued properties).
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public final class ToOneRelationMetadataGenerator {
|
||||
private static final Logger log = LoggerFactory.getLogger(ToOneRelationMetadataGenerator.class);
|
||||
|
||||
private final AuditMetadataGenerator mainGenerator;
|
||||
|
||||
ToOneRelationMetadataGenerator(AuditMetadataGenerator auditMetadataGenerator) {
|
||||
|
@ -79,23 +73,12 @@ public final class ToOneRelationMetadataGenerator {
|
|||
// the entity that didn't involve the relation, it's value will then be stored properly. In case of changes
|
||||
// to the entity that did involve the relation, it's the responsibility of the collection side to store the
|
||||
// proper data.
|
||||
boolean nonInsertableFake = false;
|
||||
if (!insertable) {
|
||||
ClassAuditingData referencedAuditingData = mainGenerator.getClassesAuditingData().getClassAuditingData(referencedEntityName);
|
||||
|
||||
// Looking through the properties of the referenced entity to find the right property.
|
||||
for (String referencedPropertyName : referencedAuditingData.getPropertyNames()) {
|
||||
String auditMappedBy = referencedAuditingData.getPropertyAuditingData(referencedPropertyName).getAuditMappedBy();
|
||||
if (propertyAuditingData.getName().equals(auditMappedBy)) {
|
||||
log.debug("Non-insertable property " + entityName + "." + propertyAuditingData.getName() +
|
||||
" will be made insertable because a matching @AuditMappedBy was found in the " +
|
||||
referencedEntityName + " entity.");
|
||||
|
||||
insertable = true;
|
||||
nonInsertableFake = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
boolean nonInsertableFake;
|
||||
if (!insertable && propertyAuditingData.isForceInsertable()) {
|
||||
nonInsertableFake = true;
|
||||
insertable = true;
|
||||
} else {
|
||||
nonInsertableFake = false;
|
||||
}
|
||||
|
||||
// Adding an element to the mapping corresponding to the references entity id's
|
||||
|
|
|
@ -48,13 +48,15 @@ public class PropertyAuditingData {
|
|||
private RelationTargetAuditMode relationTargetAuditMode;
|
||||
private String auditMappedBy;
|
||||
private String positionMappedBy;
|
||||
private boolean forceInsertable;
|
||||
|
||||
public PropertyAuditingData() {
|
||||
}
|
||||
|
||||
public PropertyAuditingData(String name, String accessType, ModificationStore store,
|
||||
RelationTargetAuditMode relationTargetAuditMode,
|
||||
String auditMappedBy, String positionMappedBy) {
|
||||
String auditMappedBy, String positionMappedBy,
|
||||
boolean forceInsertable) {
|
||||
this.name = name;
|
||||
this.beanName = name;
|
||||
this.accessType = accessType;
|
||||
|
@ -62,6 +64,7 @@ public class PropertyAuditingData {
|
|||
this.relationTargetAuditMode = relationTargetAuditMode;
|
||||
this.auditMappedBy = auditMappedBy;
|
||||
this.positionMappedBy = positionMappedBy;
|
||||
this.forceInsertable = forceInsertable;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
|
@ -136,6 +139,14 @@ public class PropertyAuditingData {
|
|||
this.positionMappedBy = positionMappedBy;
|
||||
}
|
||||
|
||||
public boolean isForceInsertable() {
|
||||
return forceInsertable;
|
||||
}
|
||||
|
||||
public void setForceInsertable(boolean forceInsertable) {
|
||||
this.forceInsertable = forceInsertable;
|
||||
}
|
||||
|
||||
public void addAuditingOverride(AuditOverride annotation) {
|
||||
if (annotation != null) {
|
||||
String overrideName = annotation.name();
|
||||
|
|
|
@ -53,29 +53,31 @@ public class EntityConfiguration {
|
|||
|
||||
public void addToOneRelation(String fromPropertyName, String toEntityName, IdMapper idMapper, boolean insertable) {
|
||||
relations.put(fromPropertyName, new RelationDescription(fromPropertyName, RelationType.TO_ONE,
|
||||
toEntityName, null, idMapper, null, insertable));
|
||||
toEntityName, null, idMapper, null, null, insertable));
|
||||
}
|
||||
|
||||
public void addToOneNotOwningRelation(String fromPropertyName, String mappedByPropertyName, String toEntityName,
|
||||
IdMapper idMapper) {
|
||||
IdMapper idMapper) {
|
||||
relations.put(fromPropertyName, new RelationDescription(fromPropertyName, RelationType.TO_ONE_NOT_OWNING,
|
||||
toEntityName, mappedByPropertyName, idMapper, null, true));
|
||||
toEntityName, mappedByPropertyName, idMapper, null, null, true));
|
||||
}
|
||||
|
||||
public void addToManyNotOwningRelation(String fromPropertyName, String mappedByPropertyName, String toEntityName,
|
||||
IdMapper idMapper, PropertyMapper fakeBidirectionalRelationMapper) {
|
||||
IdMapper idMapper, PropertyMapper fakeBidirectionalRelationMapper,
|
||||
PropertyMapper fakeBidirectionalRelationIndexMapper) {
|
||||
relations.put(fromPropertyName, new RelationDescription(fromPropertyName, RelationType.TO_MANY_NOT_OWNING,
|
||||
toEntityName, mappedByPropertyName, idMapper, fakeBidirectionalRelationMapper, true));
|
||||
toEntityName, mappedByPropertyName, idMapper, fakeBidirectionalRelationMapper,
|
||||
fakeBidirectionalRelationIndexMapper, true));
|
||||
}
|
||||
|
||||
public void addToManyMiddleRelation(String fromPropertyName, String toEntityName) {
|
||||
relations.put(fromPropertyName, new RelationDescription(fromPropertyName, RelationType.TO_MANY_MIDDLE,
|
||||
toEntityName, null, null, null, true));
|
||||
toEntityName, null, null, null, null, true));
|
||||
}
|
||||
|
||||
public void addToManyMiddleNotOwningRelation(String fromPropertyName, String mappedByPropertyName, String toEntityName) {
|
||||
relations.put(fromPropertyName, new RelationDescription(fromPropertyName, RelationType.TO_MANY_MIDDLE_NOT_OWNING,
|
||||
toEntityName, mappedByPropertyName, null, null, true));
|
||||
toEntityName, mappedByPropertyName, null, null, null, true));
|
||||
}
|
||||
|
||||
public boolean isRelation(String propertyName) {
|
||||
|
|
|
@ -36,18 +36,21 @@ public class RelationDescription {
|
|||
private final String mappedByPropertyName;
|
||||
private final IdMapper idMapper;
|
||||
private final PropertyMapper fakeBidirectionalRelationMapper;
|
||||
private final PropertyMapper fakeBidirectionalRelationIndexMapper;
|
||||
private final boolean insertable;
|
||||
private boolean bidirectional;
|
||||
|
||||
public RelationDescription(String fromPropertyName, RelationType relationType, String toEntityName,
|
||||
String mappedByPropertyName, IdMapper idMapper,
|
||||
PropertyMapper fakeBidirectionalRelationMapper, boolean insertable) {
|
||||
PropertyMapper fakeBidirectionalRelationMapper,
|
||||
PropertyMapper fakeBidirectionalRelationIndexMapper, boolean insertable) {
|
||||
this.fromPropertyName = fromPropertyName;
|
||||
this.relationType = relationType;
|
||||
this.toEntityName = toEntityName;
|
||||
this.mappedByPropertyName = mappedByPropertyName;
|
||||
this.idMapper = idMapper;
|
||||
this.fakeBidirectionalRelationMapper = fakeBidirectionalRelationMapper;
|
||||
this.fakeBidirectionalRelationIndexMapper = fakeBidirectionalRelationIndexMapper;
|
||||
this.insertable = insertable;
|
||||
|
||||
this.bidirectional = false;
|
||||
|
@ -77,6 +80,10 @@ public class RelationDescription {
|
|||
return fakeBidirectionalRelationMapper;
|
||||
}
|
||||
|
||||
public PropertyMapper getFakeBidirectionalRelationIndexMapper() {
|
||||
return fakeBidirectionalRelationIndexMapper;
|
||||
}
|
||||
|
||||
public boolean isInsertable() {
|
||||
return insertable;
|
||||
}
|
||||
|
|
|
@ -23,10 +23,12 @@
|
|||
*/
|
||||
package org.hibernate.envers.entities.mapper;
|
||||
|
||||
import org.hibernate.envers.tools.Pair;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Data describing the change of a single object in a persisten collection (when the object was added, removed or
|
||||
* Data describing the change of a single object in a persistent collection (when the object was added, removed or
|
||||
* modified in the collection).
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
|
@ -54,10 +56,32 @@ public class PersistentCollectionChangeData {
|
|||
}
|
||||
|
||||
/**
|
||||
* For use by bi-directional associations.
|
||||
* @return The affected element, which was changed (added, removed, modified) in the collection.
|
||||
*/
|
||||
public Object getChangedElement() {
|
||||
if (changedElement instanceof Pair) {
|
||||
return ((Pair) changedElement).getSecond();
|
||||
}
|
||||
|
||||
if (changedElement instanceof Map.Entry) {
|
||||
return ((Map.Entry) changedElement).getValue();
|
||||
}
|
||||
|
||||
return changedElement;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Index of the affected element, or {@code null} if the collection isn't indexed.
|
||||
*/
|
||||
public Object getChangedElementIndex() {
|
||||
if (changedElement instanceof Pair) {
|
||||
return ((Pair) changedElement).getFirst();
|
||||
}
|
||||
|
||||
if (changedElement instanceof Map.Entry) {
|
||||
return ((Map.Entry) changedElement).getKey();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -47,6 +47,10 @@ import org.hibernate.HibernateException;
|
|||
public class SinglePropertyMapper implements PropertyMapper, SimpleMapperBuilder {
|
||||
private PropertyData propertyData;
|
||||
|
||||
public SinglePropertyMapper(PropertyData propertyData) {
|
||||
this.propertyData = propertyData;
|
||||
}
|
||||
|
||||
public SinglePropertyMapper() { }
|
||||
|
||||
public void add(PropertyData propertyData) {
|
||||
|
|
|
@ -70,7 +70,6 @@ public abstract class AbstractCollectionMapper<T> implements PropertyMapper {
|
|||
|
||||
protected abstract Collection getNewCollectionContent(PersistentCollection newCollection);
|
||||
protected abstract Collection getOldCollectionContent(Serializable oldCollection);
|
||||
protected abstract Object getElement(Object changedObject);
|
||||
|
||||
/**
|
||||
* Maps the changed collection element to the given map.
|
||||
|
@ -87,7 +86,7 @@ public abstract class AbstractCollectionMapper<T> implements PropertyMapper {
|
|||
entityData.put(commonCollectionMapperData.getVerEntCfg().getOriginalIdPropName(), originalId);
|
||||
|
||||
collectionChanges.add(new PersistentCollectionChangeData(
|
||||
commonCollectionMapperData.getVersionsMiddleEntityName(), entityData, getElement(changedObj)));
|
||||
commonCollectionMapperData.getVersionsMiddleEntityName(), entityData, changedObj));
|
||||
// Mapping the collection owner's id.
|
||||
commonCollectionMapperData.getReferencingIdData().getPrefixedMapper().mapToMapFromId(originalId, id);
|
||||
|
||||
|
|
|
@ -71,8 +71,4 @@ public final class BasicCollectionMapper<T extends Collection> extends AbstractC
|
|||
protected void mapToMapFromObject(Map<String, Object> data, Object changed) {
|
||||
elementComponentData.getComponentMapper().mapToMapFromObject(data, changed);
|
||||
}
|
||||
|
||||
protected Object getElement(Object changedObject) {
|
||||
return changedObject;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -83,9 +83,4 @@ public final class ListCollectionMapper extends AbstractCollectionMapper<List> i
|
|||
elementComponentData.getComponentMapper().mapToMapFromObject(data, indexValuePair.getSecond());
|
||||
indexComponentData.getComponentMapper().mapToMapFromObject(data, indexValuePair.getFirst());
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
protected Object getElement(Object changedObject) {
|
||||
return ((Pair<Integer, Object>) changedObject).getFirst();
|
||||
}
|
||||
}
|
|
@ -76,8 +76,4 @@ public final class MapCollectionMapper<T extends Map> extends AbstractCollection
|
|||
elementComponentData.getComponentMapper().mapToMapFromObject(data, ((Map.Entry) changed).getValue());
|
||||
indexComponentData.getComponentMapper().mapToMapFromObject(data, ((Map.Entry) changed).getKey());
|
||||
}
|
||||
|
||||
protected Object getElement(Object changedObject) {
|
||||
return ((Map.Entry) changedObject).getValue();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* 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.entities.mapper.relation.component;
|
||||
|
||||
import org.hibernate.envers.entities.EntityInstantiator;
|
||||
import org.hibernate.envers.tools.query.Parameters;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* A mapper for reading and writing a property straight to/from maps. This mapper cannot be used with middle tables,
|
||||
* but only with "fake" bidirectional indexed relations.
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public final class MiddleStraightComponentMapper implements MiddleComponentMapper {
|
||||
private final String propertyName;
|
||||
|
||||
public MiddleStraightComponentMapper(String propertyName) {
|
||||
this.propertyName = propertyName;
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
public Object mapToObjectFromFullMap(EntityInstantiator entityInstantiator, Map<String, Object> data,
|
||||
Object dataObject, Number revision) {
|
||||
return data.get(propertyName);
|
||||
}
|
||||
|
||||
public void mapToMapFromObject(Map<String, Object> data, Object obj) {
|
||||
data.put(propertyName, obj);
|
||||
}
|
||||
|
||||
public void addMiddleEqualToQuery(Parameters parameters, String prefix1, String prefix2) {
|
||||
throw new UnsupportedOperationException("Cannot use this mapper with a middle table!");
|
||||
}
|
||||
}
|
|
@ -239,7 +239,8 @@ public class AuditEventListener implements PostInsertEventListener, PostUpdateEv
|
|||
relatedId, relatedObj);
|
||||
|
||||
verSync.addWorkUnit(new FakeBidirectionalRelationWorkUnit(event.getSession(), relatedEntityName, verCfg,
|
||||
relatedId, referencingPropertyName, event.getAffectedOwnerOrNull(), rd, revType, nestedWorkUnit));
|
||||
relatedId, referencingPropertyName, event.getAffectedOwnerOrNull(), rd, revType,
|
||||
changeData.getChangedElementIndex(), nestedWorkUnit));
|
||||
}
|
||||
|
||||
// We also have to generate a collection change work unit for the owning entity.
|
||||
|
|
|
@ -28,13 +28,14 @@ public class FakeBidirectionalRelationWorkUnit extends AbstractAuditWorkUnit imp
|
|||
AuditConfiguration verCfg, Serializable id,
|
||||
String referencingPropertyName, Object owningEntity,
|
||||
RelationDescription rd, RevisionType revisionType,
|
||||
Object index,
|
||||
AuditWorkUnit nestedWorkUnit) {
|
||||
super(sessionImplementor, entityName, verCfg, id);
|
||||
this.nestedWorkUnit = nestedWorkUnit;
|
||||
|
||||
// Adding the change for the relation.
|
||||
fakeRelationChanges = new HashMap<String, FakeRelationChange>();
|
||||
fakeRelationChanges.put(referencingPropertyName, new FakeRelationChange(owningEntity, rd, revisionType));
|
||||
fakeRelationChanges.put(referencingPropertyName, new FakeRelationChange(owningEntity, rd, revisionType, index));
|
||||
}
|
||||
|
||||
public FakeBidirectionalRelationWorkUnit(FakeBidirectionalRelationWorkUnit original,
|
||||
|
@ -134,11 +135,14 @@ public class FakeBidirectionalRelationWorkUnit extends AbstractAuditWorkUnit imp
|
|||
private final Object owningEntity;
|
||||
private final RelationDescription rd;
|
||||
private final RevisionType revisionType;
|
||||
private final Object index;
|
||||
|
||||
public FakeRelationChange(Object owningEntity, RelationDescription rd, RevisionType revisionType) {
|
||||
public FakeRelationChange(Object owningEntity, RelationDescription rd, RevisionType revisionType,
|
||||
Object index) {
|
||||
this.owningEntity = owningEntity;
|
||||
this.rd = rd;
|
||||
this.revisionType = revisionType;
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
public RevisionType getRevisionType() {
|
||||
|
@ -150,6 +154,12 @@ public class FakeBidirectionalRelationWorkUnit extends AbstractAuditWorkUnit imp
|
|||
// new owner will in fact be null.
|
||||
rd.getFakeBidirectionalRelationMapper().mapToMapFromEntity(sessionImplementor, data,
|
||||
revisionType == RevisionType.DEL ? null : owningEntity, null);
|
||||
|
||||
// Also mapping the index, if the collection is indexed.
|
||||
if (rd.getFakeBidirectionalRelationIndexMapper() != null) {
|
||||
rd.getFakeBidirectionalRelationIndexMapper().mapToMapFromEntity(sessionImplementor, data,
|
||||
revisionType == RevisionType.DEL ? null : index, null);
|
||||
}
|
||||
}
|
||||
|
||||
public static FakeRelationChange merge(FakeRelationChange first, FakeRelationChange second) {
|
||||
|
|
|
@ -1,5 +1,10 @@
|
|||
package org.hibernate.envers.tools;
|
||||
|
||||
import org.hibernate.mapping.Collection;
|
||||
import org.hibernate.mapping.OneToMany;
|
||||
import org.hibernate.mapping.ToOne;
|
||||
import org.hibernate.mapping.Value;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
|
@ -20,4 +25,16 @@ public class MappingTools {
|
|||
public static String createToOneRelationPrefix(String referencePropertyName) {
|
||||
return referencePropertyName + "_";
|
||||
}
|
||||
|
||||
public static String getReferencedEntityName(Value value) {
|
||||
if (value instanceof ToOne) {
|
||||
return ((ToOne) value).getReferencedEntityName();
|
||||
} else if (value instanceof OneToMany) {
|
||||
return ((OneToMany) value).getReferencedEntityName();
|
||||
} else if (value instanceof Collection) {
|
||||
return getReferencedEntityName(((Collection) value).getElement());
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,96 @@
|
|||
package org.hibernate.envers.test.entities.onetomany.detached;
|
||||
|
||||
import org.hibernate.envers.Audited;
|
||||
|
||||
import javax.persistence.*;
|
||||
|
||||
/**
|
||||
* Entity for {@link org.hibernate.envers.test.integration.onetomany.detached.IndexedJoinColumnBidirectionalList} test.
|
||||
* Owned side of the relation.
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
@Entity
|
||||
@Audited
|
||||
public class IndexedListJoinColumnBidirectionalRefEdEntity {
|
||||
@Id
|
||||
@GeneratedValue
|
||||
private Integer id;
|
||||
|
||||
private String data;
|
||||
|
||||
@Column(name = "indexed_index", insertable = false, updatable = false)
|
||||
private Integer position;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "indexed_join_column", insertable = false, updatable = false)
|
||||
private IndexedListJoinColumnBidirectionalRefIngEntity owner;
|
||||
|
||||
public IndexedListJoinColumnBidirectionalRefEdEntity() { }
|
||||
|
||||
public IndexedListJoinColumnBidirectionalRefEdEntity(Integer id, String data, IndexedListJoinColumnBidirectionalRefIngEntity owner) {
|
||||
this.id = id;
|
||||
this.data = data;
|
||||
this.owner = owner;
|
||||
}
|
||||
|
||||
public IndexedListJoinColumnBidirectionalRefEdEntity(String data, IndexedListJoinColumnBidirectionalRefIngEntity owner) {
|
||||
this.data = data;
|
||||
this.owner = owner;
|
||||
}
|
||||
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public void setData(String data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public IndexedListJoinColumnBidirectionalRefIngEntity getOwner() {
|
||||
return owner;
|
||||
}
|
||||
|
||||
public void setOwner(IndexedListJoinColumnBidirectionalRefIngEntity owner) {
|
||||
this.owner = owner;
|
||||
}
|
||||
|
||||
public Integer getPosition() {
|
||||
return position;
|
||||
}
|
||||
|
||||
public void setPosition(Integer position) {
|
||||
this.position = position;
|
||||
}
|
||||
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof IndexedListJoinColumnBidirectionalRefEdEntity)) return false;
|
||||
|
||||
IndexedListJoinColumnBidirectionalRefEdEntity that = (IndexedListJoinColumnBidirectionalRefEdEntity) o;
|
||||
|
||||
if (data != null ? !data.equals(that.data) : that.data != null) return false;
|
||||
//noinspection RedundantIfStatement
|
||||
if (id != null ? !id.equals(that.id) : that.id != null) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
int result;
|
||||
result = (id != null ? id.hashCode() : 0);
|
||||
result = 31 * result + (data != null ? data.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "IndexedListJoinColumnBidirectionalRefEdEntity(id = " + id + ", data = " + data + ")";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,92 @@
|
|||
package org.hibernate.envers.test.entities.onetomany.detached;
|
||||
|
||||
import org.hibernate.envers.Audited;
|
||||
import org.hibernate.envers.AuditMappedBy;
|
||||
import org.hibernate.annotations.IndexColumn;
|
||||
|
||||
import javax.persistence.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Entity for {@link org.hibernate.envers.test.integration.onetomany.detached.IndexedJoinColumnBidirectionalList} test.
|
||||
* Owning side of the relation.
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
@Entity
|
||||
@Audited
|
||||
public class IndexedListJoinColumnBidirectionalRefIngEntity {
|
||||
@Id
|
||||
@GeneratedValue
|
||||
private Integer id;
|
||||
|
||||
private String data;
|
||||
|
||||
@OneToMany
|
||||
@JoinColumn(name = "indexed_join_column")
|
||||
@IndexColumn(name = "indexed_index")
|
||||
@AuditMappedBy(mappedBy = "owner", positionMappedBy = "position")
|
||||
private List<IndexedListJoinColumnBidirectionalRefEdEntity> references;
|
||||
|
||||
public IndexedListJoinColumnBidirectionalRefIngEntity() { }
|
||||
|
||||
public IndexedListJoinColumnBidirectionalRefIngEntity(Integer id, String data, IndexedListJoinColumnBidirectionalRefEdEntity... references) {
|
||||
this.id = id;
|
||||
this.data = data;
|
||||
this.references = new ArrayList<IndexedListJoinColumnBidirectionalRefEdEntity>();
|
||||
this.references.addAll(Arrays.asList(references));
|
||||
}
|
||||
|
||||
public IndexedListJoinColumnBidirectionalRefIngEntity(String data, IndexedListJoinColumnBidirectionalRefEdEntity... references) {
|
||||
this(null, data, references);
|
||||
}
|
||||
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public void setData(String data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public List<IndexedListJoinColumnBidirectionalRefEdEntity> getReferences() {
|
||||
return references;
|
||||
}
|
||||
|
||||
public void setReferences(List<IndexedListJoinColumnBidirectionalRefEdEntity> references) {
|
||||
this.references = references;
|
||||
}
|
||||
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof IndexedListJoinColumnBidirectionalRefIngEntity)) return false;
|
||||
|
||||
IndexedListJoinColumnBidirectionalRefIngEntity that = (IndexedListJoinColumnBidirectionalRefIngEntity) o;
|
||||
|
||||
if (data != null ? !data.equals(that.data) : that.data != null) return false;
|
||||
//noinspection RedundantIfStatement
|
||||
if (id != null ? !id.equals(that.id) : that.id != null) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
int result;
|
||||
result = (id != null ? id.hashCode() : 0);
|
||||
result = 31 * result + (data != null ? data.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "IndexedListJoinColumnBidirectionalRefIngEntity(id = " + id + ", data = " + data + ")";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,250 @@
|
|||
/*
|
||||
* 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.onetomany.detached;
|
||||
|
||||
import org.hibernate.ejb.Ejb3Configuration;
|
||||
import org.hibernate.envers.test.AbstractEntityTest;
|
||||
import org.hibernate.envers.test.entities.onetomany.detached.IndexedListJoinColumnBidirectionalRefIngEntity;
|
||||
import org.hibernate.envers.test.entities.onetomany.detached.IndexedListJoinColumnBidirectionalRefEdEntity;
|
||||
import static org.testng.Assert.assertEquals;
|
||||
import static org.testng.Assert.assertTrue;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Test for a "fake" bidirectional mapping where one side uses @OneToMany+@JoinColumn (and thus owns the relatin),
|
||||
* and the other uses a @ManyToOne(insertable=false, updatable=false).
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public class IndexedJoinColumnBidirectionalList extends AbstractEntityTest {
|
||||
private Integer ed1_id;
|
||||
private Integer ed2_id;
|
||||
private Integer ed3_id;
|
||||
|
||||
private Integer ing1_id;
|
||||
private Integer ing2_id;
|
||||
|
||||
public void configure(Ejb3Configuration cfg) {
|
||||
cfg.addAnnotatedClass(IndexedListJoinColumnBidirectionalRefIngEntity.class);
|
||||
cfg.addAnnotatedClass(IndexedListJoinColumnBidirectionalRefEdEntity.class);
|
||||
}
|
||||
|
||||
@Test(enabled = true)
|
||||
public void createData() {
|
||||
EntityManager em = getEntityManager();
|
||||
|
||||
IndexedListJoinColumnBidirectionalRefEdEntity ed1 = new IndexedListJoinColumnBidirectionalRefEdEntity("ed1", null);
|
||||
IndexedListJoinColumnBidirectionalRefEdEntity ed2 = new IndexedListJoinColumnBidirectionalRefEdEntity("ed2", null);
|
||||
IndexedListJoinColumnBidirectionalRefEdEntity ed3 = new IndexedListJoinColumnBidirectionalRefEdEntity("ed3", null);
|
||||
|
||||
IndexedListJoinColumnBidirectionalRefIngEntity ing1 = new IndexedListJoinColumnBidirectionalRefIngEntity("coll1", ed1, ed2, ed3);
|
||||
IndexedListJoinColumnBidirectionalRefIngEntity ing2 = new IndexedListJoinColumnBidirectionalRefIngEntity("coll1");
|
||||
|
||||
// Revision 1 (ing1: ed1, ed2, ed3)
|
||||
em.getTransaction().begin();
|
||||
|
||||
em.persist(ed1);
|
||||
em.persist(ed2);
|
||||
em.persist(ed3);
|
||||
em.persist(ing1);
|
||||
em.persist(ing2);
|
||||
|
||||
em.getTransaction().commit();
|
||||
|
||||
// Revision 2 (ing1: ed1, ed3, ing2: ed2)
|
||||
em.getTransaction().begin();
|
||||
|
||||
ing1 = em.find(IndexedListJoinColumnBidirectionalRefIngEntity.class, ing1.getId());
|
||||
ing2 = em.find(IndexedListJoinColumnBidirectionalRefIngEntity.class, ing2.getId());
|
||||
ed2 = em.find(IndexedListJoinColumnBidirectionalRefEdEntity.class, ed2.getId());
|
||||
|
||||
ing1.getReferences().remove(ed2);
|
||||
ing2.getReferences().add(ed2);
|
||||
|
||||
em.getTransaction().commit();
|
||||
em.clear();
|
||||
|
||||
// Revision 3 (ing1: ed3, ed1, ing2: ed2)
|
||||
em.getTransaction().begin();
|
||||
|
||||
ing1 = em.find(IndexedListJoinColumnBidirectionalRefIngEntity.class, ing1.getId());
|
||||
ing2 = em.find(IndexedListJoinColumnBidirectionalRefIngEntity.class, ing2.getId());
|
||||
ed1 = em.find(IndexedListJoinColumnBidirectionalRefEdEntity.class, ed1.getId());
|
||||
ed2 = em.find(IndexedListJoinColumnBidirectionalRefEdEntity.class, ed2.getId());
|
||||
ed3 = em.find(IndexedListJoinColumnBidirectionalRefEdEntity.class, ed3.getId());
|
||||
|
||||
ing1.getReferences().remove(ed3);
|
||||
ing1.getReferences().add(0, ed3);
|
||||
|
||||
em.getTransaction().commit();
|
||||
em.clear();
|
||||
|
||||
// Revision 4 (ing1: ed2, ed3, ed1)
|
||||
em.getTransaction().begin();
|
||||
|
||||
ing1 = em.find(IndexedListJoinColumnBidirectionalRefIngEntity.class, ing1.getId());
|
||||
ing2 = em.find(IndexedListJoinColumnBidirectionalRefIngEntity.class, ing2.getId());
|
||||
ed1 = em.find(IndexedListJoinColumnBidirectionalRefEdEntity.class, ed1.getId());
|
||||
ed2 = em.find(IndexedListJoinColumnBidirectionalRefEdEntity.class, ed2.getId());
|
||||
ed3 = em.find(IndexedListJoinColumnBidirectionalRefEdEntity.class, ed3.getId());
|
||||
|
||||
ing2.getReferences().remove(ed2);
|
||||
ing1.getReferences().add(0, ed2);
|
||||
|
||||
em.getTransaction().commit();
|
||||
em.clear();
|
||||
|
||||
//
|
||||
|
||||
ing1_id = ing1.getId();
|
||||
ing2_id = ing2.getId();
|
||||
|
||||
ed1_id = ed1.getId();
|
||||
ed2_id = ed2.getId();
|
||||
ed3_id = ed3.getId();
|
||||
}
|
||||
|
||||
@Test(enabled = true, dependsOnMethods = "createData")
|
||||
public void testRevisionsCounts() {
|
||||
assertEquals(Arrays.asList(1, 2, 3, 4), getAuditReader().getRevisions(IndexedListJoinColumnBidirectionalRefIngEntity.class, ing1_id));
|
||||
assertEquals(Arrays.asList(1, 2, 4), getAuditReader().getRevisions(IndexedListJoinColumnBidirectionalRefIngEntity.class, ing2_id));
|
||||
|
||||
assertEquals(Arrays.asList(1, 3, 4), getAuditReader().getRevisions(IndexedListJoinColumnBidirectionalRefEdEntity.class, ed1_id));
|
||||
assertEquals(Arrays.asList(1, 2, 4), getAuditReader().getRevisions(IndexedListJoinColumnBidirectionalRefEdEntity.class, ed2_id));
|
||||
assertEquals(Arrays.asList(1, 2, 3, 4), getAuditReader().getRevisions(IndexedListJoinColumnBidirectionalRefEdEntity.class, ed3_id));
|
||||
}
|
||||
|
||||
@Test(enabled = true, dependsOnMethods = "createData")
|
||||
public void testHistoryOfIng1() {
|
||||
IndexedListJoinColumnBidirectionalRefEdEntity ed1 = getEntityManager().find(IndexedListJoinColumnBidirectionalRefEdEntity.class, ed1_id);
|
||||
IndexedListJoinColumnBidirectionalRefEdEntity ed2 = getEntityManager().find(IndexedListJoinColumnBidirectionalRefEdEntity.class, ed2_id);
|
||||
IndexedListJoinColumnBidirectionalRefEdEntity ed3 = getEntityManager().find(IndexedListJoinColumnBidirectionalRefEdEntity.class, ed3_id);
|
||||
|
||||
IndexedListJoinColumnBidirectionalRefIngEntity rev1 = getAuditReader().find(IndexedListJoinColumnBidirectionalRefIngEntity.class, ing1_id, 1);
|
||||
IndexedListJoinColumnBidirectionalRefIngEntity rev2 = getAuditReader().find(IndexedListJoinColumnBidirectionalRefIngEntity.class, ing1_id, 2);
|
||||
IndexedListJoinColumnBidirectionalRefIngEntity rev3 = getAuditReader().find(IndexedListJoinColumnBidirectionalRefIngEntity.class, ing1_id, 3);
|
||||
IndexedListJoinColumnBidirectionalRefIngEntity rev4 = getAuditReader().find(IndexedListJoinColumnBidirectionalRefIngEntity.class, ing1_id, 4);
|
||||
|
||||
assertEquals(rev1.getReferences().size(), 3);
|
||||
assertEquals(rev1.getReferences().get(0), ed1);
|
||||
assertEquals(rev1.getReferences().get(1), ed2);
|
||||
assertEquals(rev1.getReferences().get(2), ed3);
|
||||
|
||||
assertEquals(rev2.getReferences().size(), 2);
|
||||
assertEquals(rev2.getReferences().get(0), ed1);
|
||||
assertEquals(rev2.getReferences().get(1), ed3);
|
||||
|
||||
assertEquals(rev3.getReferences().size(), 2);
|
||||
assertEquals(rev3.getReferences().get(0), ed3);
|
||||
assertEquals(rev3.getReferences().get(1), ed1);
|
||||
|
||||
assertEquals(rev4.getReferences().size(), 3);
|
||||
assertEquals(rev4.getReferences().get(0), ed2);
|
||||
assertEquals(rev4.getReferences().get(1), ed3);
|
||||
assertEquals(rev4.getReferences().get(2), ed1);
|
||||
}
|
||||
|
||||
@Test(enabled = true, dependsOnMethods = "createData")
|
||||
public void testHistoryOfIng2() {
|
||||
IndexedListJoinColumnBidirectionalRefEdEntity ed2 = getEntityManager().find(IndexedListJoinColumnBidirectionalRefEdEntity.class, ed2_id);
|
||||
|
||||
IndexedListJoinColumnBidirectionalRefIngEntity rev1 = getAuditReader().find(IndexedListJoinColumnBidirectionalRefIngEntity.class, ing2_id, 1);
|
||||
IndexedListJoinColumnBidirectionalRefIngEntity rev2 = getAuditReader().find(IndexedListJoinColumnBidirectionalRefIngEntity.class, ing2_id, 2);
|
||||
IndexedListJoinColumnBidirectionalRefIngEntity rev3 = getAuditReader().find(IndexedListJoinColumnBidirectionalRefIngEntity.class, ing2_id, 3);
|
||||
IndexedListJoinColumnBidirectionalRefIngEntity rev4 = getAuditReader().find(IndexedListJoinColumnBidirectionalRefIngEntity.class, ing2_id, 4);
|
||||
|
||||
assertEquals(rev1.getReferences().size(), 0);
|
||||
|
||||
assertEquals(rev2.getReferences().size(), 1);
|
||||
assertEquals(rev2.getReferences().get(0), ed2);
|
||||
|
||||
assertEquals(rev3.getReferences().size(), 1);
|
||||
assertEquals(rev3.getReferences().get(0), ed2);
|
||||
|
||||
assertEquals(rev4.getReferences().size(), 0);
|
||||
}
|
||||
|
||||
@Test(enabled = true, dependsOnMethods = "createData")
|
||||
public void testHistoryOfEd1() {
|
||||
IndexedListJoinColumnBidirectionalRefIngEntity ing1 = getEntityManager().find(IndexedListJoinColumnBidirectionalRefIngEntity.class, ing1_id);
|
||||
|
||||
IndexedListJoinColumnBidirectionalRefEdEntity rev1 = getAuditReader().find(IndexedListJoinColumnBidirectionalRefEdEntity.class, ed1_id, 1);
|
||||
IndexedListJoinColumnBidirectionalRefEdEntity rev2 = getAuditReader().find(IndexedListJoinColumnBidirectionalRefEdEntity.class, ed1_id, 2);
|
||||
IndexedListJoinColumnBidirectionalRefEdEntity rev3 = getAuditReader().find(IndexedListJoinColumnBidirectionalRefEdEntity.class, ed1_id, 3);
|
||||
IndexedListJoinColumnBidirectionalRefEdEntity rev4 = getAuditReader().find(IndexedListJoinColumnBidirectionalRefEdEntity.class, ed1_id, 4);
|
||||
|
||||
assertTrue(rev1.getOwner().equals(ing1));
|
||||
assertTrue(rev2.getOwner().equals(ing1));
|
||||
assertTrue(rev3.getOwner().equals(ing1));
|
||||
assertTrue(rev4.getOwner().equals(ing1));
|
||||
|
||||
assertEquals(rev1.getPosition(), new Integer(0));
|
||||
assertEquals(rev2.getPosition(), new Integer(0));
|
||||
assertEquals(rev3.getPosition(), new Integer(1));
|
||||
assertEquals(rev4.getPosition(), new Integer(2));
|
||||
}
|
||||
|
||||
@Test(enabled = true, dependsOnMethods = "createData")
|
||||
public void testHistoryOfEd2() {
|
||||
IndexedListJoinColumnBidirectionalRefIngEntity ing1 = getEntityManager().find(IndexedListJoinColumnBidirectionalRefIngEntity.class, ing1_id);
|
||||
IndexedListJoinColumnBidirectionalRefIngEntity ing2 = getEntityManager().find(IndexedListJoinColumnBidirectionalRefIngEntity.class, ing2_id);
|
||||
|
||||
IndexedListJoinColumnBidirectionalRefEdEntity rev1 = getAuditReader().find(IndexedListJoinColumnBidirectionalRefEdEntity.class, ed2_id, 1);
|
||||
IndexedListJoinColumnBidirectionalRefEdEntity rev2 = getAuditReader().find(IndexedListJoinColumnBidirectionalRefEdEntity.class, ed2_id, 2);
|
||||
IndexedListJoinColumnBidirectionalRefEdEntity rev3 = getAuditReader().find(IndexedListJoinColumnBidirectionalRefEdEntity.class, ed2_id, 3);
|
||||
IndexedListJoinColumnBidirectionalRefEdEntity rev4 = getAuditReader().find(IndexedListJoinColumnBidirectionalRefEdEntity.class, ed2_id, 4);
|
||||
|
||||
assertTrue(rev1.getOwner().equals(ing1));
|
||||
assertTrue(rev2.getOwner().equals(ing2));
|
||||
assertTrue(rev3.getOwner().equals(ing2));
|
||||
assertTrue(rev4.getOwner().equals(ing1));
|
||||
|
||||
assertEquals(rev1.getPosition(), new Integer(1));
|
||||
assertEquals(rev2.getPosition(), new Integer(0));
|
||||
assertEquals(rev3.getPosition(), new Integer(0));
|
||||
assertEquals(rev4.getPosition(), new Integer(0));
|
||||
}
|
||||
|
||||
@Test(enabled = true, dependsOnMethods = "createData")
|
||||
public void testHistoryOfEd3() {
|
||||
IndexedListJoinColumnBidirectionalRefIngEntity ing1 = getEntityManager().find(IndexedListJoinColumnBidirectionalRefIngEntity.class, ing1_id);
|
||||
|
||||
IndexedListJoinColumnBidirectionalRefEdEntity rev1 = getAuditReader().find(IndexedListJoinColumnBidirectionalRefEdEntity.class, ed3_id, 1);
|
||||
IndexedListJoinColumnBidirectionalRefEdEntity rev2 = getAuditReader().find(IndexedListJoinColumnBidirectionalRefEdEntity.class, ed3_id, 2);
|
||||
IndexedListJoinColumnBidirectionalRefEdEntity rev3 = getAuditReader().find(IndexedListJoinColumnBidirectionalRefEdEntity.class, ed3_id, 3);
|
||||
IndexedListJoinColumnBidirectionalRefEdEntity rev4 = getAuditReader().find(IndexedListJoinColumnBidirectionalRefEdEntity.class, ed3_id, 4);
|
||||
|
||||
assertTrue(rev1.getOwner().equals(ing1));
|
||||
assertTrue(rev2.getOwner().equals(ing1));
|
||||
assertTrue(rev3.getOwner().equals(ing1));
|
||||
assertTrue(rev4.getOwner().equals(ing1));
|
||||
|
||||
assertEquals(rev1.getPosition(), new Integer(2));
|
||||
assertEquals(rev2.getPosition(), new Integer(1));
|
||||
assertEquals(rev3.getPosition(), new Integer(0));
|
||||
assertEquals(rev4.getPosition(), new Integer(1));
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue