Author: adamw
Date: 2009-12-16 06:09:34 -0500 (Wed, 16 Dec 2009)
New Revision: 18236
Added:
core/trunk/envers/src/main/java/org/hibernate/envers/entities/mapper/relation/component/MiddleStraightComponentMapper.java
core/trunk/envers/src/test/java/org/hibernate/envers/test/entities/onetomany/detached/IndexedListJoinColumnBidirectionalRefEdEntity.java
core/trunk/envers/src/test/java/org/hibernate/envers/test/entities/onetomany/detached/IndexedListJoinColumnBidirectionalRefIngEntity.java
core/trunk/envers/src/test/java/org/hibernate/envers/test/integration/onetomany/detached/IndexedJoinColumnBidirectionalList.java
Modified:
core/trunk/envers/src/main/java/org/hibernate/envers/configuration/ClassesAuditingData.java
core/trunk/envers/src/main/java/org/hibernate/envers/configuration/EntitiesConfigurator.java
core/trunk/envers/src/main/java/org/hibernate/envers/configuration/metadata/BasicMetadataGenerator.java
core/trunk/envers/src/main/java/org/hibernate/envers/configuration/metadata/CollectionMetadataGenerator.java
core/trunk/envers/src/main/java/org/hibernate/envers/configuration/metadata/IdMetadataGenerator.java
core/trunk/envers/src/main/java/org/hibernate/envers/configuration/metadata/ToOneRelationMetadataGenerator.java
core/trunk/envers/src/main/java/org/hibernate/envers/configuration/metadata/reader/PropertyAuditingData.java
core/trunk/envers/src/main/java/org/hibernate/envers/entities/EntityConfiguration.java
core/trunk/envers/src/main/java/org/hibernate/envers/entities/RelationDescription.java
core/trunk/envers/src/main/java/org/hibernate/envers/entities/mapper/PersistentCollectionChangeData.java
core/trunk/envers/src/main/java/org/hibernate/envers/entities/mapper/SinglePropertyMapper.java
core/trunk/envers/src/main/java/org/hibernate/envers/entities/mapper/relation/AbstractCollectionMapper.java
core/trunk/envers/src/main/java/org/hibernate/envers/entities/mapper/relation/BasicCollectionMapper.java
core/trunk/envers/src/main/java/org/hibernate/envers/entities/mapper/relation/ListCollectionMapper.java
core/trunk/envers/src/main/java/org/hibernate/envers/entities/mapper/relation/MapCollectionMapper.java
core/trunk/envers/src/main/java/org/hibernate/envers/event/AuditEventListener.java
core/trunk/envers/src/main/java/org/hibernate/envers/synchronization/work/FakeBidirectionalRelationWorkUnit.java
core/trunk/envers/src/main/java/org/hibernate/envers/tools/MappingTools.java
Log:
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
Modified:
core/trunk/envers/src/main/java/org/hibernate/envers/configuration/ClassesAuditingData.java
===================================================================
---
core/trunk/envers/src/main/java/org/hibernate/envers/configuration/ClassesAuditingData.java 2009-12-16
08:23:41 UTC (rev 18235)
+++
core/trunk/envers/src/main/java/org/hibernate/envers/configuration/ClassesAuditingData.java 2009-12-16
11:09:34 UTC (rev 18236)
@@ -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 @@
* @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 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);
+ }
+ }
}
Modified:
core/trunk/envers/src/main/java/org/hibernate/envers/configuration/EntitiesConfigurator.java
===================================================================
---
core/trunk/envers/src/main/java/org/hibernate/envers/configuration/EntitiesConfigurator.java 2009-12-16
08:23:41 UTC (rev 18235)
+++
core/trunk/envers/src/main/java/org/hibernate/envers/configuration/EntitiesConfigurator.java 2009-12-16
11:09:34 UTC (rev 18236)
@@ -80,6 +80,9 @@
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);
Modified:
core/trunk/envers/src/main/java/org/hibernate/envers/configuration/metadata/BasicMetadataGenerator.java
===================================================================
---
core/trunk/envers/src/main/java/org/hibernate/envers/configuration/metadata/BasicMetadataGenerator.java 2009-12-16
08:23:41 UTC (rev 18235)
+++
core/trunk/envers/src/main/java/org/hibernate/envers/configuration/metadata/BasicMetadataGenerator.java 2009-12-16
11:09:34 UTC (rev 18236)
@@ -66,7 +66,7 @@
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());
}
Modified:
core/trunk/envers/src/main/java/org/hibernate/envers/configuration/metadata/CollectionMetadataGenerator.java
===================================================================
---
core/trunk/envers/src/main/java/org/hibernate/envers/configuration/metadata/CollectionMetadataGenerator.java 2009-12-16
08:23:41 UTC (rev 18235)
+++
core/trunk/envers/src/main/java/org/hibernate/envers/configuration/metadata/CollectionMetadataGenerator.java 2009-12-16
11:09:34 UTC (rev 18236)
@@ -43,13 +43,10 @@
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.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,19 +128,9 @@
throw new MappingException("Unable to read auditing configuration for
" + referencingEntityName + "!");
}
- referencedEntityName = getReferencedEntityName(propertyValue.getElement());
+ referencedEntityName =
MappingTools.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;
- }
- }
-
void addCollection() {
Type type = propertyValue.getType();
@@ -206,10 +192,8 @@
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 @@
// 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 @@
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 @@
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 @@
} 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,33 +533,16 @@
return middleEntityXmlId;
}
- private String getMappedByCommon(PersistentClass referencedClass) {
+ @SuppressWarnings({"unchecked"})
+ private String getMappedBy(Collection collectionValue) {
+ PersistentClass referencedClass = ((OneToMany)
collectionValue.getElement()).getAssociatedClass();
+
// 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;
- }
-
Iterator<Property> assocClassProps =
referencedClass.getPropertyIterator();
while (assocClassProps.hasNext()) {
@@ -577,9 +560,10 @@
@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();
Modified:
core/trunk/envers/src/main/java/org/hibernate/envers/configuration/metadata/IdMetadataGenerator.java
===================================================================
---
core/trunk/envers/src/main/java/org/hibernate/envers/configuration/metadata/IdMetadataGenerator.java 2009-12-16
08:23:41 UTC (rev 18235)
+++
core/trunk/envers/src/main/java/org/hibernate/envers/configuration/metadata/IdMetadataGenerator.java 2009-12-16
11:09:34 UTC (rev 18236)
@@ -139,6 +139,6 @@
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);
}
}
Modified:
core/trunk/envers/src/main/java/org/hibernate/envers/configuration/metadata/ToOneRelationMetadataGenerator.java
===================================================================
---
core/trunk/envers/src/main/java/org/hibernate/envers/configuration/metadata/ToOneRelationMetadataGenerator.java 2009-12-16
08:23:41 UTC (rev 18235)
+++
core/trunk/envers/src/main/java/org/hibernate/envers/configuration/metadata/ToOneRelationMetadataGenerator.java 2009-12-16
11:09:34 UTC (rev 18236)
@@ -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.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 @@
// 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
Modified:
core/trunk/envers/src/main/java/org/hibernate/envers/configuration/metadata/reader/PropertyAuditingData.java
===================================================================
---
core/trunk/envers/src/main/java/org/hibernate/envers/configuration/metadata/reader/PropertyAuditingData.java 2009-12-16
08:23:41 UTC (rev 18235)
+++
core/trunk/envers/src/main/java/org/hibernate/envers/configuration/metadata/reader/PropertyAuditingData.java 2009-12-16
11:09:34 UTC (rev 18236)
@@ -48,13 +48,15 @@
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 @@
this.relationTargetAuditMode = relationTargetAuditMode;
this.auditMappedBy = auditMappedBy;
this.positionMappedBy = positionMappedBy;
+ this.forceInsertable = forceInsertable;
}
public String getName() {
@@ -136,6 +139,14 @@
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();
Modified:
core/trunk/envers/src/main/java/org/hibernate/envers/entities/EntityConfiguration.java
===================================================================
---
core/trunk/envers/src/main/java/org/hibernate/envers/entities/EntityConfiguration.java 2009-12-16
08:23:41 UTC (rev 18235)
+++
core/trunk/envers/src/main/java/org/hibernate/envers/entities/EntityConfiguration.java 2009-12-16
11:09:34 UTC (rev 18236)
@@ -53,29 +53,31 @@
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) {
Modified:
core/trunk/envers/src/main/java/org/hibernate/envers/entities/RelationDescription.java
===================================================================
---
core/trunk/envers/src/main/java/org/hibernate/envers/entities/RelationDescription.java 2009-12-16
08:23:41 UTC (rev 18235)
+++
core/trunk/envers/src/main/java/org/hibernate/envers/entities/RelationDescription.java 2009-12-16
11:09:34 UTC (rev 18236)
@@ -36,18 +36,21 @@
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 @@
return fakeBidirectionalRelationMapper;
}
+ public PropertyMapper getFakeBidirectionalRelationIndexMapper() {
+ return fakeBidirectionalRelationIndexMapper;
+ }
+
public boolean isInsertable() {
return insertable;
}
Modified:
core/trunk/envers/src/main/java/org/hibernate/envers/entities/mapper/PersistentCollectionChangeData.java
===================================================================
---
core/trunk/envers/src/main/java/org/hibernate/envers/entities/mapper/PersistentCollectionChangeData.java 2009-12-16
08:23:41 UTC (rev 18235)
+++
core/trunk/envers/src/main/java/org/hibernate/envers/entities/mapper/PersistentCollectionChangeData.java 2009-12-16
11:09:34 UTC (rev 18236)
@@ -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 @@
}
/**
- * 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;
+ }
}
Modified:
core/trunk/envers/src/main/java/org/hibernate/envers/entities/mapper/SinglePropertyMapper.java
===================================================================
---
core/trunk/envers/src/main/java/org/hibernate/envers/entities/mapper/SinglePropertyMapper.java 2009-12-16
08:23:41 UTC (rev 18235)
+++
core/trunk/envers/src/main/java/org/hibernate/envers/entities/mapper/SinglePropertyMapper.java 2009-12-16
11:09:34 UTC (rev 18236)
@@ -47,6 +47,10 @@
public class SinglePropertyMapper implements PropertyMapper, SimpleMapperBuilder {
private PropertyData propertyData;
+ public SinglePropertyMapper(PropertyData propertyData) {
+ this.propertyData = propertyData;
+ }
+
public SinglePropertyMapper() { }
public void add(PropertyData propertyData) {
Modified:
core/trunk/envers/src/main/java/org/hibernate/envers/entities/mapper/relation/AbstractCollectionMapper.java
===================================================================
---
core/trunk/envers/src/main/java/org/hibernate/envers/entities/mapper/relation/AbstractCollectionMapper.java 2009-12-16
08:23:41 UTC (rev 18235)
+++
core/trunk/envers/src/main/java/org/hibernate/envers/entities/mapper/relation/AbstractCollectionMapper.java 2009-12-16
11:09:34 UTC (rev 18236)
@@ -70,7 +70,6 @@
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 @@
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);
Modified:
core/trunk/envers/src/main/java/org/hibernate/envers/entities/mapper/relation/BasicCollectionMapper.java
===================================================================
---
core/trunk/envers/src/main/java/org/hibernate/envers/entities/mapper/relation/BasicCollectionMapper.java 2009-12-16
08:23:41 UTC (rev 18235)
+++
core/trunk/envers/src/main/java/org/hibernate/envers/entities/mapper/relation/BasicCollectionMapper.java 2009-12-16
11:09:34 UTC (rev 18236)
@@ -71,8 +71,4 @@
protected void mapToMapFromObject(Map<String, Object> data, Object changed) {
elementComponentData.getComponentMapper().mapToMapFromObject(data, changed);
}
-
- protected Object getElement(Object changedObject) {
- return changedObject;
- }
}
Modified:
core/trunk/envers/src/main/java/org/hibernate/envers/entities/mapper/relation/ListCollectionMapper.java
===================================================================
---
core/trunk/envers/src/main/java/org/hibernate/envers/entities/mapper/relation/ListCollectionMapper.java 2009-12-16
08:23:41 UTC (rev 18235)
+++
core/trunk/envers/src/main/java/org/hibernate/envers/entities/mapper/relation/ListCollectionMapper.java 2009-12-16
11:09:34 UTC (rev 18236)
@@ -83,9 +83,4 @@
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();
- }
}
\ No newline at end of file
Modified:
core/trunk/envers/src/main/java/org/hibernate/envers/entities/mapper/relation/MapCollectionMapper.java
===================================================================
---
core/trunk/envers/src/main/java/org/hibernate/envers/entities/mapper/relation/MapCollectionMapper.java 2009-12-16
08:23:41 UTC (rev 18235)
+++
core/trunk/envers/src/main/java/org/hibernate/envers/entities/mapper/relation/MapCollectionMapper.java 2009-12-16
11:09:34 UTC (rev 18236)
@@ -76,8 +76,4 @@
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();
- }
}
\ No newline at end of file
Copied:
core/trunk/envers/src/main/java/org/hibernate/envers/entities/mapper/relation/component/MiddleStraightComponentMapper.java
(from rev 18224,
core/trunk/envers/src/main/java/org/hibernate/envers/entities/mapper/relation/component/MiddleSimpleComponentMapper.java)
===================================================================
---
core/trunk/envers/src/main/java/org/hibernate/envers/entities/mapper/relation/component/MiddleStraightComponentMapper.java
(rev 0)
+++
core/trunk/envers/src/main/java/org/hibernate/envers/entities/mapper/relation/component/MiddleStraightComponentMapper.java 2009-12-16
11:09:34 UTC (rev 18236)
@@ -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!");
+ }
+}
\ No newline at end of file
Modified:
core/trunk/envers/src/main/java/org/hibernate/envers/event/AuditEventListener.java
===================================================================
---
core/trunk/envers/src/main/java/org/hibernate/envers/event/AuditEventListener.java 2009-12-16
08:23:41 UTC (rev 18235)
+++
core/trunk/envers/src/main/java/org/hibernate/envers/event/AuditEventListener.java 2009-12-16
11:09:34 UTC (rev 18236)
@@ -239,7 +239,8 @@
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.
Modified:
core/trunk/envers/src/main/java/org/hibernate/envers/synchronization/work/FakeBidirectionalRelationWorkUnit.java
===================================================================
---
core/trunk/envers/src/main/java/org/hibernate/envers/synchronization/work/FakeBidirectionalRelationWorkUnit.java 2009-12-16
08:23:41 UTC (rev 18235)
+++
core/trunk/envers/src/main/java/org/hibernate/envers/synchronization/work/FakeBidirectionalRelationWorkUnit.java 2009-12-16
11:09:34 UTC (rev 18236)
@@ -28,13 +28,14 @@
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 @@
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 @@
// 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) {
Modified: core/trunk/envers/src/main/java/org/hibernate/envers/tools/MappingTools.java
===================================================================
---
core/trunk/envers/src/main/java/org/hibernate/envers/tools/MappingTools.java 2009-12-16
08:23:41 UTC (rev 18235)
+++
core/trunk/envers/src/main/java/org/hibernate/envers/tools/MappingTools.java 2009-12-16
11:09:34 UTC (rev 18236)
@@ -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 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;
+ }
}
Copied:
core/trunk/envers/src/test/java/org/hibernate/envers/test/entities/onetomany/detached/IndexedListJoinColumnBidirectionalRefEdEntity.java
(from rev 18224,
core/trunk/envers/src/test/java/org/hibernate/envers/test/entities/onetomany/detached/ListJoinColumnBidirectionalRefEdEntity.java)
===================================================================
---
core/trunk/envers/src/test/java/org/hibernate/envers/test/entities/onetomany/detached/IndexedListJoinColumnBidirectionalRefEdEntity.java
(rev 0)
+++
core/trunk/envers/src/test/java/org/hibernate/envers/test/entities/onetomany/detached/IndexedListJoinColumnBidirectionalRefEdEntity.java 2009-12-16
11:09:34 UTC (rev 18236)
@@ -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 + ")";
+ }
+}
\ No newline at end of file
Copied:
core/trunk/envers/src/test/java/org/hibernate/envers/test/entities/onetomany/detached/IndexedListJoinColumnBidirectionalRefIngEntity.java
(from rev 18224,
core/trunk/envers/src/test/java/org/hibernate/envers/test/entities/onetomany/detached/ListJoinColumnBidirectionalRefIngEntity.java)
===================================================================
---
core/trunk/envers/src/test/java/org/hibernate/envers/test/entities/onetomany/detached/IndexedListJoinColumnBidirectionalRefIngEntity.java
(rev 0)
+++
core/trunk/envers/src/test/java/org/hibernate/envers/test/entities/onetomany/detached/IndexedListJoinColumnBidirectionalRefIngEntity.java 2009-12-16
11:09:34 UTC (rev 18236)
@@ -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 + ")";
+ }
+}
\ No newline at end of file
Copied:
core/trunk/envers/src/test/java/org/hibernate/envers/test/integration/onetomany/detached/IndexedJoinColumnBidirectionalList.java
(from rev 18226,
core/trunk/envers/src/test/java/org/hibernate/envers/test/integration/onetomany/detached/JoinColumnBidirectionalList.java)
===================================================================
---
core/trunk/envers/src/test/java/org/hibernate/envers/test/integration/onetomany/detached/IndexedJoinColumnBidirectionalList.java
(rev 0)
+++
core/trunk/envers/src/test/java/org/hibernate/envers/test/integration/onetomany/detached/IndexedJoinColumnBidirectionalList.java 2009-12-16
11:09:34 UTC (rev 18236)
@@ -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));
+ }
+}
\ No newline at end of file