HHH-3563: relation support in components
git-svn-id: https://svn.jboss.org/repos/hibernate/core/trunk@15802 1b8cb986-b30d-0410-93ca-fae66ebed9b2
This commit is contained in:
parent
6d56458124
commit
bf8e6fed6f
|
@ -37,9 +37,9 @@ import org.dom4j.Element;
|
|||
import org.dom4j.io.DOMWriter;
|
||||
import org.dom4j.io.OutputFormat;
|
||||
import org.dom4j.io.XMLWriter;
|
||||
import org.hibernate.envers.configuration.metadata.AnnotationsMetadataReader;
|
||||
import org.hibernate.envers.configuration.metadata.reader.AnnotationsMetadataReader;
|
||||
import org.hibernate.envers.configuration.metadata.EntityXmlMappingData;
|
||||
import org.hibernate.envers.configuration.metadata.PersistentClassAuditingData;
|
||||
import org.hibernate.envers.configuration.metadata.reader.ClassAuditingData;
|
||||
import org.hibernate.envers.configuration.metadata.AuditMetadataGenerator;
|
||||
import org.hibernate.envers.entities.EntitiesConfigurations;
|
||||
import org.hibernate.envers.tools.StringTools;
|
||||
|
@ -64,8 +64,8 @@ public class EntitiesConfigurator {
|
|||
// Sorting the persistent class topologically - superclass always before subclass
|
||||
Iterator<PersistentClass> classes = GraphTopologicalSort.sort(new PersistentClassGraphDefiner(cfg)).iterator();
|
||||
|
||||
Map<PersistentClass, PersistentClassAuditingData> pcDatas =
|
||||
new HashMap<PersistentClass, PersistentClassAuditingData>();
|
||||
Map<PersistentClass, ClassAuditingData> pcDatas =
|
||||
new HashMap<PersistentClass, ClassAuditingData>();
|
||||
Map<PersistentClass, EntityXmlMappingData> xmlMappings = new HashMap<PersistentClass, EntityXmlMappingData>();
|
||||
|
||||
// First pass
|
||||
|
@ -74,7 +74,7 @@ public class EntitiesConfigurator {
|
|||
// Collecting information from annotations on the persistent class pc
|
||||
AnnotationsMetadataReader annotationsMetadataReader =
|
||||
new AnnotationsMetadataReader(globalCfg, reflectionManager, pc);
|
||||
PersistentClassAuditingData auditData = annotationsMetadataReader.getAuditData();
|
||||
ClassAuditingData auditData = annotationsMetadataReader.getAuditData();
|
||||
|
||||
if (auditData.isAudited()) {
|
||||
pcDatas.put(pc, auditData);
|
||||
|
@ -90,7 +90,7 @@ public class EntitiesConfigurator {
|
|||
}
|
||||
|
||||
// Second pass
|
||||
for (Map.Entry<PersistentClass, PersistentClassAuditingData> pcDatasEntry : pcDatas.entrySet()) {
|
||||
for (Map.Entry<PersistentClass, ClassAuditingData> pcDatasEntry : pcDatas.entrySet()) {
|
||||
EntityXmlMappingData xmlMappingData = xmlMappings.get(pcDatasEntry.getKey());
|
||||
|
||||
auditMetaGen.generateSecondPass(pcDatasEntry.getKey(), pcDatasEntry.getValue(), xmlMappingData);
|
||||
|
|
|
@ -1,286 +0,0 @@
|
|||
/*
|
||||
* 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.configuration.metadata;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.util.Set;
|
||||
import java.util.Iterator;
|
||||
import javax.persistence.MapKey;
|
||||
import javax.persistence.Version;
|
||||
import javax.persistence.JoinColumn;
|
||||
|
||||
import org.hibernate.envers.SecondaryAuditTable;
|
||||
import org.hibernate.envers.*;
|
||||
import org.hibernate.envers.ModificationStore;
|
||||
import org.hibernate.envers.tools.Tools;
|
||||
import org.hibernate.envers.configuration.GlobalConfiguration;
|
||||
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.annotations.common.reflection.ReflectionManager;
|
||||
import org.hibernate.annotations.common.reflection.XClass;
|
||||
import org.hibernate.annotations.common.reflection.XProperty;
|
||||
import org.hibernate.mapping.PersistentClass;
|
||||
import org.hibernate.mapping.Property;
|
||||
import org.jboss.envers.*;
|
||||
|
||||
/**
|
||||
* A helper class to read versioning meta-data from annotations on a persistent class.
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
* @author Sebastian Komander
|
||||
*/
|
||||
public final class AnnotationsMetadataReader {
|
||||
private final GlobalConfiguration globalCfg;
|
||||
private final ReflectionManager reflectionManager;
|
||||
private final PersistentClass pc;
|
||||
|
||||
/**
|
||||
* This object is filled with information read from annotations and returned by the <code>getVersioningData</code>
|
||||
* method.
|
||||
*/
|
||||
private final PersistentClassAuditingData auditData;
|
||||
|
||||
/**
|
||||
* Not null if the whole class is annotated with @Audited; the variable then holds the value of this
|
||||
* annotation's "modStore" parameter.
|
||||
*/
|
||||
private ModificationStore defaultStore;
|
||||
|
||||
private Set<String> propertyPersistentProperties;
|
||||
private Set<String> fieldPersistentProperties;
|
||||
|
||||
public AnnotationsMetadataReader(GlobalConfiguration globalCfg, ReflectionManager reflectionManager,
|
||||
PersistentClass pc) {
|
||||
this.globalCfg = globalCfg;
|
||||
this.reflectionManager = reflectionManager;
|
||||
this.pc = pc;
|
||||
|
||||
auditData = new PersistentClassAuditingData();
|
||||
|
||||
propertyPersistentProperties = Tools.newHashSet();
|
||||
fieldPersistentProperties = Tools.newHashSet();
|
||||
}
|
||||
|
||||
private ModificationStore translateModStore(org.jboss.envers.ModificationStore store) {
|
||||
switch (store) {
|
||||
case FULL: return ModificationStore.FULL;
|
||||
default: throw new AssertionError("Illegal modification store: " + store + "!");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a property is audited and if yes, sets its modification store on the supplied property data.
|
||||
* @param property Property to check.
|
||||
* @param propertyData Property data, on which to set this property's modification store.
|
||||
* @param persistentProperties Persistent properties with the access type of the given property.
|
||||
* @return True, iff this property is audited.
|
||||
*/
|
||||
private boolean ifPropertyAuditedAddStore(XProperty property, PersistentPropertyAuditingData propertyData,
|
||||
Set<String> persistentProperties) {
|
||||
// If this is not a persistent property, with the same access type as currently checked,
|
||||
// it's not audited as well.
|
||||
if (!persistentProperties.contains(property.getName())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// check if a property is declared as not audited to exclude it
|
||||
// useful if a class is audited but some properties should be excluded
|
||||
NotAudited unVer = property.getAnnotation(NotAudited.class);
|
||||
if (unVer != null) {
|
||||
return false;
|
||||
} else {
|
||||
// if the optimistic locking field has to be unversioned and the current property
|
||||
// is the optimistic locking field, don't audit it
|
||||
if (globalCfg.isDoNotAuditOptimisticLockingField()) {
|
||||
Version jpaVer = property.getAnnotation(Version.class);
|
||||
if (jpaVer != null) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Checking if this property is explicitly audited or if all properties are.
|
||||
Audited aud = property.getAnnotation(Audited.class);
|
||||
Versioned ver = property.getAnnotation(Versioned.class);
|
||||
if (aud != null) {
|
||||
propertyData.setStore(aud.modStore());
|
||||
return true;
|
||||
} else if (ver != null) {
|
||||
propertyData.setStore(translateModStore(ver.modStore()));
|
||||
return true;
|
||||
} else {
|
||||
if (defaultStore != null) {
|
||||
propertyData.setStore(defaultStore);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void addPropertyMapKey(XProperty property, PersistentPropertyAuditingData propertyData) {
|
||||
MapKey mapKey = property.getAnnotation(MapKey.class);
|
||||
if (mapKey != null) {
|
||||
propertyData.setMapKey(mapKey.name());
|
||||
}
|
||||
}
|
||||
|
||||
private void addPropertyJoinTables(XProperty property, PersistentPropertyAuditingData propertyData) {
|
||||
AuditJoinTable joinTable = property.getAnnotation(AuditJoinTable.class);
|
||||
if (joinTable != null) {
|
||||
propertyData.setJoinTable(joinTable);
|
||||
} else {
|
||||
propertyData.setJoinTable(getDefaultAuditJoinTable());
|
||||
}
|
||||
}
|
||||
|
||||
private void addFromProperties(Iterable<XProperty> properties, String accessType, Set<String> persistenProperties) {
|
||||
for (XProperty property : properties) {
|
||||
PersistentPropertyAuditingData propertyData = new PersistentPropertyAuditingData();
|
||||
|
||||
if (ifPropertyAuditedAddStore(property, propertyData, persistenProperties)) {
|
||||
// Now we know that the property is audited
|
||||
auditData.getProperties().put(property.getName(), propertyData);
|
||||
|
||||
propertyData.setName(property.getName());
|
||||
propertyData.setAccessType(accessType);
|
||||
|
||||
addPropertyJoinTables(property, propertyData);
|
||||
addPropertyMapKey(property, propertyData);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void addPropertiesFromClass(XClass clazz) {
|
||||
XClass superclazz = clazz.getSuperclass();
|
||||
if (!"java.lang.Object".equals(superclazz.getName())) {
|
||||
addPropertiesFromClass(superclazz);
|
||||
}
|
||||
|
||||
addFromProperties(clazz.getDeclaredProperties("field"), "field", fieldPersistentProperties);
|
||||
addFromProperties(clazz.getDeclaredProperties("property"), "property", propertyPersistentProperties);
|
||||
}
|
||||
|
||||
private void readDefaultAudited(XClass clazz) {
|
||||
Audited defaultAudited = clazz.getAnnotation(Audited.class);
|
||||
|
||||
if (defaultAudited != null) {
|
||||
defaultStore = defaultAudited.modStore();
|
||||
auditData.setDefaultAudited(true);
|
||||
} else {
|
||||
Versioned defaultVersioned = clazz.getAnnotation(Versioned.class);
|
||||
if (defaultVersioned != null) {
|
||||
defaultStore = translateModStore(defaultVersioned.modStore());
|
||||
auditData.setDefaultAudited(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void readPersistentProperties() {
|
||||
Iterator propertyIter = pc.getPropertyIterator();
|
||||
while (propertyIter.hasNext()) {
|
||||
Property property = (Property) propertyIter.next();
|
||||
if ("field".equals(property.getPropertyAccessorName())) {
|
||||
fieldPersistentProperties.add(property.getName());
|
||||
} else {
|
||||
propertyPersistentProperties.add(property.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void addAuditTable(XClass clazz) {
|
||||
AuditTable auditTable = clazz.getAnnotation(AuditTable.class);
|
||||
if (auditTable != null) {
|
||||
auditData.setAuditTable(auditTable);
|
||||
} else {
|
||||
auditData.setAuditTable(getDefaultAuditTable());
|
||||
}
|
||||
}
|
||||
|
||||
private void addAuditSecondaryTables(XClass clazz) {
|
||||
// Getting information on secondary tables
|
||||
SecondaryAuditTable secondaryVersionsTable1 = clazz.getAnnotation(SecondaryAuditTable.class);
|
||||
if (secondaryVersionsTable1 != null) {
|
||||
auditData.getSecondaryTableDictionary().put(secondaryVersionsTable1.secondaryTableName(),
|
||||
secondaryVersionsTable1.secondaryAuditTableName());
|
||||
}
|
||||
|
||||
SecondaryAuditTables secondaryAuditTables = clazz.getAnnotation(SecondaryAuditTables.class);
|
||||
if (secondaryAuditTables != null) {
|
||||
for (SecondaryAuditTable secondaryAuditTable2 : secondaryAuditTables.value()) {
|
||||
auditData.getSecondaryTableDictionary().put(secondaryAuditTable2.secondaryTableName(),
|
||||
secondaryAuditTable2.secondaryAuditTableName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public PersistentClassAuditingData getAuditData() {
|
||||
if (pc.getClassName() == null) {
|
||||
return auditData;
|
||||
}
|
||||
|
||||
readPersistentProperties();
|
||||
|
||||
try {
|
||||
XClass clazz = reflectionManager.classForName(pc.getClassName(), this.getClass());
|
||||
|
||||
readDefaultAudited(clazz);
|
||||
addPropertiesFromClass(clazz);
|
||||
addAuditTable(clazz);
|
||||
addAuditSecondaryTables(clazz);
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new MappingException(e);
|
||||
}
|
||||
|
||||
return auditData;
|
||||
}
|
||||
|
||||
private AuditTable defaultAuditTable;
|
||||
private AuditTable getDefaultAuditTable() {
|
||||
if (defaultAuditTable == null) {
|
||||
defaultAuditTable = new AuditTable() {
|
||||
public String value() { return ""; }
|
||||
public String schema() { return ""; }
|
||||
public String catalog() { return ""; }
|
||||
public Class<? extends Annotation> annotationType() { return this.getClass(); }
|
||||
};
|
||||
}
|
||||
|
||||
return defaultAuditTable;
|
||||
}
|
||||
|
||||
private AuditJoinTable defaultAuditJoinTable;
|
||||
private AuditJoinTable getDefaultAuditJoinTable() {
|
||||
if (defaultAuditJoinTable == null) {
|
||||
defaultAuditJoinTable = new AuditJoinTable() {
|
||||
public String name() { return ""; }
|
||||
public String schema() { return ""; }
|
||||
public String catalog() { return ""; }
|
||||
public JoinColumn[] inverseJoinColumns() { return new JoinColumn[0]; }
|
||||
public Class<? extends Annotation> annotationType() { return this.getClass(); }
|
||||
};
|
||||
}
|
||||
|
||||
return defaultAuditJoinTable;
|
||||
}
|
||||
}
|
|
@ -30,6 +30,8 @@ import java.util.Map;
|
|||
import org.dom4j.Element;
|
||||
import org.hibernate.envers.configuration.GlobalConfiguration;
|
||||
import org.hibernate.envers.configuration.AuditEntitiesConfiguration;
|
||||
import org.hibernate.envers.configuration.metadata.reader.ClassAuditingData;
|
||||
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.mapper.CompositeMapperBuilder;
|
||||
|
@ -100,14 +102,14 @@ public final class AuditMetadataGenerator {
|
|||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
void addValue(Element parent, Value value, CompositeMapperBuilder currentMapper, String entityName,
|
||||
EntityXmlMappingData xmlMappingData, PersistentPropertyAuditingData persistentPropertyAuditingData,
|
||||
void addValue(Element parent, Value value, CompositeMapperBuilder currentMapper, String entityName,
|
||||
EntityXmlMappingData xmlMappingData, PropertyAuditingData propertyAuditingData,
|
||||
boolean insertable, boolean firstPass) {
|
||||
Type type = value.getType();
|
||||
|
||||
// only first pass
|
||||
if (firstPass) {
|
||||
if (basicMetadataGenerator.addBasic(parent, persistentPropertyAuditingData, value, currentMapper,
|
||||
if (basicMetadataGenerator.addBasic(parent, propertyAuditingData, value, currentMapper,
|
||||
insertable, false)) {
|
||||
// The property was mapped by the basic generator.
|
||||
return;
|
||||
|
@ -116,18 +118,18 @@ public final class AuditMetadataGenerator {
|
|||
|
||||
if (type instanceof ComponentType) {
|
||||
// both passes
|
||||
componentMetadataGenerator.addComponent(parent, persistentPropertyAuditingData, value, currentMapper,
|
||||
componentMetadataGenerator.addComponent(parent, propertyAuditingData, value, currentMapper,
|
||||
entityName, xmlMappingData, firstPass);
|
||||
} else if (type instanceof ManyToOneType) {
|
||||
// only second pass
|
||||
if (!firstPass) {
|
||||
toOneRelationMetadataGenerator.addToOne(parent, persistentPropertyAuditingData, value, currentMapper,
|
||||
toOneRelationMetadataGenerator.addToOne(parent, propertyAuditingData, value, currentMapper,
|
||||
entityName, insertable);
|
||||
}
|
||||
} else if (type instanceof OneToOneType) {
|
||||
// only second pass
|
||||
if (!firstPass) {
|
||||
toOneRelationMetadataGenerator.addOneToOneNotOwning(persistentPropertyAuditingData, value,
|
||||
toOneRelationMetadataGenerator.addOneToOneNotOwning(propertyAuditingData, value,
|
||||
currentMapper, entityName);
|
||||
}
|
||||
} else if (type instanceof CollectionType) {
|
||||
|
@ -135,35 +137,35 @@ public final class AuditMetadataGenerator {
|
|||
if (!firstPass) {
|
||||
CollectionMetadataGenerator collectionMetadataGenerator = new CollectionMetadataGenerator(this,
|
||||
(Collection) value, currentMapper, entityName, xmlMappingData,
|
||||
persistentPropertyAuditingData);
|
||||
propertyAuditingData);
|
||||
collectionMetadataGenerator.addCollection();
|
||||
}
|
||||
} else {
|
||||
if (firstPass) {
|
||||
// If we got here in the first pass, it means the basic mapper didn't map it, and none of the
|
||||
// above branches either.
|
||||
throwUnsupportedTypeException(type, entityName, persistentPropertyAuditingData.getName());
|
||||
throwUnsupportedTypeException(type, entityName, propertyAuditingData.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
private void addProperties(Element parent, Iterator<Property> properties, CompositeMapperBuilder currentMapper,
|
||||
PersistentClassAuditingData auditingData, String entityName, EntityXmlMappingData xmlMappingData,
|
||||
ClassAuditingData auditingData, String entityName, EntityXmlMappingData xmlMappingData,
|
||||
boolean firstPass) {
|
||||
while (properties.hasNext()) {
|
||||
Property property = properties.next();
|
||||
String propertyName = property.getName();
|
||||
if (auditingData.getPropertyAuditingData(propertyName) != null) {
|
||||
addValue(parent, property.getValue(), currentMapper, entityName,
|
||||
xmlMappingData, auditingData.getPropertyAuditingData(propertyName),
|
||||
property.isInsertable(), firstPass);
|
||||
PropertyAuditingData propertyAuditingData = auditingData.getPropertyAuditingData(propertyName);
|
||||
if (propertyAuditingData != null) {
|
||||
addValue(parent, property.getValue(), currentMapper, entityName, xmlMappingData, propertyAuditingData,
|
||||
property.isInsertable(), firstPass);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
private void createJoins(PersistentClass pc, Element parent, PersistentClassAuditingData auditingData) {
|
||||
private void createJoins(PersistentClass pc, Element parent, ClassAuditingData auditingData) {
|
||||
Iterator<Join> joins = pc.getJoinIterator();
|
||||
|
||||
Map<Join, Element> joinElements = new HashMap<Join, Element>();
|
||||
|
@ -200,7 +202,7 @@ public final class AuditMetadataGenerator {
|
|||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
private void addJoins(PersistentClass pc, CompositeMapperBuilder currentMapper, PersistentClassAuditingData auditingData,
|
||||
private void addJoins(PersistentClass pc, CompositeMapperBuilder currentMapper, ClassAuditingData auditingData,
|
||||
String entityName, EntityXmlMappingData xmlMappingData,boolean firstPass) {
|
||||
Iterator<Join> joins = pc.getJoinIterator();
|
||||
|
||||
|
@ -255,7 +257,7 @@ public final class AuditMetadataGenerator {
|
|||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
public void generateFirstPass(PersistentClass pc, PersistentClassAuditingData auditingData,
|
||||
public void generateFirstPass(PersistentClass pc, ClassAuditingData auditingData,
|
||||
EntityXmlMappingData xmlMappingData) {
|
||||
String schema = auditingData.getAuditTable().schema();
|
||||
if (StringTools.isEmpty(schema)) {
|
||||
|
@ -334,7 +336,7 @@ public final class AuditMetadataGenerator {
|
|||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
public void generateSecondPass(PersistentClass pc, PersistentClassAuditingData auditingData,
|
||||
public void generateSecondPass(PersistentClass pc, ClassAuditingData auditingData,
|
||||
EntityXmlMappingData xmlMappingData) {
|
||||
String entityName = pc.getEntityName();
|
||||
|
||||
|
|
|
@ -28,6 +28,7 @@ import java.util.Properties;
|
|||
|
||||
import org.dom4j.Element;
|
||||
import org.hibernate.envers.entities.mapper.SimpleMapperBuilder;
|
||||
import org.hibernate.envers.configuration.metadata.reader.PropertyAuditingData;
|
||||
|
||||
import org.hibernate.mapping.Column;
|
||||
import org.hibernate.mapping.SimpleValue;
|
||||
|
@ -43,16 +44,16 @@ import org.hibernate.type.Type;
|
|||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public final class BasicMetadataGenerator {
|
||||
boolean addBasic(Element parent, PersistentPropertyAuditingData persistentPropertyAuditingData,
|
||||
boolean addBasic(Element parent, PropertyAuditingData propertyAuditingData,
|
||||
Value value, SimpleMapperBuilder mapper, boolean insertable, boolean key) {
|
||||
Type type = value.getType();
|
||||
|
||||
if (type instanceof ImmutableType || type instanceof MutableType) {
|
||||
addSimpleValue(parent, persistentPropertyAuditingData, value, mapper, insertable, key);
|
||||
addSimpleValue(parent, propertyAuditingData, value, mapper, insertable, key);
|
||||
} else if (type instanceof CustomType || type instanceof CompositeCustomType) {
|
||||
addCustomValue(parent, persistentPropertyAuditingData, value, mapper, insertable, key);
|
||||
addCustomValue(parent, propertyAuditingData, value, mapper, insertable, key);
|
||||
} else if ("org.hibernate.type.PrimitiveByteArrayBlobType".equals(type.getClass().getName())) {
|
||||
addSimpleValue(parent, persistentPropertyAuditingData, value, mapper, insertable, key);
|
||||
addSimpleValue(parent, propertyAuditingData, value, mapper, insertable, key);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
@ -61,25 +62,25 @@ public final class BasicMetadataGenerator {
|
|||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
private void addSimpleValue(Element parent, PersistentPropertyAuditingData persistentPropertyAuditingData,
|
||||
private void addSimpleValue(Element parent, PropertyAuditingData propertyAuditingData,
|
||||
Value value, SimpleMapperBuilder mapper, boolean insertable, boolean key) {
|
||||
if (parent != null) {
|
||||
Element prop_mapping = MetadataTools.addProperty(parent, persistentPropertyAuditingData.getName(),
|
||||
Element prop_mapping = MetadataTools.addProperty(parent, propertyAuditingData.getName(),
|
||||
value.getType().getName(), insertable, key);
|
||||
MetadataTools.addColumns(prop_mapping, (Iterator<Column>) value.getColumnIterator());
|
||||
}
|
||||
|
||||
// A null mapper means that we only want to add xml mappings
|
||||
if (mapper != null) {
|
||||
mapper.add(persistentPropertyAuditingData.getPropertyData());
|
||||
mapper.add(propertyAuditingData.getPropertyData());
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
private void addCustomValue(Element parent, PersistentPropertyAuditingData persistentPropertyAuditingData,
|
||||
private void addCustomValue(Element parent, PropertyAuditingData propertyAuditingData,
|
||||
Value value, SimpleMapperBuilder mapper, boolean insertable, boolean key) {
|
||||
if (parent != null) {
|
||||
Element prop_mapping = MetadataTools.addProperty(parent, persistentPropertyAuditingData.getName(),
|
||||
Element prop_mapping = MetadataTools.addProperty(parent, propertyAuditingData.getName(),
|
||||
null, insertable, key);
|
||||
|
||||
//CustomType propertyType = (CustomType) value.getType();
|
||||
|
@ -102,7 +103,7 @@ public final class BasicMetadataGenerator {
|
|||
}
|
||||
|
||||
if (mapper != null) {
|
||||
mapper.add(persistentPropertyAuditingData.getPropertyData());
|
||||
mapper.add(propertyAuditingData.getPropertyData());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,6 +36,7 @@ import javax.persistence.JoinColumn;
|
|||
|
||||
import org.dom4j.Element;
|
||||
import org.hibernate.envers.ModificationStore;
|
||||
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.mapper.CompositeMapperBuilder;
|
||||
|
@ -89,7 +90,7 @@ public final class CollectionMetadataGenerator {
|
|||
private final CompositeMapperBuilder currentMapper;
|
||||
private final String referencingEntityName;
|
||||
private final EntityXmlMappingData xmlMappingData;
|
||||
private final PersistentPropertyAuditingData persistentPropertyAuditingData;
|
||||
private final PropertyAuditingData propertyAuditingData;
|
||||
|
||||
private final EntityConfiguration referencingEntityConfiguration;
|
||||
/**
|
||||
|
@ -97,7 +98,7 @@ public final class CollectionMetadataGenerator {
|
|||
*/
|
||||
private final String referencedEntityName;
|
||||
|
||||
/**
|
||||
/**
|
||||
* @param mainGenerator Main generator, giving access to configuration and the basic mapper.
|
||||
* @param propertyValue Value of the collection, as mapped by Hibernate.
|
||||
* @param currentMapper Mapper, to which the appropriate {@link org.hibernate.envers.entities.mapper.PropertyMapper}
|
||||
|
@ -105,22 +106,22 @@ public final class CollectionMetadataGenerator {
|
|||
* @param referencingEntityName Name of the entity that owns this collection.
|
||||
* @param xmlMappingData In case this collection requires a middle table, additional mapping documents will
|
||||
* be created using this object.
|
||||
* @param persistentPropertyAuditingData Property auditing (meta-)data. Among other things, holds the name of the
|
||||
* @param propertyAuditingData Property auditing (meta-)data. Among other things, holds the name of the
|
||||
* property that references the collection in the referencing entity, the user data for middle (join)
|
||||
* table and the value of the <code>@MapKey</code> annotation, if there was one.
|
||||
*/
|
||||
public CollectionMetadataGenerator(AuditMetadataGenerator mainGenerator,
|
||||
Collection propertyValue, CompositeMapperBuilder currentMapper,
|
||||
String referencingEntityName, EntityXmlMappingData xmlMappingData,
|
||||
PersistentPropertyAuditingData persistentPropertyAuditingData) {
|
||||
PropertyAuditingData propertyAuditingData) {
|
||||
this.mainGenerator = mainGenerator;
|
||||
this.propertyValue = propertyValue;
|
||||
this.currentMapper = currentMapper;
|
||||
this.referencingEntityName = referencingEntityName;
|
||||
this.xmlMappingData = xmlMappingData;
|
||||
this.persistentPropertyAuditingData = persistentPropertyAuditingData;
|
||||
this.propertyAuditingData = propertyAuditingData;
|
||||
|
||||
this.propertyName = persistentPropertyAuditingData.getName();
|
||||
this.propertyName = propertyAuditingData.getName();
|
||||
|
||||
referencingEntityConfiguration = mainGenerator.getEntitiesConfigurations().get(referencingEntityName);
|
||||
if (referencingEntityConfiguration == null) {
|
||||
|
@ -189,7 +190,7 @@ public final class CollectionMetadataGenerator {
|
|||
// Creating common mapper data.
|
||||
CommonCollectionMapperData commonCollectionMapperData = new CommonCollectionMapperData(
|
||||
mainGenerator.getVerEntCfg(), referencedEntityName,
|
||||
persistentPropertyAuditingData.getPropertyData(),
|
||||
propertyAuditingData.getPropertyData(),
|
||||
referencingIdData, queryGenerator);
|
||||
|
||||
// Checking the type of the collection and adding an appropriate mapper.
|
||||
|
@ -235,9 +236,9 @@ public final class CollectionMetadataGenerator {
|
|||
// Generating the name of the middle table
|
||||
String auditMiddleTableName;
|
||||
String auditMiddleEntityName;
|
||||
if (!StringTools.isEmpty(persistentPropertyAuditingData.getJoinTable().name())) {
|
||||
auditMiddleTableName = persistentPropertyAuditingData.getJoinTable().name();
|
||||
auditMiddleEntityName = persistentPropertyAuditingData.getJoinTable().name();
|
||||
if (!StringTools.isEmpty(propertyAuditingData.getJoinTable().name())) {
|
||||
auditMiddleTableName = propertyAuditingData.getJoinTable().name();
|
||||
auditMiddleEntityName = propertyAuditingData.getJoinTable().name();
|
||||
} else {
|
||||
String middleTableName = getMiddleTableName(propertyValue, referencingEntityName);
|
||||
auditMiddleTableName = mainGenerator.getVerEntCfg().getAuditTableName(null, middleTableName);
|
||||
|
@ -301,7 +302,7 @@ public final class CollectionMetadataGenerator {
|
|||
// Generating the element mapping.
|
||||
// ******
|
||||
MiddleComponentData elementComponentData = addValueToMiddleTable(propertyValue.getElement(), middleEntityXml,
|
||||
queryGeneratorBuilder, referencedPrefix, persistentPropertyAuditingData.getJoinTable().inverseJoinColumns());
|
||||
queryGeneratorBuilder, referencedPrefix, propertyAuditingData.getJoinTable().inverseJoinColumns());
|
||||
|
||||
// ******
|
||||
// Generating the index mapping, if an index exists.
|
||||
|
@ -317,7 +318,7 @@ public final class CollectionMetadataGenerator {
|
|||
// Creating common data
|
||||
CommonCollectionMapperData commonCollectionMapperData = new CommonCollectionMapperData(
|
||||
mainGenerator.getVerEntCfg(), auditMiddleEntityName,
|
||||
persistentPropertyAuditingData.getPropertyData(),
|
||||
propertyAuditingData.getPropertyData(),
|
||||
referencingIdData, queryGenerator);
|
||||
|
||||
// Checking the type of the collection and adding an appropriate mapper.
|
||||
|
@ -332,7 +333,7 @@ public final class CollectionMetadataGenerator {
|
|||
private MiddleComponentData addIndex(Element middleEntityXml, QueryGeneratorBuilder queryGeneratorBuilder) {
|
||||
if (propertyValue instanceof IndexedCollection) {
|
||||
IndexedCollection indexedValue = (IndexedCollection) propertyValue;
|
||||
String mapKey = persistentPropertyAuditingData.getMapKey();
|
||||
String mapKey = propertyAuditingData.getMapKey();
|
||||
if (mapKey == null) {
|
||||
// This entity doesn't specify a javax.persistence.MapKey. Mapping it to the middle entity.
|
||||
return addValueToMiddleTable(indexedValue.getIndex(), middleEntityXml,
|
||||
|
@ -348,7 +349,7 @@ public final class CollectionMetadataGenerator {
|
|||
} else {
|
||||
// The key of the map is a property of the entity.
|
||||
return new MiddleComponentData(new MiddleMapKeyPropertyComponentMapper(mapKey,
|
||||
persistentPropertyAuditingData.getAccessType()), currentIndex);
|
||||
propertyAuditingData.getAccessType()), currentIndex);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -401,7 +402,7 @@ public final class CollectionMetadataGenerator {
|
|||
} else {
|
||||
// Last but one parameter: collection components are always insertable
|
||||
boolean mapped = mainGenerator.getBasicMetadataGenerator().addBasic(xmlMapping,
|
||||
new PersistentPropertyAuditingData(prefix, "field", ModificationStore.FULL), value, null,
|
||||
new PropertyAuditingData(prefix, "field", ModificationStore.FULL), value, null,
|
||||
true, true);
|
||||
|
||||
if (mapped) {
|
||||
|
@ -419,30 +420,30 @@ public final class CollectionMetadataGenerator {
|
|||
MiddleComponentData indexComponentData) {
|
||||
Type type = propertyValue.getType();
|
||||
if (type instanceof SortedSetType) {
|
||||
currentMapper.addComposite(persistentPropertyAuditingData.getPropertyData(),
|
||||
currentMapper.addComposite(propertyAuditingData.getPropertyData(),
|
||||
new BasicCollectionMapper<Set>(commonCollectionMapperData,
|
||||
TreeSet.class, SortedSetProxy.class, elementComponentData));
|
||||
} else if (type instanceof SetType) {
|
||||
currentMapper.addComposite(persistentPropertyAuditingData.getPropertyData(),
|
||||
currentMapper.addComposite(propertyAuditingData.getPropertyData(),
|
||||
new BasicCollectionMapper<Set>(commonCollectionMapperData,
|
||||
HashSet.class, SetProxy.class, elementComponentData));
|
||||
} else if (type instanceof SortedMapType) {
|
||||
// Indexed collection, so <code>indexComponentData</code> is not null.
|
||||
currentMapper.addComposite(persistentPropertyAuditingData.getPropertyData(),
|
||||
currentMapper.addComposite(propertyAuditingData.getPropertyData(),
|
||||
new MapCollectionMapper<Map>(commonCollectionMapperData,
|
||||
TreeMap.class, SortedMapProxy.class, elementComponentData, indexComponentData));
|
||||
} else if (type instanceof MapType) {
|
||||
// Indexed collection, so <code>indexComponentData</code> is not null.
|
||||
currentMapper.addComposite(persistentPropertyAuditingData.getPropertyData(),
|
||||
currentMapper.addComposite(propertyAuditingData.getPropertyData(),
|
||||
new MapCollectionMapper<Map>(commonCollectionMapperData,
|
||||
HashMap.class, MapProxy.class, elementComponentData, indexComponentData));
|
||||
} else if (type instanceof BagType) {
|
||||
currentMapper.addComposite(persistentPropertyAuditingData.getPropertyData(),
|
||||
currentMapper.addComposite(propertyAuditingData.getPropertyData(),
|
||||
new BasicCollectionMapper<List>(commonCollectionMapperData,
|
||||
ArrayList.class, ListProxy.class, elementComponentData));
|
||||
} else if (type instanceof ListType) {
|
||||
// Indexed collection, so <code>indexComponentData</code> is not null.
|
||||
currentMapper.addComposite(persistentPropertyAuditingData.getPropertyData(),
|
||||
currentMapper.addComposite(propertyAuditingData.getPropertyData(),
|
||||
new ListCollectionMapper(commonCollectionMapperData,
|
||||
elementComponentData, indexComponentData));
|
||||
} else {
|
||||
|
@ -462,10 +463,10 @@ public final class CollectionMetadataGenerator {
|
|||
}
|
||||
|
||||
private Element createMiddleEntityXml(String auditMiddleTableName, String auditMiddleEntityName) {
|
||||
String schema = StringTools.isEmpty(persistentPropertyAuditingData.getJoinTable().schema()) ?
|
||||
propertyValue.getCollectionTable().getSchema() : persistentPropertyAuditingData.getJoinTable().schema();
|
||||
String catalog = StringTools.isEmpty(persistentPropertyAuditingData.getJoinTable().catalog()) ?
|
||||
propertyValue.getCollectionTable().getCatalog() : persistentPropertyAuditingData.getJoinTable().catalog();
|
||||
String schema = StringTools.isEmpty(propertyAuditingData.getJoinTable().schema()) ?
|
||||
propertyValue.getCollectionTable().getSchema() : propertyAuditingData.getJoinTable().schema();
|
||||
String catalog = StringTools.isEmpty(propertyAuditingData.getJoinTable().catalog()) ?
|
||||
propertyValue.getCollectionTable().getCatalog() : propertyAuditingData.getJoinTable().catalog();
|
||||
|
||||
Element middleEntityXml = MetadataTools.createEntity(xmlMappingData.newAdditionalMapping(),
|
||||
new AuditTableData(auditMiddleEntityName, auditMiddleTableName, schema, catalog), null);
|
||||
|
|
|
@ -5,7 +5,8 @@ import org.hibernate.mapping.Value;
|
|||
import org.hibernate.mapping.Component;
|
||||
import org.hibernate.mapping.Property;
|
||||
import org.hibernate.envers.entities.mapper.CompositeMapperBuilder;
|
||||
import org.hibernate.envers.ModificationStore;
|
||||
import org.hibernate.envers.configuration.metadata.reader.ComponentAuditingData;
|
||||
import org.hibernate.envers.configuration.metadata.reader.PropertyAuditingData;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
|
@ -21,25 +22,24 @@ public final class ComponentMetadataGenerator {
|
|||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
public void addComponent(Element parent, PersistentPropertyAuditingData persistentPropertyAuditingData,
|
||||
public void addComponent(Element parent, PropertyAuditingData propertyAuditingData,
|
||||
Value value, CompositeMapperBuilder mapper, String entityName,
|
||||
EntityXmlMappingData xmlMappingData, boolean firstPass) {
|
||||
Component prop_component = (Component) value;
|
||||
|
||||
CompositeMapperBuilder componentMapper = mapper.addComponent(persistentPropertyAuditingData.getPropertyData());
|
||||
CompositeMapperBuilder componentMapper = mapper.addComponent(propertyAuditingData.getPropertyData());
|
||||
|
||||
// The property auditing data must be for a component.
|
||||
ComponentAuditingData componentAuditingData = (ComponentAuditingData) propertyAuditingData;
|
||||
|
||||
// Adding all properties of the component
|
||||
Iterator<Property> properties = (Iterator<Property>) prop_component.getPropertyIterator();
|
||||
while (properties.hasNext()) {
|
||||
Property property = properties.next();
|
||||
// The name of the property in the entity will consist of the name of the component property concatenated
|
||||
// with the name of the property in the bean, to avoid conflicts.
|
||||
PersistentPropertyAuditingData propertyAuditingData = new PersistentComponentPropertyAuditingData(
|
||||
persistentPropertyAuditingData.getName() + "_" + property.getName(),
|
||||
property.getName(), property.getPropertyAccessorName(), ModificationStore.FULL);
|
||||
|
||||
mainGenerator.addValue(parent, property.getValue(), componentMapper,
|
||||
entityName, xmlMappingData, propertyAuditingData, property.isInsertable(), firstPass);
|
||||
mainGenerator.addValue(parent, property.getValue(), componentMapper, entityName, xmlMappingData,
|
||||
componentAuditingData.getPropertyAuditingData(property.getName()),
|
||||
property.isInsertable(), firstPass);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@ import java.util.Iterator;
|
|||
import org.dom4j.Element;
|
||||
import org.dom4j.tree.DefaultElement;
|
||||
import org.hibernate.envers.ModificationStore;
|
||||
import org.hibernate.envers.configuration.metadata.reader.PropertyAuditingData;
|
||||
import org.hibernate.envers.entities.IdMappingData;
|
||||
import org.hibernate.envers.entities.PropertyData;
|
||||
import org.hibernate.envers.entities.mapper.SimpleMapperBuilder;
|
||||
|
@ -130,8 +131,8 @@ public final class IdMetadataGenerator {
|
|||
ModificationStore.FULL);
|
||||
}
|
||||
|
||||
private PersistentPropertyAuditingData getIdPersistentPropertyAuditingData(Property property) {
|
||||
return new PersistentPropertyAuditingData(property.getName(), property.getPropertyAccessorName(),
|
||||
private PropertyAuditingData getIdPersistentPropertyAuditingData(Property property) {
|
||||
return new PropertyAuditingData(property.getName(), property.getPropertyAccessorName(),
|
||||
ModificationStore.FULL);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@ 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.MappingException;
|
||||
import org.hibernate.mapping.OneToOne;
|
||||
|
@ -49,7 +50,7 @@ public final class ToOneRelationMetadataGenerator {
|
|||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
void addToOne(Element parent, PersistentPropertyAuditingData persistentPropertyAuditingData, Value value,
|
||||
void addToOne(Element parent, PropertyAuditingData propertyAuditingData, Value value,
|
||||
CompositeMapperBuilder mapper, String entityName, boolean insertable) {
|
||||
String referencedEntityName = ((ToOne) value).getReferencedEntityName();
|
||||
|
||||
|
@ -60,30 +61,30 @@ public final class ToOneRelationMetadataGenerator {
|
|||
|
||||
IdMappingData idMapping = configuration.getIdMappingData();
|
||||
|
||||
String lastPropertyPrefix = persistentPropertyAuditingData.getName() + "_";
|
||||
String lastPropertyPrefix = propertyAuditingData.getName() + "_";
|
||||
|
||||
// Generating the id mapper for the relation
|
||||
IdMapper relMapper = idMapping.getIdMapper().prefixMappedProperties(lastPropertyPrefix);
|
||||
|
||||
// Storing information about this relation
|
||||
mainGenerator.getEntitiesConfigurations().get(entityName).addToOneRelation(
|
||||
persistentPropertyAuditingData.getName(), referencedEntityName, relMapper);
|
||||
propertyAuditingData.getName(), referencedEntityName, relMapper);
|
||||
|
||||
// Adding an element to the mapping corresponding to the references entity id's
|
||||
Element properties = (Element) idMapping.getXmlRelationMapping().clone();
|
||||
properties.addAttribute("name", persistentPropertyAuditingData.getName());
|
||||
properties.addAttribute("name", propertyAuditingData.getName());
|
||||
|
||||
MetadataTools.prefixNamesInPropertyElement(properties, lastPropertyPrefix,
|
||||
MetadataTools.getColumnNameIterator(value.getColumnIterator()), false, insertable);
|
||||
parent.add(properties);
|
||||
|
||||
// Adding mapper for the id
|
||||
PropertyData propertyData = persistentPropertyAuditingData.getPropertyData();
|
||||
PropertyData propertyData = propertyAuditingData.getPropertyData();
|
||||
mapper.addComposite(propertyData, new ToOneIdMapper(relMapper, propertyData, referencedEntityName));
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
void addOneToOneNotOwning(PersistentPropertyAuditingData persistentPropertyAuditingData, Value value,
|
||||
void addOneToOneNotOwning(PropertyAuditingData propertyAuditingData, Value value,
|
||||
CompositeMapperBuilder mapper, String entityName) {
|
||||
OneToOne propertyValue = (OneToOne) value;
|
||||
|
||||
|
@ -108,11 +109,11 @@ public final class ToOneRelationMetadataGenerator {
|
|||
|
||||
// Storing information about this relation
|
||||
mainGenerator.getEntitiesConfigurations().get(entityName).addToOneNotOwningRelation(
|
||||
persistentPropertyAuditingData.getName(), owningReferencePropertyName,
|
||||
propertyAuditingData.getName(), owningReferencePropertyName,
|
||||
referencedEntityName, ownedIdMapper);
|
||||
|
||||
// Adding mapper for the id
|
||||
PropertyData propertyData = persistentPropertyAuditingData.getPropertyData();
|
||||
PropertyData propertyData = propertyAuditingData.getPropertyData();
|
||||
mapper.addComposite(propertyData, new OneToOneNotOwningMapper(owningReferencePropertyName,
|
||||
referencedEntityName, propertyData));
|
||||
}
|
||||
|
|
|
@ -0,0 +1,153 @@
|
|||
/*
|
||||
* 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.configuration.metadata.reader;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.util.Iterator;
|
||||
|
||||
import org.hibernate.envers.SecondaryAuditTable;
|
||||
import org.hibernate.envers.*;
|
||||
import org.hibernate.envers.ModificationStore;
|
||||
import org.hibernate.envers.configuration.GlobalConfiguration;
|
||||
|
||||
import org.hibernate.MappingException;
|
||||
import org.hibernate.annotations.common.reflection.ReflectionManager;
|
||||
import org.hibernate.annotations.common.reflection.XClass;
|
||||
import org.hibernate.mapping.PersistentClass;
|
||||
import org.hibernate.mapping.Property;
|
||||
import org.jboss.envers.*;
|
||||
|
||||
/**
|
||||
* A helper class to read versioning meta-data from annotations on a persistent class.
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
* @author Sebastian Komander
|
||||
*/
|
||||
public final class AnnotationsMetadataReader {
|
||||
private final GlobalConfiguration globalCfg;
|
||||
private final ReflectionManager reflectionManager;
|
||||
private final PersistentClass pc;
|
||||
|
||||
/**
|
||||
* This object is filled with information read from annotations and returned by the <code>getVersioningData</code>
|
||||
* method.
|
||||
*/
|
||||
private final ClassAuditingData auditData;
|
||||
|
||||
public AnnotationsMetadataReader(GlobalConfiguration globalCfg, ReflectionManager reflectionManager,
|
||||
PersistentClass pc) {
|
||||
this.globalCfg = globalCfg;
|
||||
this.reflectionManager = reflectionManager;
|
||||
this.pc = pc;
|
||||
|
||||
auditData = new ClassAuditingData();
|
||||
}
|
||||
|
||||
private ModificationStore getDefaultAudited(XClass clazz) {
|
||||
Audited defaultAudited = clazz.getAnnotation(Audited.class);
|
||||
|
||||
if (defaultAudited != null) {
|
||||
return defaultAudited.modStore();
|
||||
} else {
|
||||
Versioned defaultVersioned = clazz.getAnnotation(Versioned.class);
|
||||
if (defaultVersioned != null) {
|
||||
return ModificationStore.FULL;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void addAuditTable(XClass clazz) {
|
||||
AuditTable auditTable = clazz.getAnnotation(AuditTable.class);
|
||||
if (auditTable != null) {
|
||||
auditData.setAuditTable(auditTable);
|
||||
} else {
|
||||
auditData.setAuditTable(getDefaultAuditTable());
|
||||
}
|
||||
}
|
||||
|
||||
private void addAuditSecondaryTables(XClass clazz) {
|
||||
// Getting information on secondary tables
|
||||
SecondaryAuditTable secondaryVersionsTable1 = clazz.getAnnotation(SecondaryAuditTable.class);
|
||||
if (secondaryVersionsTable1 != null) {
|
||||
auditData.getSecondaryTableDictionary().put(secondaryVersionsTable1.secondaryTableName(),
|
||||
secondaryVersionsTable1.secondaryAuditTableName());
|
||||
}
|
||||
|
||||
SecondaryAuditTables secondaryAuditTables = clazz.getAnnotation(SecondaryAuditTables.class);
|
||||
if (secondaryAuditTables != null) {
|
||||
for (SecondaryAuditTable secondaryAuditTable2 : secondaryAuditTables.value()) {
|
||||
auditData.getSecondaryTableDictionary().put(secondaryAuditTable2.secondaryTableName(),
|
||||
secondaryAuditTable2.secondaryAuditTableName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public ClassAuditingData getAuditData() {
|
||||
if (pc.getClassName() == null) {
|
||||
return auditData;
|
||||
}
|
||||
|
||||
try {
|
||||
XClass xclass = reflectionManager.classForName(pc.getClassName(), this.getClass());
|
||||
|
||||
ModificationStore defaultStore = getDefaultAudited(xclass);
|
||||
if (defaultStore != null) {
|
||||
auditData.setDefaultAudited(true);
|
||||
}
|
||||
|
||||
new AuditedPropertiesReader(defaultStore, new PersistentClassPropertiesSource(xclass), auditData,
|
||||
globalCfg, "").read();
|
||||
|
||||
addAuditTable(xclass);
|
||||
addAuditSecondaryTables(xclass);
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new MappingException(e);
|
||||
}
|
||||
|
||||
return auditData;
|
||||
}
|
||||
|
||||
private AuditTable defaultAuditTable = new AuditTable() {
|
||||
public String value() { return ""; }
|
||||
public String schema() { return ""; }
|
||||
public String catalog() { return ""; }
|
||||
public Class<? extends Annotation> annotationType() { return this.getClass(); }
|
||||
};
|
||||
|
||||
private AuditTable getDefaultAuditTable() {
|
||||
return defaultAuditTable;
|
||||
}
|
||||
|
||||
private class PersistentClassPropertiesSource implements PersistentPropertiesSource {
|
||||
private final XClass xclass;
|
||||
|
||||
private PersistentClassPropertiesSource(XClass xclass) { this.xclass = xclass; }
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
public Iterator<Property> getPropertyIterator() { return pc.getPropertyIterator(); }
|
||||
public Property getProperty(String propertyName) { return pc.getProperty(propertyName); }
|
||||
public XClass getXClass() { return xclass; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
package org.hibernate.envers.configuration.metadata.reader;
|
||||
|
||||
/**
|
||||
* Implementations hold other audited properties.
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public interface AuditedPropertiesHolder {
|
||||
/**
|
||||
* Add an audited property.
|
||||
* @param propertyName Name of the audited property.
|
||||
* @param auditingData Data for the audited property.
|
||||
*/
|
||||
void addPropertyAuditingData(String propertyName, PropertyAuditingData auditingData);
|
||||
|
||||
/**
|
||||
* @param propertyName Name of a property.
|
||||
* @return Auditing data for the property.
|
||||
*/
|
||||
PropertyAuditingData getPropertyAuditingData(String propertyName);
|
||||
}
|
|
@ -0,0 +1,210 @@
|
|||
package org.hibernate.envers.configuration.metadata.reader;
|
||||
|
||||
import org.hibernate.envers.ModificationStore;
|
||||
import org.hibernate.envers.NotAudited;
|
||||
import org.hibernate.envers.Audited;
|
||||
import org.hibernate.envers.AuditJoinTable;
|
||||
import org.hibernate.envers.configuration.GlobalConfiguration;
|
||||
import static org.hibernate.envers.tools.Tools.*;
|
||||
import org.hibernate.envers.tools.MappingTools;
|
||||
import org.hibernate.mapping.Property;
|
||||
import org.hibernate.mapping.Component;
|
||||
import org.hibernate.mapping.Value;
|
||||
import org.hibernate.annotations.common.reflection.XProperty;
|
||||
import org.hibernate.annotations.common.reflection.XClass;
|
||||
import org.jboss.envers.Versioned;
|
||||
|
||||
import javax.persistence.Version;
|
||||
import javax.persistence.MapKey;
|
||||
import javax.persistence.JoinColumn;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
import java.lang.annotation.Annotation;
|
||||
|
||||
/**
|
||||
* Reads persistent properties form a
|
||||
* {@link org.hibernate.envers.configuration.metadata.reader.PersistentPropertiesSource}
|
||||
* and adds the ones that are audited to a
|
||||
* {@link org.hibernate.envers.configuration.metadata.reader.AuditedPropertiesHolder},
|
||||
* filling all the auditing data.
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public class AuditedPropertiesReader {
|
||||
private final ModificationStore defaultStore;
|
||||
private final PersistentPropertiesSource persistentPropertiesSource;
|
||||
private final AuditedPropertiesHolder auditedPropertiesHolder;
|
||||
private final GlobalConfiguration globalCfg;
|
||||
private final String propertyNamePrefix;
|
||||
|
||||
private final Set<String> propertyAccessedPersistentProperties;
|
||||
private final Set<String> fieldAccessedPersistentProperties;
|
||||
|
||||
public AuditedPropertiesReader(ModificationStore defaultStore,
|
||||
PersistentPropertiesSource persistentPropertiesSource,
|
||||
AuditedPropertiesHolder auditedPropertiesHolder,
|
||||
GlobalConfiguration globalCfg,
|
||||
String propertyNamePrefix) {
|
||||
this.defaultStore = defaultStore;
|
||||
this.persistentPropertiesSource = persistentPropertiesSource;
|
||||
this.auditedPropertiesHolder = auditedPropertiesHolder;
|
||||
this.globalCfg = globalCfg;
|
||||
this.propertyNamePrefix = propertyNamePrefix;
|
||||
|
||||
propertyAccessedPersistentProperties = newHashSet();
|
||||
fieldAccessedPersistentProperties = newHashSet();
|
||||
}
|
||||
|
||||
public void read() {
|
||||
// First reading the access types for the persistent properties.
|
||||
readPersistentPropertiesAccess();
|
||||
|
||||
// Adding all properties from the given class.
|
||||
addPropertiesFromClass(persistentPropertiesSource.getXClass());
|
||||
}
|
||||
|
||||
private void readPersistentPropertiesAccess() {
|
||||
Iterator propertyIter = persistentPropertiesSource.getPropertyIterator();
|
||||
while (propertyIter.hasNext()) {
|
||||
Property property = (Property) propertyIter.next();
|
||||
if ("field".equals(property.getPropertyAccessorName())) {
|
||||
fieldAccessedPersistentProperties.add(property.getName());
|
||||
} else {
|
||||
propertyAccessedPersistentProperties.add(property.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void addPropertiesFromClass(XClass clazz) {
|
||||
XClass superclazz = clazz.getSuperclass();
|
||||
if (!"java.lang.Object".equals(superclazz.getName())) {
|
||||
addPropertiesFromClass(superclazz);
|
||||
}
|
||||
|
||||
addFromProperties(clazz.getDeclaredProperties("field"), "field", fieldAccessedPersistentProperties);
|
||||
addFromProperties(clazz.getDeclaredProperties("property"), "property", propertyAccessedPersistentProperties);
|
||||
}
|
||||
|
||||
private void addFromProperties(Iterable<XProperty> properties, String accessType, Set<String> persistentProperties) {
|
||||
for (XProperty property : properties) {
|
||||
// If this is not a persistent property, with the same access type as currently checked,
|
||||
// it's not audited as well.
|
||||
if (persistentProperties.contains(property.getName())) {
|
||||
Value propertyValue = persistentPropertiesSource.getProperty(property.getName()).getValue();
|
||||
|
||||
PropertyAuditingData propertyData;
|
||||
boolean isAudited;
|
||||
if (propertyValue instanceof Component) {
|
||||
ComponentAuditingData componentData = new ComponentAuditingData();
|
||||
isAudited = fillPropertyData(property, componentData, accessType);
|
||||
|
||||
// TODO: component stuff
|
||||
PersistentPropertiesSource componentPropertiesSource = new ComponentPropertiesSource(
|
||||
property.getType(), (Component) propertyValue);
|
||||
new AuditedPropertiesReader(ModificationStore.FULL, componentPropertiesSource, componentData,
|
||||
globalCfg, propertyNamePrefix+ MappingTools.createComponentPrefix(property.getName()))
|
||||
.read();
|
||||
|
||||
propertyData = componentData;
|
||||
} else {
|
||||
propertyData = new PropertyAuditingData();
|
||||
isAudited = fillPropertyData(property, propertyData, accessType);
|
||||
}
|
||||
|
||||
if (isAudited) {
|
||||
// Now we know that the property is audited
|
||||
auditedPropertiesHolder.addPropertyAuditingData(property.getName(), propertyData);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a property is audited and if yes, fills all of its data.
|
||||
* @param property Property to check.
|
||||
* @param propertyData Property data, on which to set this property's modification store.
|
||||
* @param accessType Access type for the property.
|
||||
* @return False if this property is not audited.
|
||||
*/
|
||||
private boolean fillPropertyData(XProperty property, PropertyAuditingData propertyData,
|
||||
String accessType) {
|
||||
|
||||
// check if a property is declared as not audited to exclude it
|
||||
// useful if a class is audited but some properties should be excluded
|
||||
NotAudited unVer = property.getAnnotation(NotAudited.class);
|
||||
if (unVer != null) {
|
||||
return false;
|
||||
} else {
|
||||
// if the optimistic locking field has to be unversioned and the current property
|
||||
// is the optimistic locking field, don't audit it
|
||||
if (globalCfg.isDoNotAuditOptimisticLockingField()) {
|
||||
Version jpaVer = property.getAnnotation(Version.class);
|
||||
if (jpaVer != null) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Checking if this property is explicitly audited or if all properties are.
|
||||
Audited aud = property.getAnnotation(Audited.class);
|
||||
Versioned ver = property.getAnnotation(Versioned.class);
|
||||
if (aud != null) {
|
||||
propertyData.setStore(aud.modStore());
|
||||
} else if (ver != null) {
|
||||
propertyData.setStore(ModificationStore.FULL);
|
||||
} else {
|
||||
if (defaultStore != null) {
|
||||
propertyData.setStore(defaultStore);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
propertyData.setName(propertyNamePrefix + property.getName());
|
||||
propertyData.setBeanName(property.getName());
|
||||
propertyData.setAccessType(accessType);
|
||||
|
||||
addPropertyJoinTables(property, propertyData);
|
||||
addPropertyMapKey(property, propertyData);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void addPropertyMapKey(XProperty property, PropertyAuditingData propertyData) {
|
||||
MapKey mapKey = property.getAnnotation(MapKey.class);
|
||||
if (mapKey != null) {
|
||||
propertyData.setMapKey(mapKey.name());
|
||||
}
|
||||
}
|
||||
|
||||
private void addPropertyJoinTables(XProperty property, PropertyAuditingData propertyData) {
|
||||
AuditJoinTable joinTable = property.getAnnotation(AuditJoinTable.class);
|
||||
if (joinTable != null) {
|
||||
propertyData.setJoinTable(joinTable);
|
||||
} else {
|
||||
propertyData.setJoinTable(DEFAULT_AUDIT_JOIN_TABLE);
|
||||
}
|
||||
}
|
||||
|
||||
private static AuditJoinTable DEFAULT_AUDIT_JOIN_TABLE = new AuditJoinTable() {
|
||||
public String name() { return ""; }
|
||||
public String schema() { return ""; }
|
||||
public String catalog() { return ""; }
|
||||
public JoinColumn[] inverseJoinColumns() { return new JoinColumn[0]; }
|
||||
public Class<? extends Annotation> annotationType() { return this.getClass(); }
|
||||
};
|
||||
|
||||
private class ComponentPropertiesSource implements PersistentPropertiesSource {
|
||||
private final XClass xclass;
|
||||
private final Component component;
|
||||
|
||||
private ComponentPropertiesSource(XClass xclass, Component component) {
|
||||
this.xclass = xclass;
|
||||
this.component = component;
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
public Iterator<Property> getPropertyIterator() { return component.getPropertyIterator(); }
|
||||
public Property getProperty(String propertyName) { return component.getProperty(propertyName); }
|
||||
public XClass getXClass() { return xclass; }
|
||||
}
|
||||
}
|
|
@ -21,37 +21,39 @@
|
|||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.envers.configuration.metadata;
|
||||
package org.hibernate.envers.configuration.metadata.reader;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.hibernate.envers.AuditTable;
|
||||
import org.hibernate.envers.tools.Tools;
|
||||
import static org.hibernate.envers.tools.Tools.*;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
* @author Sebastian Komander
|
||||
*/
|
||||
public class PersistentClassAuditingData {
|
||||
public PersistentClassAuditingData() {
|
||||
properties = Tools.newHashMap();
|
||||
secondaryTableDictionary = Tools.newHashMap();
|
||||
}
|
||||
public class ClassAuditingData implements AuditedPropertiesHolder {
|
||||
private final Map<String, PropertyAuditingData> properties;
|
||||
private final Map<String, String> secondaryTableDictionary;
|
||||
|
||||
private Map<String, PersistentPropertyAuditingData> properties;
|
||||
private AuditTable auditTable;
|
||||
private Map<String, String> secondaryTableDictionary;
|
||||
|
||||
/**
|
||||
* True if the class is audited globally (this helps to cover the cases when there are no fields in the class,
|
||||
* but it's still audited).
|
||||
*/
|
||||
private boolean defaultAudited;
|
||||
|
||||
public Map<String, PersistentPropertyAuditingData> getProperties() {
|
||||
return properties;
|
||||
public ClassAuditingData() {
|
||||
properties = newHashMap();
|
||||
secondaryTableDictionary = newHashMap();
|
||||
}
|
||||
|
||||
public PersistentPropertyAuditingData getPropertyAuditingData(String propertyName) {
|
||||
public void addPropertyAuditingData(String propertyName, PropertyAuditingData auditingData) {
|
||||
properties.put(propertyName, auditingData);
|
||||
}
|
||||
|
||||
public PropertyAuditingData getPropertyAuditingData(String propertyName) {
|
||||
return properties.get(propertyName);
|
||||
}
|
||||
|
||||
|
@ -72,10 +74,6 @@ public class PersistentClassAuditingData {
|
|||
}
|
||||
|
||||
public boolean isAudited() {
|
||||
if (defaultAudited || properties.size() > 0) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return defaultAudited || properties.size() > 0;
|
||||
}
|
||||
}
|
|
@ -22,25 +22,28 @@
|
|||
* Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
package org.hibernate.envers.configuration.metadata;
|
||||
package org.hibernate.envers.configuration.metadata.reader;
|
||||
|
||||
import org.hibernate.envers.ModificationStore;
|
||||
import org.hibernate.envers.entities.PropertyData;
|
||||
import static org.hibernate.envers.tools.Tools.*;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Audit mapping meta-data for component.
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public class PersistentComponentPropertyAuditingData extends PersistentPropertyAuditingData {
|
||||
private final String beanName;
|
||||
public class ComponentAuditingData extends PropertyAuditingData implements AuditedPropertiesHolder {
|
||||
private final Map<String, PropertyAuditingData> properties;
|
||||
|
||||
public PersistentComponentPropertyAuditingData(String name, String beanName, String accessType,
|
||||
ModificationStore store) {
|
||||
super(name, accessType, store);
|
||||
|
||||
this.beanName = beanName;
|
||||
}
|
||||
|
||||
public PropertyData getPropertyData() {
|
||||
return new PropertyData(getName(), beanName, getAccessType(), getStore());
|
||||
public ComponentAuditingData() {
|
||||
this.properties = newHashMap();
|
||||
}
|
||||
|
||||
public void addPropertyAuditingData(String propertyName, PropertyAuditingData auditingData) {
|
||||
properties.put(propertyName, auditingData);
|
||||
}
|
||||
|
||||
public PropertyAuditingData getPropertyAuditingData(String propertyName) {
|
||||
return properties.get(propertyName);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,16 @@
|
|||
package org.hibernate.envers.configuration.metadata.reader;
|
||||
|
||||
import org.hibernate.mapping.Property;
|
||||
import org.hibernate.annotations.common.reflection.XClass;
|
||||
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* A source of data on persistent properties of a class or component.
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public interface PersistentPropertiesSource {
|
||||
Iterator<Property> getPropertyIterator();
|
||||
Property getProperty(String propertyName);
|
||||
XClass getXClass();
|
||||
}
|
|
@ -22,7 +22,7 @@
|
|||
* Boston, MA 02110-1301 USA
|
||||
*
|
||||
*/
|
||||
package org.hibernate.envers.configuration.metadata;
|
||||
package org.hibernate.envers.configuration.metadata.reader;
|
||||
|
||||
import org.hibernate.envers.ModificationStore;
|
||||
import org.hibernate.envers.AuditJoinTable;
|
||||
|
@ -31,23 +31,25 @@ import org.hibernate.envers.entities.PropertyData;
|
|||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public class PersistentPropertyAuditingData {
|
||||
public class PropertyAuditingData {
|
||||
private String name;
|
||||
private String beanName;
|
||||
private ModificationStore store;
|
||||
private String mapKey;
|
||||
private AuditJoinTable joinTable;
|
||||
private String accessType;
|
||||
|
||||
public PersistentPropertyAuditingData() {
|
||||
public PropertyAuditingData() {
|
||||
}
|
||||
|
||||
public PersistentPropertyAuditingData(String name, String accessType, ModificationStore store) {
|
||||
public PropertyAuditingData(String name, String accessType, ModificationStore store) {
|
||||
this.name = name;
|
||||
this.beanName = name;
|
||||
this.accessType = accessType;
|
||||
this.store = store;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
|
@ -55,7 +57,15 @@ public class PersistentPropertyAuditingData {
|
|||
this.name = name;
|
||||
}
|
||||
|
||||
public ModificationStore getStore() {
|
||||
public String getBeanName() {
|
||||
return beanName;
|
||||
}
|
||||
|
||||
public void setBeanName(String beanName) {
|
||||
this.beanName = beanName;
|
||||
}
|
||||
|
||||
public ModificationStore getStore() {
|
||||
return store;
|
||||
}
|
||||
|
||||
|
@ -88,6 +98,6 @@ public class PersistentPropertyAuditingData {
|
|||
}
|
||||
|
||||
public PropertyData getPropertyData() {
|
||||
return new PropertyData(name, name, accessType, store);
|
||||
return new PropertyData(name, beanName, accessType, store);
|
||||
}
|
||||
}
|
|
@ -32,6 +32,7 @@ import org.hibernate.envers.configuration.AuditConfiguration;
|
|||
import org.hibernate.envers.reader.AuditReaderImplementor;
|
||||
import org.hibernate.envers.tools.reflection.ReflectionTools;
|
||||
import org.hibernate.envers.tools.Tools;
|
||||
import org.hibernate.envers.tools.MappingTools;
|
||||
|
||||
import org.hibernate.collection.PersistentCollection;
|
||||
import org.hibernate.property.Getter;
|
||||
|
@ -120,9 +121,30 @@ public class MultiPropertyMapper implements ExtendedPropertyMapper {
|
|||
PersistentCollection newColl,
|
||||
Serializable oldColl,
|
||||
Serializable id) {
|
||||
// Name of the properyt, to which we will delegate the mapping.
|
||||
String delegatePropertyName;
|
||||
|
||||
// Checking if the property name doesn't reference a collection in a component - then the name will containa a .
|
||||
int dotIndex = referencingPropertyName.indexOf('.');
|
||||
if (dotIndex != -1) {
|
||||
// Computing the name of the component
|
||||
String componentName = referencingPropertyName.substring(0, dotIndex);
|
||||
// And the name of the property in the component
|
||||
String propertyInComponentName = MappingTools.createComponentPrefix(componentName)
|
||||
+ referencingPropertyName.substring(dotIndex+1);
|
||||
|
||||
// We need to get the mapper for the component.
|
||||
referencingPropertyName = componentName;
|
||||
// As this is a component, we delegate to the property in the component.
|
||||
delegatePropertyName = propertyInComponentName;
|
||||
} else {
|
||||
// If this is not a component, we delegate to the same property.
|
||||
delegatePropertyName = referencingPropertyName;
|
||||
}
|
||||
|
||||
PropertyMapper mapper = properties.get(propertyDatas.get(referencingPropertyName));
|
||||
if (mapper != null) {
|
||||
return mapper.mapCollectionChanges(referencingPropertyName, newColl, oldColl, id);
|
||||
return mapper.mapCollectionChanges(delegatePropertyName, newColl, oldColl, id);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
package org.hibernate.envers.tools;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public class MappingTools {
|
||||
/**
|
||||
* @param componentName Name of the component, that is, name of the property in the entity that references the
|
||||
* component.
|
||||
* @return A prefix for properties in the given component.
|
||||
*/
|
||||
public static String createComponentPrefix(String componentName) {
|
||||
return componentName + "_";
|
||||
}
|
||||
}
|
|
@ -23,9 +23,12 @@
|
|||
*/
|
||||
package org.hibernate.envers.test.entities.components;
|
||||
|
||||
import javax.persistence.Embeddable;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
@Embeddable
|
||||
public class Component1 {
|
||||
private String str1;
|
||||
|
||||
|
|
|
@ -23,9 +23,12 @@
|
|||
*/
|
||||
package org.hibernate.envers.test.entities.components;
|
||||
|
||||
import javax.persistence.Embeddable;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
@Embeddable
|
||||
public class Component2 {
|
||||
private String str5;
|
||||
|
||||
|
|
|
@ -0,0 +1,88 @@
|
|||
/*
|
||||
* 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.entities.components.relations;
|
||||
|
||||
import org.hibernate.envers.test.entities.StrTestEntity;
|
||||
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.Embeddable;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
@Embeddable
|
||||
public class ManyToOneComponent {
|
||||
@ManyToOne
|
||||
private StrTestEntity entity;
|
||||
|
||||
private String data;
|
||||
|
||||
public ManyToOneComponent(StrTestEntity entity, String data) {
|
||||
this.entity = entity;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public ManyToOneComponent() {
|
||||
}
|
||||
|
||||
public String getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public void setData(String data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public StrTestEntity getEntity() {
|
||||
return entity;
|
||||
}
|
||||
|
||||
public void setEntity(StrTestEntity entity) {
|
||||
this.entity = entity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
ManyToOneComponent that = (ManyToOneComponent) o;
|
||||
|
||||
if (data != null ? !data.equals(that.data) : that.data != null) return false;
|
||||
if (entity != null ? !entity.equals(that.entity) : that.entity != null) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = entity != null ? entity.hashCode() : 0;
|
||||
result = 31 * result + (data != null ? data.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "ManyToOneComponent(str1 = " + data + ")";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,97 @@
|
|||
/*
|
||||
* 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.entities.components.relations;
|
||||
|
||||
import javax.persistence.Embedded;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
|
||||
import org.hibernate.envers.Audited;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
@Entity
|
||||
public class ManyToOneComponentTestEntity {
|
||||
@Id
|
||||
@GeneratedValue
|
||||
private Integer id;
|
||||
|
||||
@Embedded
|
||||
@Audited
|
||||
private ManyToOneComponent comp1;
|
||||
|
||||
public ManyToOneComponentTestEntity() {
|
||||
}
|
||||
|
||||
public ManyToOneComponentTestEntity(Integer id, ManyToOneComponent comp1) {
|
||||
this.id = id;
|
||||
this.comp1 = comp1;
|
||||
}
|
||||
|
||||
public ManyToOneComponentTestEntity(ManyToOneComponent comp1) {
|
||||
this.comp1 = comp1;
|
||||
}
|
||||
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public ManyToOneComponent getComp1() {
|
||||
return comp1;
|
||||
}
|
||||
|
||||
public void setComp1(ManyToOneComponent comp1) {
|
||||
this.comp1 = comp1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
ManyToOneComponentTestEntity that = (ManyToOneComponentTestEntity) o;
|
||||
|
||||
if (comp1 != null ? !comp1.equals(that.comp1) : that.comp1 != null) return false;
|
||||
if (id != null ? !id.equals(that.id) : that.id != null) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = id != null ? id.hashCode() : 0;
|
||||
result = 31 * result + (comp1 != null ? comp1.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "MTOCTE(id = " + id + ", comp1 = " + comp1 + ")";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
* 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.entities.components.relations;
|
||||
|
||||
import org.hibernate.envers.test.entities.StrTestEntity;
|
||||
|
||||
import javax.persistence.OneToMany;
|
||||
import javax.persistence.Embeddable;
|
||||
import java.util.Set;
|
||||
import java.util.HashSet;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
@Embeddable
|
||||
public class OneToManyComponent {
|
||||
@OneToMany
|
||||
private Set<StrTestEntity> entities = new HashSet<StrTestEntity>();
|
||||
|
||||
private String data;
|
||||
|
||||
public OneToManyComponent(String data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public OneToManyComponent() {
|
||||
}
|
||||
|
||||
public String getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public void setData(String data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public Set<StrTestEntity> getEntities() {
|
||||
return entities;
|
||||
}
|
||||
|
||||
public void setEntities(Set<StrTestEntity> entities) {
|
||||
this.entities = entities;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
OneToManyComponent that = (OneToManyComponent) o;
|
||||
|
||||
if (data != null ? !data.equals(that.data) : that.data != null) return false;
|
||||
if (entities != null ? !entities.equals(that.entities) : that.entities != null) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = entities != null ? entities.hashCode() : 0;
|
||||
result = 31 * result + (data != null ? data.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "OneToManyComponent(data = " + data + ")";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,97 @@
|
|||
/*
|
||||
* 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.entities.components.relations;
|
||||
|
||||
import javax.persistence.Embedded;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
|
||||
import org.hibernate.envers.Audited;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
@Entity
|
||||
public class OneToManyComponentTestEntity {
|
||||
@Id
|
||||
@GeneratedValue
|
||||
private Integer id;
|
||||
|
||||
@Embedded
|
||||
@Audited
|
||||
private OneToManyComponent comp1;
|
||||
|
||||
public OneToManyComponentTestEntity() {
|
||||
}
|
||||
|
||||
public OneToManyComponentTestEntity(Integer id, OneToManyComponent comp1) {
|
||||
this.id = id;
|
||||
this.comp1 = comp1;
|
||||
}
|
||||
|
||||
public OneToManyComponentTestEntity(OneToManyComponent comp1) {
|
||||
this.comp1 = comp1;
|
||||
}
|
||||
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public OneToManyComponent getComp1() {
|
||||
return comp1;
|
||||
}
|
||||
|
||||
public void setComp1(OneToManyComponent comp1) {
|
||||
this.comp1 = comp1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
|
||||
OneToManyComponentTestEntity that = (OneToManyComponentTestEntity) o;
|
||||
|
||||
if (comp1 != null ? !comp1.equals(that.comp1) : that.comp1 != null) return false;
|
||||
if (id != null ? !id.equals(that.id) : that.id != null) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = id != null ? id.hashCode() : 0;
|
||||
result = 31 * result + (comp1 != null ? comp1.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "OTMCTE(id = " + id + ", comp1 = " + comp1 + ")";
|
||||
}
|
||||
}
|
|
@ -42,7 +42,7 @@ public class MixedAccessType extends AbstractEntityTest {
|
|||
cfg.addAnnotatedClass(MixedAccessTypeEntity.class);
|
||||
}
|
||||
|
||||
@BeforeClass(dependsOnMethods = "init")
|
||||
@Test
|
||||
public void initData() {
|
||||
EntityManager em = getEntityManager();
|
||||
em.getTransaction().begin();
|
||||
|
@ -57,12 +57,12 @@ public class MixedAccessType extends AbstractEntityTest {
|
|||
em.getTransaction().commit();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Test(dependsOnMethods = "initData")
|
||||
public void testRevisionsCounts() {
|
||||
assert Arrays.asList(1, 2).equals(getAuditReader().getRevisions(MixedAccessTypeEntity.class, id1));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Test(dependsOnMethods = "initData")
|
||||
public void testHistoryOfId1() {
|
||||
MixedAccessTypeEntity ver1 = new MixedAccessTypeEntity(id1, "data");
|
||||
MixedAccessTypeEntity ver2 = new MixedAccessTypeEntity(id1, "data2");
|
||||
|
|
|
@ -43,7 +43,7 @@ public class Simple extends AbstractEntityTest {
|
|||
cfg.addAnnotatedClass(IntTestEntity.class);
|
||||
}
|
||||
|
||||
@BeforeClass(dependsOnMethods = "init")
|
||||
@Test
|
||||
public void initData() {
|
||||
EntityManager em = getEntityManager();
|
||||
em.getTransaction().begin();
|
||||
|
@ -58,12 +58,12 @@ public class Simple extends AbstractEntityTest {
|
|||
em.getTransaction().commit();
|
||||
}
|
||||
|
||||
@Test
|
||||
@Test(dependsOnMethods = "initData")
|
||||
public void testRevisionsCounts() {
|
||||
assert Arrays.asList(1, 2).equals(getAuditReader().getRevisions(IntTestEntity.class, id1));
|
||||
}
|
||||
|
||||
@Test
|
||||
@Test(dependsOnMethods = "initData")
|
||||
public void testHistoryOfId1() {
|
||||
IntTestEntity ver1 = new IntTestEntity(10, id1);
|
||||
IntTestEntity ver2 = new IntTestEntity(20, id1);
|
||||
|
|
|
@ -0,0 +1,109 @@
|
|||
/*
|
||||
* 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.components.relations;
|
||||
|
||||
import java.util.Arrays;
|
||||
import javax.persistence.EntityManager;
|
||||
|
||||
import org.hibernate.envers.test.AbstractEntityTest;
|
||||
import org.hibernate.envers.test.entities.components.relations.ManyToOneComponentTestEntity;
|
||||
import org.hibernate.envers.test.entities.components.relations.ManyToOneComponent;
|
||||
import org.hibernate.envers.test.entities.StrTestEntity;
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import org.hibernate.ejb.Ejb3Configuration;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public class ManyToOneInComponent extends AbstractEntityTest {
|
||||
private Integer mtocte_id1;
|
||||
private Integer ste_id1;
|
||||
private Integer ste_id2;
|
||||
|
||||
public void configure(Ejb3Configuration cfg) {
|
||||
cfg.addAnnotatedClass(ManyToOneComponentTestEntity.class);
|
||||
cfg.addAnnotatedClass(StrTestEntity.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void initData() {
|
||||
// Revision 1
|
||||
EntityManager em = getEntityManager();
|
||||
em.getTransaction().begin();
|
||||
|
||||
StrTestEntity ste1 = new StrTestEntity();
|
||||
ste1.setStr("str1");
|
||||
|
||||
StrTestEntity ste2 = new StrTestEntity();
|
||||
ste2.setStr("str2");
|
||||
|
||||
em.persist(ste1);
|
||||
em.persist(ste2);
|
||||
|
||||
em.getTransaction().commit();
|
||||
|
||||
// Revision 2
|
||||
em = getEntityManager();
|
||||
em.getTransaction().begin();
|
||||
|
||||
ManyToOneComponentTestEntity mtocte1 = new ManyToOneComponentTestEntity(new ManyToOneComponent(ste1, "data1"));
|
||||
|
||||
em.persist(mtocte1);
|
||||
|
||||
em.getTransaction().commit();
|
||||
|
||||
// Revision 3
|
||||
em = getEntityManager();
|
||||
em.getTransaction().begin();
|
||||
|
||||
mtocte1 = em.find(ManyToOneComponentTestEntity.class, mtocte1.getId());
|
||||
mtocte1.getComp1().setEntity(ste2);
|
||||
|
||||
em.getTransaction().commit();
|
||||
|
||||
mtocte_id1 = mtocte1.getId();
|
||||
ste_id1 = ste1.getId();
|
||||
ste_id2 = ste2.getId();
|
||||
}
|
||||
|
||||
@Test(dependsOnMethods = "initData")
|
||||
public void testRevisionsCounts() {
|
||||
assert Arrays.asList(2, 3).equals(getAuditReader().getRevisions(ManyToOneComponentTestEntity.class, mtocte_id1));
|
||||
}
|
||||
|
||||
@Test(dependsOnMethods = "initData")
|
||||
public void testHistoryOfId1() {
|
||||
StrTestEntity ste1 = getEntityManager().find(StrTestEntity.class, ste_id1);
|
||||
StrTestEntity ste2 = getEntityManager().find(StrTestEntity.class, ste_id2);
|
||||
|
||||
ManyToOneComponentTestEntity ver2 = new ManyToOneComponentTestEntity(mtocte_id1, new ManyToOneComponent(ste1, "data1"));
|
||||
ManyToOneComponentTestEntity ver3 = new ManyToOneComponentTestEntity(mtocte_id1, new ManyToOneComponent(ste2, "data1"));
|
||||
|
||||
assert getAuditReader().find(ManyToOneComponentTestEntity.class, mtocte_id1, 1) == null;
|
||||
assert getAuditReader().find(ManyToOneComponentTestEntity.class, mtocte_id1, 2).equals(ver2);
|
||||
assert getAuditReader().find(ManyToOneComponentTestEntity.class, mtocte_id1, 3).equals(ver3);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,112 @@
|
|||
/*
|
||||
* 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.components.relations;
|
||||
|
||||
import java.util.Arrays;
|
||||
import javax.persistence.EntityManager;
|
||||
|
||||
import org.hibernate.envers.test.AbstractEntityTest;
|
||||
import org.hibernate.envers.test.entities.components.relations.OneToManyComponentTestEntity;
|
||||
import org.hibernate.envers.test.entities.components.relations.OneToManyComponent;
|
||||
import org.hibernate.envers.test.entities.StrTestEntity;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import org.hibernate.ejb.Ejb3Configuration;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public class OneToManyInComponent extends AbstractEntityTest {
|
||||
private Integer otmcte_id1;
|
||||
private Integer ste_id1;
|
||||
private Integer ste_id2;
|
||||
|
||||
public void configure(Ejb3Configuration cfg) {
|
||||
cfg.addAnnotatedClass(OneToManyComponentTestEntity.class);
|
||||
cfg.addAnnotatedClass(StrTestEntity.class);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void initData() {
|
||||
// Revision 1
|
||||
EntityManager em = getEntityManager();
|
||||
em.getTransaction().begin();
|
||||
|
||||
StrTestEntity ste1 = new StrTestEntity();
|
||||
ste1.setStr("str1");
|
||||
|
||||
StrTestEntity ste2 = new StrTestEntity();
|
||||
ste2.setStr("str2");
|
||||
|
||||
em.persist(ste1);
|
||||
em.persist(ste2);
|
||||
|
||||
em.getTransaction().commit();
|
||||
|
||||
// Revision 2
|
||||
em = getEntityManager();
|
||||
em.getTransaction().begin();
|
||||
|
||||
OneToManyComponentTestEntity otmcte1 = new OneToManyComponentTestEntity(new OneToManyComponent("data1"));
|
||||
otmcte1.getComp1().getEntities().add(ste1);
|
||||
|
||||
em.persist(otmcte1);
|
||||
|
||||
em.getTransaction().commit();
|
||||
|
||||
// Revision 3
|
||||
em = getEntityManager();
|
||||
em.getTransaction().begin();
|
||||
|
||||
otmcte1 = em.find(OneToManyComponentTestEntity.class, otmcte1.getId());
|
||||
otmcte1.getComp1().getEntities().add(ste2);
|
||||
|
||||
em.getTransaction().commit();
|
||||
|
||||
otmcte_id1 = otmcte1.getId();
|
||||
ste_id1 = ste1.getId();
|
||||
ste_id2 = ste2.getId();
|
||||
}
|
||||
|
||||
@Test(dependsOnMethods = "initData")
|
||||
public void testRevisionsCounts() {
|
||||
assert Arrays.asList(2, 3).equals(getAuditReader().getRevisions(OneToManyComponentTestEntity.class, otmcte_id1));
|
||||
}
|
||||
|
||||
@Test(dependsOnMethods = "initData")
|
||||
public void testHistoryOfId1() {
|
||||
StrTestEntity ste1 = getEntityManager().find(StrTestEntity.class, ste_id1);
|
||||
StrTestEntity ste2 = getEntityManager().find(StrTestEntity.class, ste_id2);
|
||||
|
||||
OneToManyComponentTestEntity ver2 = new OneToManyComponentTestEntity(otmcte_id1, new OneToManyComponent("data1"));
|
||||
ver2.getComp1().getEntities().add(ste1);
|
||||
OneToManyComponentTestEntity ver3 = new OneToManyComponentTestEntity(otmcte_id1, new OneToManyComponent("data1"));
|
||||
ver3.getComp1().getEntities().add(ste1);
|
||||
ver3.getComp1().getEntities().add(ste2);
|
||||
|
||||
assert getAuditReader().find(OneToManyComponentTestEntity.class, otmcte_id1, 1) == null;
|
||||
assert getAuditReader().find(OneToManyComponentTestEntity.class, otmcte_id1, 2).equals(ver2);
|
||||
assert getAuditReader().find(OneToManyComponentTestEntity.class, otmcte_id1, 3).equals(ver3);
|
||||
}
|
||||
}
|
|
@ -9,6 +9,7 @@
|
|||
<package name="org.hibernate.envers.test.integration.collection" />
|
||||
<package name="org.hibernate.envers.test.integration.collection.mapkey" />
|
||||
<package name="org.hibernate.envers.test.integration.components" />
|
||||
<package name="org.hibernate.envers.test.integration.components.relations" />
|
||||
<package name="org.hibernate.envers.test.integration.customtype" />
|
||||
<package name="org.hibernate.envers.test.integration.data" />
|
||||
<package name="org.hibernate.envers.test.integration.flush" />
|
||||
|
|
Loading…
Reference in New Issue