HHH-3565: adding support for field and property access types; changed the way properties are read. Now, instead of a sole property name, a special "PropertyData" object is passed around which encapsulates the property name and access type information.
git-svn-id: https://svn.jboss.org/repos/hibernate/core/trunk@15481 1b8cb986-b30d-0410-93ca-fae66ebed9b2
This commit is contained in:
parent
572f412482
commit
cc03033e59
|
@ -41,18 +41,18 @@ import org.hibernate.annotations.common.reflection.ReflectionManager;
|
|||
*/
|
||||
public class AuditConfiguration {
|
||||
private final GlobalConfiguration globalCfg;
|
||||
private final AuditEntitiesConfiguration verEntCfg;
|
||||
private final AuditSyncManager versionsSyncManager;
|
||||
private final AuditEntitiesConfiguration auditEntCfg;
|
||||
private final AuditSyncManager auditSyncManager;
|
||||
private final EntitiesConfigurations entCfg;
|
||||
private final RevisionInfoQueryCreator revisionInfoQueryCreator;
|
||||
private final RevisionInfoNumberReader revisionInfoNumberReader;
|
||||
|
||||
public AuditEntitiesConfiguration getVerEntCfg() {
|
||||
return verEntCfg;
|
||||
public AuditEntitiesConfiguration getAuditEntCfg() {
|
||||
return auditEntCfg;
|
||||
}
|
||||
|
||||
public AuditSyncManager getSyncManager() {
|
||||
return versionsSyncManager;
|
||||
return auditSyncManager;
|
||||
}
|
||||
|
||||
public GlobalConfiguration getGlobalCfg() {
|
||||
|
@ -78,12 +78,12 @@ public class AuditConfiguration {
|
|||
ReflectionManager reflectionManager = ((AnnotationConfiguration) cfg).getReflectionManager();
|
||||
RevisionInfoConfiguration revInfoCfg = new RevisionInfoConfiguration();
|
||||
RevisionInfoConfigurationResult revInfoCfgResult = revInfoCfg.configure(cfg, reflectionManager);
|
||||
verEntCfg = new AuditEntitiesConfiguration(properties, revInfoCfgResult.getRevisionInfoEntityName());
|
||||
auditEntCfg = new AuditEntitiesConfiguration(properties, revInfoCfgResult.getRevisionInfoEntityName());
|
||||
globalCfg = new GlobalConfiguration(properties);
|
||||
versionsSyncManager = new AuditSyncManager(revInfoCfgResult.getRevisionInfoGenerator());
|
||||
auditSyncManager = new AuditSyncManager(revInfoCfgResult.getRevisionInfoGenerator());
|
||||
revisionInfoQueryCreator = revInfoCfgResult.getRevisionInfoQueryCreator();
|
||||
revisionInfoNumberReader = revInfoCfgResult.getRevisionInfoNumberReader();
|
||||
entCfg = new EntitiesConfigurator().configure(cfg, reflectionManager, globalCfg, verEntCfg,
|
||||
entCfg = new EntitiesConfigurator().configure(cfg, reflectionManager, globalCfg, auditEntCfg,
|
||||
revInfoCfgResult.getRevisionInfoXmlMapping(), revInfoCfgResult.getRevisionInfoRelationMapping());
|
||||
}
|
||||
|
||||
|
|
|
@ -39,7 +39,7 @@ import org.dom4j.io.OutputFormat;
|
|||
import org.dom4j.io.XMLWriter;
|
||||
import org.hibernate.envers.configuration.metadata.AnnotationsMetadataReader;
|
||||
import org.hibernate.envers.configuration.metadata.EntityXmlMappingData;
|
||||
import org.hibernate.envers.configuration.metadata.PersistentClassVersioningData;
|
||||
import org.hibernate.envers.configuration.metadata.PersistentClassAuditingData;
|
||||
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, PersistentClassVersioningData> pcDatas =
|
||||
new HashMap<PersistentClass, PersistentClassVersioningData>();
|
||||
Map<PersistentClass, PersistentClassAuditingData> pcDatas =
|
||||
new HashMap<PersistentClass, PersistentClassAuditingData>();
|
||||
Map<PersistentClass, EntityXmlMappingData> xmlMappings = new HashMap<PersistentClass, EntityXmlMappingData>();
|
||||
|
||||
// First pass
|
||||
|
@ -74,23 +74,23 @@ public class EntitiesConfigurator {
|
|||
// Collecting information from annotations on the persistent class pc
|
||||
AnnotationsMetadataReader annotationsMetadataReader =
|
||||
new AnnotationsMetadataReader(globalCfg, reflectionManager, pc);
|
||||
PersistentClassVersioningData versioningData = annotationsMetadataReader.getVersioningData();
|
||||
PersistentClassAuditingData auditData = annotationsMetadataReader.getAuditData();
|
||||
|
||||
if (versioningData.isVersioned()) {
|
||||
pcDatas.put(pc, versioningData);
|
||||
if (auditData.isAudited()) {
|
||||
pcDatas.put(pc, auditData);
|
||||
|
||||
if (!StringTools.isEmpty(versioningData.versionsTable.value())) {
|
||||
verEntCfg.addCustomVersionsTableName(pc.getEntityName(), versioningData.versionsTable.value());
|
||||
if (!StringTools.isEmpty(auditData.getAuditTable().value())) {
|
||||
verEntCfg.addCustomVersionsTableName(pc.getEntityName(), auditData.getAuditTable().value());
|
||||
}
|
||||
|
||||
EntityXmlMappingData xmlMappingData = new EntityXmlMappingData();
|
||||
versionsMetaGen.generateFirstPass(pc, versioningData, xmlMappingData);
|
||||
versionsMetaGen.generateFirstPass(pc, auditData, xmlMappingData);
|
||||
xmlMappings.put(pc, xmlMappingData);
|
||||
}
|
||||
}
|
||||
|
||||
// Second pass
|
||||
for (Map.Entry<PersistentClass, PersistentClassVersioningData> pcDatasEntry : pcDatas.entrySet()) {
|
||||
for (Map.Entry<PersistentClass, PersistentClassAuditingData> pcDatasEntry : pcDatas.entrySet()) {
|
||||
EntityXmlMappingData xmlMappingData = xmlMappings.get(pcDatasEntry.getKey());
|
||||
|
||||
versionsMetaGen.generateSecondPass(pcDatasEntry.getKey(), pcDatasEntry.getValue(), xmlMappingData);
|
||||
|
|
|
@ -30,6 +30,7 @@ import org.dom4j.DocumentHelper;
|
|||
import org.dom4j.Element;
|
||||
import org.hibernate.envers.Audited;
|
||||
import org.hibernate.envers.*;
|
||||
import org.hibernate.envers.entities.PropertyData;
|
||||
import org.hibernate.envers.configuration.metadata.MetadataTools;
|
||||
import org.hibernate.envers.revisioninfo.DefaultRevisionInfoGenerator;
|
||||
import org.hibernate.envers.revisioninfo.RevisionInfoGenerator;
|
||||
|
@ -49,16 +50,16 @@ import org.hibernate.mapping.PersistentClass;
|
|||
*/
|
||||
public class RevisionInfoConfiguration {
|
||||
private String revisionInfoEntityName;
|
||||
private String revisionInfoIdName;
|
||||
private String revisionInfoTimestampName;
|
||||
private PropertyData revisionInfoIdData;
|
||||
private PropertyData revisionInfoTimestampData;
|
||||
private String revisionInfoTimestampType;
|
||||
|
||||
private String revisionPropType;
|
||||
|
||||
public RevisionInfoConfiguration() {
|
||||
revisionInfoEntityName = "org.hibernate.envers.DefaultRevisionEntity";
|
||||
revisionInfoIdName = "id";
|
||||
revisionInfoTimestampName = "timestamp";
|
||||
revisionInfoIdData = new PropertyData("id", "field", null);
|
||||
revisionInfoTimestampData = new PropertyData("timestamp", "field", null);
|
||||
revisionInfoTimestampType = "long";
|
||||
|
||||
revisionPropType = "integer";
|
||||
|
@ -72,11 +73,11 @@ public class RevisionInfoConfiguration {
|
|||
class_mapping.addAttribute("name", revisionInfoEntityName);
|
||||
class_mapping.addAttribute("table", "_revisions_info");
|
||||
|
||||
Element idProperty = MetadataTools.addNativelyGeneratedId(class_mapping, revisionInfoIdName,
|
||||
Element idProperty = MetadataTools.addNativelyGeneratedId(class_mapping, revisionInfoIdData.getName(),
|
||||
revisionPropType);
|
||||
MetadataTools.addColumn(idProperty, "revision_id", null);
|
||||
|
||||
Element timestampProperty = MetadataTools.addProperty(class_mapping, revisionInfoTimestampName,
|
||||
Element timestampProperty = MetadataTools.addProperty(class_mapping, revisionInfoTimestampData.getName(),
|
||||
revisionInfoTimestampType, true, false);
|
||||
MetadataTools.addColumn(timestampProperty, "revision_timestamp", null);
|
||||
|
||||
|
@ -107,11 +108,11 @@ public class RevisionInfoConfiguration {
|
|||
XClass revisionNumberClass = property.getType();
|
||||
if (reflectionManager.equals(revisionNumberClass, Integer.class) ||
|
||||
reflectionManager.equals(revisionNumberClass, Integer.TYPE)) {
|
||||
revisionInfoIdName = property.getName();
|
||||
revisionInfoIdData = new PropertyData(property.getName(), accessType, null);
|
||||
revisionNumberFound.set();
|
||||
} else if (reflectionManager.equals(revisionNumberClass, Long.class) ||
|
||||
reflectionManager.equals(revisionNumberClass, Long.TYPE)) {
|
||||
revisionInfoIdName = property.getName();
|
||||
revisionInfoIdData = new PropertyData(property.getName(), accessType, null);
|
||||
revisionNumberFound.set();
|
||||
|
||||
// The default is integer
|
||||
|
@ -130,7 +131,7 @@ public class RevisionInfoConfiguration {
|
|||
XClass revisionTimestampClass = property.getType();
|
||||
if (reflectionManager.equals(revisionTimestampClass, Long.class) ||
|
||||
reflectionManager.equals(revisionTimestampClass, Long.TYPE)) {
|
||||
revisionInfoTimestampName = property.getName();
|
||||
revisionInfoTimestampData = new PropertyData(property.getName(), accessType, null);
|
||||
revisionTimestampFound.set();
|
||||
} else {
|
||||
throw new MappingException("The field annotated with @RevisionTimestamp must be of type " +
|
||||
|
@ -178,7 +179,7 @@ public class RevisionInfoConfiguration {
|
|||
|
||||
// Checking if custom revision entity isn't versioned
|
||||
if (clazz.getAnnotation(Audited.class) != null) {
|
||||
throw new MappingException("An entity annotated with @RevisionEntity cannot be versioned!");
|
||||
throw new MappingException("An entity annotated with @RevisionEntity cannot be audited!");
|
||||
}
|
||||
|
||||
revisionEntityFound = true;
|
||||
|
@ -202,7 +203,7 @@ public class RevisionInfoConfiguration {
|
|||
|
||||
revisionInfoClass = pc.getMappedClass();
|
||||
revisionInfoGenerator = new DefaultRevisionInfoGenerator(revisionInfoEntityName, revisionInfoClass,
|
||||
revisionEntity.value(), revisionInfoTimestampName);
|
||||
revisionEntity.value(), revisionInfoTimestampData);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -212,15 +213,16 @@ public class RevisionInfoConfiguration {
|
|||
if (revisionInfoGenerator == null) {
|
||||
revisionInfoClass = DefaultRevisionEntity.class;
|
||||
revisionInfoGenerator = new DefaultRevisionInfoGenerator(revisionInfoEntityName, revisionInfoClass,
|
||||
RevisionListener.class, revisionInfoTimestampName);
|
||||
RevisionListener.class, revisionInfoTimestampData);
|
||||
revisionInfoXmlMapping = generateDefaultRevisionInfoXmlMapping();
|
||||
}
|
||||
|
||||
return new RevisionInfoConfigurationResult(
|
||||
revisionInfoGenerator, revisionInfoXmlMapping,
|
||||
new RevisionInfoQueryCreator(revisionInfoEntityName, revisionInfoIdName, revisionInfoTimestampName),
|
||||
new RevisionInfoQueryCreator(revisionInfoEntityName, revisionInfoIdData.getName(),
|
||||
revisionInfoTimestampData.getName()),
|
||||
generateRevisionInfoRelationMapping(),
|
||||
new RevisionInfoNumberReader(revisionInfoClass, revisionInfoIdName), revisionInfoEntityName);
|
||||
new RevisionInfoNumberReader(revisionInfoClass, revisionInfoIdData), revisionInfoEntityName);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -24,11 +24,15 @@
|
|||
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.tools.Tools;
|
||||
import org.hibernate.envers.configuration.GlobalConfiguration;
|
||||
|
||||
import org.hibernate.MappingException;
|
||||
|
@ -36,6 +40,7 @@ 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;
|
||||
|
||||
/**
|
||||
* A helper class to read versioning meta-data from annotations on a persistent class.
|
||||
|
@ -51,7 +56,16 @@ public final class AnnotationsMetadataReader {
|
|||
* This object is filled with information read from annotations and returned by the <code>getVersioningData</code>
|
||||
* method.
|
||||
*/
|
||||
private final PersistentClassVersioningData versioningData;
|
||||
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) {
|
||||
|
@ -59,54 +73,88 @@ public final class AnnotationsMetadataReader {
|
|||
this.reflectionManager = reflectionManager;
|
||||
this.pc = pc;
|
||||
|
||||
versioningData = new PersistentClassVersioningData();
|
||||
auditData = new PersistentClassAuditingData();
|
||||
|
||||
propertyPersistentProperties = Tools.newHashSet();
|
||||
fieldPersistentProperties = Tools.newHashSet();
|
||||
}
|
||||
|
||||
private void addPropertyVersioned(XProperty property) {
|
||||
Audited ver = property.getAnnotation(Audited.class);
|
||||
if (ver != null) {
|
||||
versioningData.propertyStoreInfo.propertyStores.put(property.getName(), ver.modStore());
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
|
||||
private void addPropertyMapKey(XProperty property) {
|
||||
MapKey mapKey = property.getAnnotation(MapKey.class);
|
||||
if (mapKey != null) {
|
||||
versioningData.mapKeys.put(property.getName(), mapKey.name());
|
||||
}
|
||||
}
|
||||
|
||||
private void addPropertyUnversioned(XProperty property) {
|
||||
// check if a property is declared as unversioned to exclude it
|
||||
// useful if a class is versioned but some properties should be excluded
|
||||
// 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) {
|
||||
versioningData.unversionedProperties.add(property.getName());
|
||||
return false;
|
||||
} else {
|
||||
// if the optimistic locking field has to be unversioned and the current property
|
||||
// is the optimistic locking field, add it to the unversioned properties list
|
||||
// is the optimistic locking field, don't audit it
|
||||
if (globalCfg.isUnversionedOptimisticLockingField()) {
|
||||
Version jpaVer = property.getAnnotation(Version.class);
|
||||
if (jpaVer != null) {
|
||||
versioningData.unversionedProperties.add(property.getName());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Checking if this property is explicitly audited or if all properties are.
|
||||
Audited ver = property.getAnnotation(Audited.class);
|
||||
if (ver != null) {
|
||||
propertyData.setStore(ver.modStore());
|
||||
return true;
|
||||
} else {
|
||||
if (defaultStore != null) {
|
||||
propertyData.setStore(defaultStore);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void addPropertyJoinTables(XProperty property) {
|
||||
AuditJoinTable joinTable = property.getAnnotation(AuditJoinTable.class);
|
||||
if (joinTable != null) {
|
||||
versioningData.versionsJoinTables.put(property.getName(), joinTable);
|
||||
private void addPropertyMapKey(XProperty property, PersistentPropertyAuditingData propertyData) {
|
||||
MapKey mapKey = property.getAnnotation(MapKey.class);
|
||||
if (mapKey != null) {
|
||||
propertyData.setMapKey(mapKey.name());
|
||||
}
|
||||
}
|
||||
|
||||
private void addFromProperties(Iterable<XProperty> properties) {
|
||||
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) {
|
||||
addPropertyVersioned(property);
|
||||
addPropertyUnversioned(property);
|
||||
addPropertyJoinTables(property);
|
||||
addPropertyMapKey(property);
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -116,24 +164,36 @@ public final class AnnotationsMetadataReader {
|
|||
addPropertiesFromClass(superclazz);
|
||||
}
|
||||
|
||||
addFromProperties(clazz.getDeclaredProperties("field"));
|
||||
addFromProperties(clazz.getDeclaredProperties("property"));
|
||||
addFromProperties(clazz.getDeclaredProperties("field"), "field", fieldPersistentProperties);
|
||||
addFromProperties(clazz.getDeclaredProperties("property"), "property", propertyPersistentProperties);
|
||||
}
|
||||
|
||||
private void addDefaultVersioned(XClass clazz) {
|
||||
Audited defaultVersioned = clazz.getAnnotation(Audited.class);
|
||||
private void readDefaultAudited(XClass clazz) {
|
||||
Audited defaultAudited = clazz.getAnnotation(Audited.class);
|
||||
|
||||
if (defaultVersioned != null) {
|
||||
versioningData.propertyStoreInfo.defaultStore = defaultVersioned.modStore();
|
||||
if (defaultAudited != null) {
|
||||
defaultStore = defaultAudited.modStore();
|
||||
}
|
||||
}
|
||||
|
||||
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 addVersionsTable(XClass clazz) {
|
||||
AuditTable versionsTable = clazz.getAnnotation(AuditTable.class);
|
||||
if (versionsTable != null) {
|
||||
versioningData.versionsTable = versionsTable;
|
||||
AuditTable auditTable = clazz.getAnnotation(AuditTable.class);
|
||||
if (auditTable != null) {
|
||||
auditData.setAuditTable(auditTable);
|
||||
} else {
|
||||
versioningData.versionsTable = getDefaultVersionsTable();
|
||||
auditData.setAuditTable(getDefaultAuditTable());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -141,28 +201,30 @@ public final class AnnotationsMetadataReader {
|
|||
// Getting information on secondary tables
|
||||
SecondaryAuditTable secondaryVersionsTable1 = clazz.getAnnotation(SecondaryAuditTable.class);
|
||||
if (secondaryVersionsTable1 != null) {
|
||||
versioningData.secondaryTableDictionary.put(secondaryVersionsTable1.secondaryTableName(),
|
||||
auditData.getSecondaryTableDictionary().put(secondaryVersionsTable1.secondaryTableName(),
|
||||
secondaryVersionsTable1.secondaryVersionsTableName());
|
||||
}
|
||||
|
||||
SecondaryAuditTables secondaryVersionsTables = clazz.getAnnotation(SecondaryAuditTables.class);
|
||||
if (secondaryVersionsTables != null) {
|
||||
for (SecondaryAuditTable secondaryVersionsTable2 : secondaryVersionsTables.value()) {
|
||||
versioningData.secondaryTableDictionary.put(secondaryVersionsTable2.secondaryTableName(),
|
||||
auditData.getSecondaryTableDictionary().put(secondaryVersionsTable2.secondaryTableName(),
|
||||
secondaryVersionsTable2.secondaryVersionsTableName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public PersistentClassVersioningData getVersioningData() {
|
||||
public PersistentClassAuditingData getAuditData() {
|
||||
if (pc.getClassName() == null) {
|
||||
return versioningData;
|
||||
return auditData;
|
||||
}
|
||||
|
||||
readPersistentProperties();
|
||||
|
||||
try {
|
||||
XClass clazz = reflectionManager.classForName(pc.getClassName(), this.getClass());
|
||||
|
||||
addDefaultVersioned(clazz);
|
||||
readDefaultAudited(clazz);
|
||||
addPropertiesFromClass(clazz);
|
||||
addVersionsTable(clazz);
|
||||
addVersionsSecondaryTables(clazz);
|
||||
|
@ -170,15 +232,35 @@ public final class AnnotationsMetadataReader {
|
|||
throw new MappingException(e);
|
||||
}
|
||||
|
||||
return versioningData;
|
||||
return auditData;
|
||||
}
|
||||
|
||||
private AuditTable getDefaultVersionsTable() {
|
||||
return new AuditTable() {
|
||||
public String value() { return ""; }
|
||||
public String schema() { return ""; }
|
||||
public String catalog() { return ""; }
|
||||
public Class<? extends Annotation> annotationType() { return this.getClass(); }
|
||||
};
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,12 +25,9 @@ package org.hibernate.envers.configuration.metadata;
|
|||
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.dom4j.Element;
|
||||
import org.hibernate.envers.ModificationStore;
|
||||
import org.hibernate.envers.AuditJoinTable;
|
||||
import org.hibernate.envers.configuration.GlobalConfiguration;
|
||||
import org.hibernate.envers.configuration.AuditEntitiesConfiguration;
|
||||
import org.hibernate.envers.entities.EntityConfiguration;
|
||||
|
@ -77,8 +74,8 @@ public final class AuditMetadataGenerator {
|
|||
private Logger log = LoggerFactory.getLogger(AuditMetadataGenerator.class);
|
||||
|
||||
public AuditMetadataGenerator(Configuration cfg, GlobalConfiguration globalCfg,
|
||||
AuditEntitiesConfiguration verEntCfg,
|
||||
Element revisionInfoRelationMapping) {
|
||||
AuditEntitiesConfiguration verEntCfg,
|
||||
Element revisionInfoRelationMapping) {
|
||||
this.cfg = cfg;
|
||||
this.globalCfg = globalCfg;
|
||||
this.verEntCfg = verEntCfg;
|
||||
|
@ -106,38 +103,16 @@ public final class AuditMetadataGenerator {
|
|||
revTypeProperty.addAttribute("type", "org.hibernate.envers.entities.RevisionTypeType");
|
||||
}
|
||||
|
||||
private ModificationStore getStoreForProperty(Property property, PropertyStoreInfo propertyStoreInfo,
|
||||
List<String> unversionedProperties) {
|
||||
/*
|
||||
* Checks if a property is versioned, which is when:
|
||||
* - the property isn't unversioned
|
||||
* - the whole entity is versioned, then the default store is not null
|
||||
* - there is a store defined for this entity, which is when this property is annotated
|
||||
*/
|
||||
|
||||
if (unversionedProperties.contains(property.getName())) {
|
||||
return null;
|
||||
}
|
||||
|
||||
ModificationStore store = propertyStoreInfo.propertyStores.get(property.getName());
|
||||
|
||||
if (store == null) {
|
||||
return propertyStoreInfo.defaultStore;
|
||||
}
|
||||
|
||||
return store;
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
void addValue(Element parent, String name, Value value, CompositeMapperBuilder currentMapper,
|
||||
ModificationStore store, String entityName, EntityXmlMappingData xmlMappingData,
|
||||
AuditJoinTable joinTable, String mapKey, boolean insertable, boolean firstPass) {
|
||||
void addValue(Element parent, Value value, CompositeMapperBuilder currentMapper, String entityName,
|
||||
EntityXmlMappingData xmlMappingData, PersistentPropertyAuditingData persistentPropertyAuditingData,
|
||||
boolean insertable, boolean firstPass) {
|
||||
Type type = value.getType();
|
||||
|
||||
// only first pass
|
||||
if (firstPass) {
|
||||
if (basicMetadataGenerator.addBasic(parent, name, value, currentMapper, store, entityName, insertable,
|
||||
false)) {
|
||||
if (basicMetadataGenerator.addBasic(parent, persistentPropertyAuditingData, value, currentMapper,
|
||||
entityName, insertable, false)) {
|
||||
// The property was mapped by the basic generator.
|
||||
return;
|
||||
}
|
||||
|
@ -146,50 +121,49 @@ public final class AuditMetadataGenerator {
|
|||
if (type instanceof ManyToOneType) {
|
||||
// only second pass
|
||||
if (!firstPass) {
|
||||
toOneRelationMetadataGenerator.addToOne(parent, name, value, currentMapper, entityName);
|
||||
toOneRelationMetadataGenerator.addToOne(parent, persistentPropertyAuditingData, value, currentMapper,
|
||||
entityName);
|
||||
}
|
||||
} else if (type instanceof OneToOneType) {
|
||||
// only second pass
|
||||
if (!firstPass) {
|
||||
toOneRelationMetadataGenerator.addOneToOneNotOwning(name, value, currentMapper, entityName);
|
||||
toOneRelationMetadataGenerator.addOneToOneNotOwning(persistentPropertyAuditingData, value,
|
||||
currentMapper, entityName);
|
||||
}
|
||||
} else if (type instanceof CollectionType) {
|
||||
// only second pass
|
||||
if (!firstPass) {
|
||||
CollectionMetadataGenerator collectionMetadataGenerator = new CollectionMetadataGenerator(this,
|
||||
name, (Collection) value, currentMapper, entityName, xmlMappingData, joinTable, mapKey);
|
||||
(Collection) value, currentMapper, entityName, xmlMappingData,
|
||||
persistentPropertyAuditingData);
|
||||
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, name);
|
||||
throwUnsupportedTypeException(type, entityName, persistentPropertyAuditingData.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
private void addProperties(Element parent, Iterator<Property> properties, CompositeMapperBuilder currentMapper,
|
||||
PersistentClassVersioningData versioningData, String entityName, EntityXmlMappingData xmlMappingData,
|
||||
PersistentClassAuditingData versioningData, String entityName, EntityXmlMappingData xmlMappingData,
|
||||
boolean firstPass) {
|
||||
while (properties.hasNext()) {
|
||||
Property property = properties.next();
|
||||
if (!"_identifierMapper".equals(property.getName())) {
|
||||
ModificationStore store = getStoreForProperty(property, versioningData.propertyStoreInfo,
|
||||
versioningData.unversionedProperties);
|
||||
|
||||
if (store != null) {
|
||||
addValue(parent, property.getName(), property.getValue(), currentMapper, store, entityName,
|
||||
xmlMappingData, versioningData.versionsJoinTables.get(property.getName()),
|
||||
versioningData.mapKeys.get(property.getName()), property.isInsertable(), firstPass);
|
||||
}
|
||||
String propertyName = property.getName();
|
||||
if (versioningData.getPropertyAuditingData(propertyName) != null) {
|
||||
addValue(parent, property.getValue(), currentMapper, entityName,
|
||||
xmlMappingData, versioningData.getPropertyAuditingData(propertyName),
|
||||
property.isInsertable(), firstPass);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
private void createJoins(PersistentClass pc, Element parent, PersistentClassVersioningData versioningData) {
|
||||
private void createJoins(PersistentClass pc, Element parent, PersistentClassAuditingData versioningData) {
|
||||
Iterator<Join> joins = pc.getJoinIterator();
|
||||
|
||||
Map<Join, Element> joinElements = new HashMap<Join, Element>();
|
||||
|
@ -201,17 +175,17 @@ public final class AuditMetadataGenerator {
|
|||
// Determining the table name. If there is no entry in the dictionary, just constructing the table name
|
||||
// as if it was an entity (by appending/prepending configured strings).
|
||||
String originalTableName = join.getTable().getName();
|
||||
String versionedTableName = versioningData.secondaryTableDictionary.get(originalTableName);
|
||||
String versionedTableName = versioningData.getSecondaryTableDictionary().get(originalTableName);
|
||||
if (versionedTableName == null) {
|
||||
versionedTableName = verEntCfg.getVersionsEntityName(originalTableName);
|
||||
}
|
||||
|
||||
String schema = versioningData.versionsTable.schema();
|
||||
String schema = versioningData.getAuditTable().schema();
|
||||
if (StringTools.isEmpty(schema)) {
|
||||
schema = join.getTable().getSchema();
|
||||
}
|
||||
|
||||
String catalog = versioningData.versionsTable.catalog();
|
||||
String catalog = versioningData.getAuditTable().catalog();
|
||||
if (StringTools.isEmpty(catalog)) {
|
||||
catalog = join.getTable().getCatalog();
|
||||
}
|
||||
|
@ -226,7 +200,7 @@ public final class AuditMetadataGenerator {
|
|||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
private void addJoins(PersistentClass pc, CompositeMapperBuilder currentMapper, PersistentClassVersioningData versioningData,
|
||||
private void addJoins(PersistentClass pc, CompositeMapperBuilder currentMapper, PersistentClassAuditingData versioningData,
|
||||
String entityName, EntityXmlMappingData xmlMappingData,boolean firstPass) {
|
||||
Iterator<Join> joins = pc.getJoinIterator();
|
||||
|
||||
|
@ -240,14 +214,14 @@ public final class AuditMetadataGenerator {
|
|||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
public void generateFirstPass(PersistentClass pc, PersistentClassVersioningData versioningData,
|
||||
public void generateFirstPass(PersistentClass pc, PersistentClassAuditingData versioningData,
|
||||
EntityXmlMappingData xmlMappingData) {
|
||||
String schema = versioningData.versionsTable.schema();
|
||||
String schema = versioningData.getAuditTable().schema();
|
||||
if (StringTools.isEmpty(schema)) {
|
||||
schema = pc.getTable().getSchema();
|
||||
}
|
||||
|
||||
String catalog = versioningData.versionsTable.catalog();
|
||||
String catalog = versioningData.getAuditTable().catalog();
|
||||
if (StringTools.isEmpty(catalog)) {
|
||||
catalog = pc.getTable().getCatalog();
|
||||
}
|
||||
|
@ -322,7 +296,7 @@ public final class AuditMetadataGenerator {
|
|||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
public void generateSecondPass(PersistentClass pc, PersistentClassVersioningData versioningData,
|
||||
public void generateSecondPass(PersistentClass pc, PersistentClassAuditingData versioningData,
|
||||
EntityXmlMappingData xmlMappingData) {
|
||||
String entityName = pc.getEntityName();
|
||||
|
||||
|
|
|
@ -49,28 +49,28 @@ import org.hibernate.util.StringHelper;
|
|||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public final class BasicMetadataGenerator {
|
||||
boolean addBasic(Element parent, String name, Value value, CompositeMapperBuilder mapper,
|
||||
ModificationStore store, String entityName, boolean insertable, boolean key) {
|
||||
boolean addBasic(Element parent, PersistentPropertyAuditingData persistentPropertyAuditingData, Value value,
|
||||
CompositeMapperBuilder mapper, String entityName, boolean insertable, boolean key) {
|
||||
Type type = value.getType();
|
||||
|
||||
if (type instanceof ComponentType) {
|
||||
addComponent(parent, name, value, mapper, entityName, key);
|
||||
addComponent(parent, persistentPropertyAuditingData, value, mapper, entityName, key);
|
||||
return true;
|
||||
} else {
|
||||
return addBasicNoComponent(parent, name, value, mapper, store, insertable, key);
|
||||
return addBasicNoComponent(parent, persistentPropertyAuditingData, value, mapper, insertable, key);
|
||||
}
|
||||
}
|
||||
|
||||
boolean addBasicNoComponent(Element parent, String name, Value value, SimpleMapperBuilder mapper,
|
||||
ModificationStore store, boolean insertable, boolean key) {
|
||||
boolean addBasicNoComponent(Element parent, PersistentPropertyAuditingData persistentPropertyAuditingData,
|
||||
Value value, SimpleMapperBuilder mapper, boolean insertable, boolean key) {
|
||||
Type type = value.getType();
|
||||
|
||||
if (type instanceof ImmutableType || type instanceof MutableType) {
|
||||
addSimpleValue(parent, name, value, mapper, store, insertable, key);
|
||||
addSimpleValue(parent, persistentPropertyAuditingData, value, mapper, insertable, key);
|
||||
} else if (type instanceof CustomType || type instanceof CompositeCustomType) {
|
||||
addCustomValue(parent, name, value, mapper, store, insertable, key);
|
||||
addCustomValue(parent, persistentPropertyAuditingData, value, mapper, insertable, key);
|
||||
} else if ("org.hibernate.type.PrimitiveByteArrayBlobType".equals(type.getClass().getName())) {
|
||||
addSimpleValue(parent, name, value, mapper, store, insertable, key);
|
||||
addSimpleValue(parent, persistentPropertyAuditingData, value, mapper, insertable, key);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
@ -79,25 +79,25 @@ public final class BasicMetadataGenerator {
|
|||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
private void addSimpleValue(Element parent, String name, Value value, SimpleMapperBuilder mapper,
|
||||
ModificationStore store, boolean insertable, boolean key) {
|
||||
private void addSimpleValue(Element parent, PersistentPropertyAuditingData persistentPropertyAuditingData,
|
||||
Value value, SimpleMapperBuilder mapper, boolean insertable, boolean key) {
|
||||
if (parent != null) {
|
||||
Element prop_mapping = MetadataTools.addProperty(parent, name,
|
||||
Element prop_mapping = MetadataTools.addProperty(parent, persistentPropertyAuditingData.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(name, store);
|
||||
mapper.add(persistentPropertyAuditingData.getPropertyData());
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
private void addCustomValue(Element parent, String name, Value value, SimpleMapperBuilder mapper,
|
||||
ModificationStore store, boolean insertable, boolean key) {
|
||||
private void addCustomValue(Element parent, PersistentPropertyAuditingData persistentPropertyAuditingData,
|
||||
Value value, SimpleMapperBuilder mapper, boolean insertable, boolean key) {
|
||||
if (parent != null) {
|
||||
Element prop_mapping = MetadataTools.addProperty(parent, name,
|
||||
Element prop_mapping = MetadataTools.addProperty(parent, persistentPropertyAuditingData.getName(),
|
||||
null, insertable, key);
|
||||
|
||||
//CustomType propertyType = (CustomType) value.getType();
|
||||
|
@ -120,7 +120,7 @@ public final class BasicMetadataGenerator {
|
|||
}
|
||||
|
||||
if (mapper != null) {
|
||||
mapper.add(name, store);
|
||||
mapper.add(persistentPropertyAuditingData.getPropertyData());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -131,8 +131,8 @@ public final class BasicMetadataGenerator {
|
|||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
private void addComponent(Element parent, String name, Value value, CompositeMapperBuilder mapper,
|
||||
String entityName, boolean key) {
|
||||
private void addComponent(Element parent, PersistentPropertyAuditingData persistentPropertyAuditingData,
|
||||
Value value, CompositeMapperBuilder mapper, String entityName, boolean key) {
|
||||
Element component_mapping = null;
|
||||
Component prop_component = (Component) value;
|
||||
|
||||
|
@ -157,18 +157,19 @@ public final class BasicMetadataGenerator {
|
|||
*/
|
||||
|
||||
component_mapping = parent.addElement("component");
|
||||
component_mapping.addAttribute("name", name);
|
||||
component_mapping.addAttribute("name", persistentPropertyAuditingData.getName());
|
||||
|
||||
addComponentClassName(component_mapping, prop_component);
|
||||
}
|
||||
|
||||
CompositeMapperBuilder componentMapper = mapper.addComposite(name);
|
||||
CompositeMapperBuilder componentMapper = mapper.addComposite(persistentPropertyAuditingData.getPropertyData());
|
||||
|
||||
Iterator<Property> properties = (Iterator<Property>) prop_component.getPropertyIterator();
|
||||
while (properties.hasNext()) {
|
||||
Property property = properties.next();
|
||||
addBasic(component_mapping, property.getName(), property.getValue(), componentMapper,
|
||||
ModificationStore.FULL, entityName, property.isInsertable(), key);
|
||||
addBasic(component_mapping,
|
||||
new PersistentPropertyAuditingData(property.getName(), property.getPropertyAccessorName(), ModificationStore.FULL),
|
||||
property.getValue(), componentMapper, entityName, property.isInsertable(), key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,7 +23,6 @@
|
|||
*/
|
||||
package org.hibernate.envers.configuration.metadata;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
|
@ -37,7 +36,6 @@ import javax.persistence.JoinColumn;
|
|||
|
||||
import org.dom4j.Element;
|
||||
import org.hibernate.envers.ModificationStore;
|
||||
import org.hibernate.envers.AuditJoinTable;
|
||||
import org.hibernate.envers.entities.EntityConfiguration;
|
||||
import org.hibernate.envers.entities.IdMappingData;
|
||||
import org.hibernate.envers.entities.mapper.CompositeMapperBuilder;
|
||||
|
@ -91,8 +89,7 @@ public final class CollectionMetadataGenerator {
|
|||
private final CompositeMapperBuilder currentMapper;
|
||||
private final String referencingEntityName;
|
||||
private final EntityXmlMappingData xmlMappingData;
|
||||
private final AuditJoinTable joinTable;
|
||||
private final String mapKey;
|
||||
private final PersistentPropertyAuditingData persistentPropertyAuditingData;
|
||||
|
||||
private final EntityConfiguration referencingEntityConfiguration;
|
||||
/**
|
||||
|
@ -102,29 +99,28 @@ public final class CollectionMetadataGenerator {
|
|||
|
||||
/**
|
||||
* @param mainGenerator Main generator, giving access to configuration and the basic mapper.
|
||||
* @param propertyName Name of the property that references the collection in the referencing entity.
|
||||
* @param propertyValue Value of the collection, as mapped by Hibernate.
|
||||
* @param currentMapper Mapper, to which the appropriate {@link org.hibernate.envers.entities.mapper.PropertyMapper}
|
||||
* will be added.
|
||||
* @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 joinTable User data for the middle (join) table. <code>null</code> if the user didn't specify it.
|
||||
* @param mapKey The value of the name() property of the MapKey annotation on this property. Null, if this
|
||||
* property isn't annotated with this annotation.
|
||||
* @param persistentPropertyAuditingData 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, String propertyName,
|
||||
public CollectionMetadataGenerator(AuditMetadataGenerator mainGenerator,
|
||||
Collection propertyValue, CompositeMapperBuilder currentMapper,
|
||||
String referencingEntityName, EntityXmlMappingData xmlMappingData,
|
||||
AuditJoinTable joinTable, String mapKey) {
|
||||
PersistentPropertyAuditingData persistentPropertyAuditingData) {
|
||||
this.mainGenerator = mainGenerator;
|
||||
this.propertyName = propertyName;
|
||||
this.propertyValue = propertyValue;
|
||||
this.currentMapper = currentMapper;
|
||||
this.referencingEntityName = referencingEntityName;
|
||||
this.xmlMappingData = xmlMappingData;
|
||||
this.joinTable = joinTable == null ? getDefaultVersionsJoinTable() : joinTable;
|
||||
this.mapKey = mapKey;
|
||||
this.persistentPropertyAuditingData = persistentPropertyAuditingData;
|
||||
|
||||
this.propertyName = persistentPropertyAuditingData.getName();
|
||||
|
||||
referencingEntityConfiguration = mainGenerator.getEntitiesConfigurations().get(referencingEntityName);
|
||||
if (referencingEntityConfiguration == null) {
|
||||
|
@ -192,7 +188,8 @@ public final class CollectionMetadataGenerator {
|
|||
|
||||
// Creating common mapper data.
|
||||
CommonCollectionMapperData commonCollectionMapperData = new CommonCollectionMapperData(
|
||||
mainGenerator.getVerEntCfg(), referencedEntityName, propertyName,
|
||||
mainGenerator.getVerEntCfg(), referencedEntityName,
|
||||
persistentPropertyAuditingData.getPropertyData(),
|
||||
referencingIdData, queryGenerator);
|
||||
|
||||
// Checking the type of the collection and adding an appropriate mapper.
|
||||
|
@ -238,9 +235,9 @@ public final class CollectionMetadataGenerator {
|
|||
// Generating the name of the middle table
|
||||
String versionsMiddleTableName;
|
||||
String versionsMiddleEntityName;
|
||||
if (!StringTools.isEmpty(joinTable.name())) {
|
||||
versionsMiddleTableName = joinTable.name();
|
||||
versionsMiddleEntityName = joinTable.name();
|
||||
if (!StringTools.isEmpty(persistentPropertyAuditingData.getJoinTable().name())) {
|
||||
versionsMiddleTableName = persistentPropertyAuditingData.getJoinTable().name();
|
||||
versionsMiddleEntityName = persistentPropertyAuditingData.getJoinTable().name();
|
||||
} else {
|
||||
String middleTableName = getMiddleTableName(propertyValue, referencingEntityName);
|
||||
versionsMiddleTableName = mainGenerator.getVerEntCfg().getVersionsTableName(null, middleTableName);
|
||||
|
@ -304,7 +301,7 @@ public final class CollectionMetadataGenerator {
|
|||
// Generating the element mapping.
|
||||
// ******
|
||||
MiddleComponentData elementComponentData = addValueToMiddleTable(propertyValue.getElement(), middleEntityXml,
|
||||
queryGeneratorBuilder, referencedPrefix, joinTable.inverseJoinColumns());
|
||||
queryGeneratorBuilder, referencedPrefix, persistentPropertyAuditingData.getJoinTable().inverseJoinColumns());
|
||||
|
||||
// ******
|
||||
// Generating the index mapping, if an index exists.
|
||||
|
@ -319,7 +316,9 @@ public final class CollectionMetadataGenerator {
|
|||
|
||||
// Creating common data
|
||||
CommonCollectionMapperData commonCollectionMapperData = new CommonCollectionMapperData(
|
||||
mainGenerator.getVerEntCfg(), versionsMiddleEntityName, propertyName, referencingIdData, queryGenerator);
|
||||
mainGenerator.getVerEntCfg(), versionsMiddleEntityName,
|
||||
persistentPropertyAuditingData.getPropertyData(),
|
||||
referencingIdData, queryGenerator);
|
||||
|
||||
// Checking the type of the collection and adding an appropriate mapper.
|
||||
addMapper(commonCollectionMapperData, elementComponentData, indexComponentData);
|
||||
|
@ -333,6 +332,7 @@ public final class CollectionMetadataGenerator {
|
|||
private MiddleComponentData addIndex(Element middleEntityXml, QueryGeneratorBuilder queryGeneratorBuilder) {
|
||||
if (propertyValue instanceof IndexedCollection) {
|
||||
IndexedCollection indexedValue = (IndexedCollection) propertyValue;
|
||||
String mapKey = persistentPropertyAuditingData.getMapKey();
|
||||
if (mapKey == null) {
|
||||
// This entity doesn't specify a javax.persistence.MapKey. Mapping it to the middle entity.
|
||||
return addValueToMiddleTable(indexedValue.getIndex(), middleEntityXml,
|
||||
|
@ -347,7 +347,8 @@ public final class CollectionMetadataGenerator {
|
|||
referencedIdMapping.getIdMapper()), currentIndex);
|
||||
} else {
|
||||
// The key of the map is a property of the entity.
|
||||
return new MiddleComponentData(new MiddleMapKeyPropertyComponentMapper(mapKey), currentIndex);
|
||||
return new MiddleComponentData(new MiddleMapKeyPropertyComponentMapper(mapKey,
|
||||
persistentPropertyAuditingData.getAccessType()), currentIndex);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -399,8 +400,9 @@ public final class CollectionMetadataGenerator {
|
|||
queryGeneratorBuilder.getCurrentIndex());
|
||||
} else {
|
||||
// Last but one parameter: collection components are always insertable
|
||||
boolean mapped = mainGenerator.getBasicMetadataGenerator().addBasicNoComponent(xmlMapping, prefix, value, null,
|
||||
ModificationStore.FULL, true, true);
|
||||
boolean mapped = mainGenerator.getBasicMetadataGenerator().addBasicNoComponent(xmlMapping,
|
||||
new PersistentPropertyAuditingData(prefix, "field", ModificationStore.FULL), value, null,
|
||||
true, true);
|
||||
|
||||
if (mapped) {
|
||||
// Simple values are always stored in the first item of the array returned by the query generator.
|
||||
|
@ -417,25 +419,31 @@ public final class CollectionMetadataGenerator {
|
|||
MiddleComponentData indexComponentData) {
|
||||
Type type = propertyValue.getType();
|
||||
if (type instanceof SortedSetType) {
|
||||
currentMapper.addComposite(propertyName, new BasicCollectionMapper<Set>(commonCollectionMapperData,
|
||||
currentMapper.addComposite(persistentPropertyAuditingData.getPropertyData(),
|
||||
new BasicCollectionMapper<Set>(commonCollectionMapperData,
|
||||
TreeSet.class, SortedSetProxy.class, elementComponentData));
|
||||
} else if (type instanceof SetType) {
|
||||
currentMapper.addComposite(propertyName, new BasicCollectionMapper<Set>(commonCollectionMapperData,
|
||||
currentMapper.addComposite(persistentPropertyAuditingData.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(propertyName, new MapCollectionMapper<Map>(commonCollectionMapperData,
|
||||
currentMapper.addComposite(persistentPropertyAuditingData.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(propertyName, new MapCollectionMapper<Map>(commonCollectionMapperData,
|
||||
currentMapper.addComposite(persistentPropertyAuditingData.getPropertyData(),
|
||||
new MapCollectionMapper<Map>(commonCollectionMapperData,
|
||||
HashMap.class, MapProxy.class, elementComponentData, indexComponentData));
|
||||
} else if (type instanceof BagType) {
|
||||
currentMapper.addComposite(propertyName, new BasicCollectionMapper<List>(commonCollectionMapperData,
|
||||
currentMapper.addComposite(persistentPropertyAuditingData.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(propertyName, new ListCollectionMapper(commonCollectionMapperData,
|
||||
currentMapper.addComposite(persistentPropertyAuditingData.getPropertyData(),
|
||||
new ListCollectionMapper(commonCollectionMapperData,
|
||||
elementComponentData, indexComponentData));
|
||||
} else {
|
||||
mainGenerator.throwUnsupportedTypeException(type, referencingEntityName, propertyName);
|
||||
|
@ -454,8 +462,10 @@ public final class CollectionMetadataGenerator {
|
|||
}
|
||||
|
||||
private Element createMiddleEntityXml(String versionsMiddleTableName, String versionsMiddleEntityName) {
|
||||
String schema = StringTools.isEmpty(joinTable.schema()) ? propertyValue.getCollectionTable().getSchema() : joinTable.schema();
|
||||
String catalog = StringTools.isEmpty(joinTable.catalog()) ? propertyValue.getCollectionTable().getCatalog() : joinTable.catalog();
|
||||
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();
|
||||
|
||||
Element middleEntityXml = MetadataTools.createEntity(xmlMappingData.newAdditionalMapping(),
|
||||
versionsMiddleEntityName, versionsMiddleTableName, schema, catalog, null);
|
||||
|
@ -474,16 +484,6 @@ public final class CollectionMetadataGenerator {
|
|||
return middleEntityXmlId;
|
||||
}
|
||||
|
||||
private AuditJoinTable getDefaultVersionsJoinTable() {
|
||||
return 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(); }
|
||||
};
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
private String getMappedBy(Collection collectionValue) {
|
||||
Iterator<Property> assocClassProps =
|
||||
|
|
|
@ -29,6 +29,7 @@ import org.dom4j.Element;
|
|||
import org.dom4j.tree.DefaultElement;
|
||||
import org.hibernate.envers.ModificationStore;
|
||||
import org.hibernate.envers.entities.IdMappingData;
|
||||
import org.hibernate.envers.entities.PropertyData;
|
||||
import org.hibernate.envers.entities.mapper.SimpleMapperBuilder;
|
||||
import org.hibernate.envers.entities.mapper.id.EmbeddedIdMapper;
|
||||
import org.hibernate.envers.entities.mapper.id.MultipleIdMapper;
|
||||
|
@ -61,8 +62,9 @@ public final class IdMetadataGenerator {
|
|||
if (!"_identifierMapper".equals(property.getName())) {
|
||||
if (propertyType instanceof ImmutableType) {
|
||||
// Last but one parameter: ids are always insertable
|
||||
mainGenerator.getBasicMetadataGenerator().addBasicNoComponent(parent, property.getName(),
|
||||
property.getValue(), mapper, ModificationStore.FULL, true, key);
|
||||
mainGenerator.getBasicMetadataGenerator().addBasicNoComponent(parent,
|
||||
getIdPersistentPropertyAuditingData(property),
|
||||
property.getValue(), mapper, true, key);
|
||||
} else {
|
||||
throw new MappingException("Type not supported: " + propertyType.getClass().getName());
|
||||
}
|
||||
|
@ -94,7 +96,7 @@ public final class IdMetadataGenerator {
|
|||
|
||||
Component id_component = (Component) id_prop.getValue();
|
||||
|
||||
mapper = new EmbeddedIdMapper(id_prop.getName(), id_component.getComponentClassName());
|
||||
mapper = new EmbeddedIdMapper(getIdPropertyData(id_prop), id_component.getComponentClassName());
|
||||
addIdProperties(rel_id_mapping, (Iterator<Property>) id_component.getPropertyIterator(), mapper, false);
|
||||
|
||||
// null mapper - the mapping where already added the first time, now we only want to generate the xml
|
||||
|
@ -105,12 +107,14 @@ public final class IdMetadataGenerator {
|
|||
mapper = new SingleIdMapper();
|
||||
|
||||
// Last but one parameter: ids are always insertable
|
||||
mainGenerator.getBasicMetadataGenerator().addBasicNoComponent(rel_id_mapping, id_prop.getName(),
|
||||
id_prop.getValue(), mapper, ModificationStore.FULL, true, false);
|
||||
mainGenerator.getBasicMetadataGenerator().addBasicNoComponent(rel_id_mapping,
|
||||
getIdPersistentPropertyAuditingData(id_prop),
|
||||
id_prop.getValue(), mapper, true, false);
|
||||
|
||||
// null mapper - the mapping where already added the first time, now we only want to generate the xml
|
||||
mainGenerator.getBasicMetadataGenerator().addBasicNoComponent(orig_id_mapping, id_prop.getName(),
|
||||
id_prop.getValue(), null, ModificationStore.FULL, true, true);
|
||||
mainGenerator.getBasicMetadataGenerator().addBasicNoComponent(orig_id_mapping,
|
||||
getIdPersistentPropertyAuditingData(id_prop),
|
||||
id_prop.getValue(), null, true, true);
|
||||
}
|
||||
|
||||
orig_id_mapping.addAttribute("name", mainGenerator.getVerEntCfg().getOriginalIdPropName());
|
||||
|
@ -120,4 +124,13 @@ public final class IdMetadataGenerator {
|
|||
|
||||
return new IdMappingData(mapper, orig_id_mapping, rel_id_mapping);
|
||||
}
|
||||
|
||||
private PropertyData getIdPropertyData(Property property) {
|
||||
return new PropertyData(property.getName(), property.getPropertyAccessorName(), ModificationStore.FULL);
|
||||
}
|
||||
|
||||
private PersistentPropertyAuditingData getIdPersistentPropertyAuditingData(Property property) {
|
||||
return new PersistentPropertyAuditingData(property.getName(), property.getPropertyAccessorName(),
|
||||
ModificationStore.FULL);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,24 +25,48 @@ package org.hibernate.envers.configuration.metadata;
|
|||
|
||||
import java.util.Map;
|
||||
|
||||
import org.hibernate.envers.ModificationStore;
|
||||
import org.hibernate.envers.AuditTable;
|
||||
import org.hibernate.envers.tools.Tools;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
* @author Sebastian Komander
|
||||
*/
|
||||
public class PropertyStoreInfo {
|
||||
// Not null if the whole class is versioned
|
||||
public ModificationStore defaultStore;
|
||||
|
||||
// Maps property names to their stores defined in per-field versioned annotations
|
||||
public Map<String, ModificationStore> propertyStores;
|
||||
|
||||
public PropertyStoreInfo(Map<String, ModificationStore> propertyStores) {
|
||||
this.propertyStores = propertyStores;
|
||||
public class PersistentClassAuditingData {
|
||||
public PersistentClassAuditingData() {
|
||||
properties = Tools.newHashMap();
|
||||
secondaryTableDictionary = Tools.newHashMap();
|
||||
}
|
||||
|
||||
public PropertyStoreInfo(ModificationStore defaultStore, Map<String, ModificationStore> propertyStores) {
|
||||
this.defaultStore = defaultStore;
|
||||
this.propertyStores = propertyStores;
|
||||
private Map<String, PersistentPropertyAuditingData> properties;
|
||||
private AuditTable auditTable;
|
||||
private Map<String, String> secondaryTableDictionary;
|
||||
|
||||
public Map<String, PersistentPropertyAuditingData> getProperties() {
|
||||
return properties;
|
||||
}
|
||||
|
||||
public PersistentPropertyAuditingData getPropertyAuditingData(String propertyName) {
|
||||
return properties.get(propertyName);
|
||||
}
|
||||
|
||||
public Map<String, String> getSecondaryTableDictionary() {
|
||||
return secondaryTableDictionary;
|
||||
}
|
||||
|
||||
public AuditTable getAuditTable() {
|
||||
return auditTable;
|
||||
}
|
||||
|
||||
public void setAuditTable(AuditTable auditTable) {
|
||||
this.auditTable = auditTable;
|
||||
}
|
||||
|
||||
public boolean isAudited() {
|
||||
if (properties.size() > 0) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,67 +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.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.hibernate.envers.ModificationStore;
|
||||
import org.hibernate.envers.AuditJoinTable;
|
||||
import org.hibernate.envers.AuditTable;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
* @author Sebastian Komander
|
||||
*/
|
||||
public class PersistentClassVersioningData {
|
||||
public PersistentClassVersioningData() {
|
||||
propertyStoreInfo = new PropertyStoreInfo(new HashMap<String, ModificationStore>());
|
||||
secondaryTableDictionary = new HashMap<String, String>();
|
||||
unversionedProperties = new ArrayList<String>();
|
||||
versionsJoinTables = new HashMap<String, AuditJoinTable>();
|
||||
mapKeys = new HashMap<String, String>();
|
||||
}
|
||||
|
||||
public PropertyStoreInfo propertyStoreInfo;
|
||||
public AuditTable versionsTable;
|
||||
public Map<String, String> secondaryTableDictionary;
|
||||
public List<String> unversionedProperties;
|
||||
/**
|
||||
* A map from property names to custom join tables definitions.
|
||||
*/
|
||||
public Map<String, AuditJoinTable> versionsJoinTables;
|
||||
/**
|
||||
* A map from property names to the value of the related property names in a map key annotation. An empty string,
|
||||
* if the property name is not specified in the mapkey annotation.
|
||||
*/
|
||||
public Map<String, String> mapKeys;
|
||||
|
||||
public boolean isVersioned() {
|
||||
if (propertyStoreInfo.propertyStores.size() > 0) { return true; }
|
||||
if (propertyStoreInfo.defaultStore != null) { return true; }
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,93 @@
|
|||
/*
|
||||
* 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 org.hibernate.envers.ModificationStore;
|
||||
import org.hibernate.envers.AuditJoinTable;
|
||||
import org.hibernate.envers.entities.PropertyData;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public class PersistentPropertyAuditingData {
|
||||
private String name;
|
||||
private ModificationStore store;
|
||||
private String mapKey;
|
||||
private AuditJoinTable joinTable;
|
||||
private String accessType;
|
||||
|
||||
public PersistentPropertyAuditingData() {
|
||||
}
|
||||
|
||||
public PersistentPropertyAuditingData(String name, String accessType, ModificationStore store) {
|
||||
this.name = name;
|
||||
this.accessType = accessType;
|
||||
this.store = store;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public ModificationStore getStore() {
|
||||
return store;
|
||||
}
|
||||
|
||||
public void setStore(ModificationStore store) {
|
||||
this.store = store;
|
||||
}
|
||||
|
||||
public String getMapKey() {
|
||||
return mapKey;
|
||||
}
|
||||
|
||||
public void setMapKey(String mapKey) {
|
||||
this.mapKey = mapKey;
|
||||
}
|
||||
|
||||
public AuditJoinTable getJoinTable() {
|
||||
return joinTable;
|
||||
}
|
||||
|
||||
public void setJoinTable(AuditJoinTable joinTable) {
|
||||
this.joinTable = joinTable;
|
||||
}
|
||||
|
||||
public String getAccessType() {
|
||||
return accessType;
|
||||
}
|
||||
|
||||
public void setAccessType(String accessType) {
|
||||
this.accessType = accessType;
|
||||
}
|
||||
|
||||
public PropertyData getPropertyData() {
|
||||
return new PropertyData(name, accessType, store);
|
||||
}
|
||||
}
|
|
@ -26,6 +26,7 @@ package org.hibernate.envers.configuration.metadata;
|
|||
import org.dom4j.Element;
|
||||
import org.hibernate.envers.entities.EntityConfiguration;
|
||||
import org.hibernate.envers.entities.IdMappingData;
|
||||
import org.hibernate.envers.entities.PropertyData;
|
||||
import org.hibernate.envers.entities.mapper.CompositeMapperBuilder;
|
||||
import org.hibernate.envers.entities.mapper.id.IdMapper;
|
||||
import org.hibernate.envers.entities.mapper.relation.OneToOneNotOwningMapper;
|
||||
|
@ -48,7 +49,8 @@ public final class ToOneRelationMetadataGenerator {
|
|||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
void addToOne(Element parent, String name, Value value, CompositeMapperBuilder mapper, String entityName) {
|
||||
void addToOne(Element parent, PersistentPropertyAuditingData persistentPropertyAuditingData, Value value,
|
||||
CompositeMapperBuilder mapper, String entityName) {
|
||||
String referencedEntityName = ((ToOne) value).getReferencedEntityName();
|
||||
|
||||
EntityConfiguration configuration = mainGenerator.getEntitiesConfigurations().get(referencedEntityName);
|
||||
|
@ -58,28 +60,31 @@ public final class ToOneRelationMetadataGenerator {
|
|||
|
||||
IdMappingData idMapping = configuration.getIdMappingData();
|
||||
|
||||
String lastPropertyPrefix = name + "_";
|
||||
String lastPropertyPrefix = persistentPropertyAuditingData.getName() + "_";
|
||||
|
||||
// Generating the id mapper for the relation
|
||||
IdMapper relMapper = idMapping.getIdMapper().prefixMappedProperties(lastPropertyPrefix);
|
||||
|
||||
// Storing information about this relation
|
||||
mainGenerator.getEntitiesConfigurations().get(entityName).addToOneRelation(name, referencedEntityName, relMapper);
|
||||
mainGenerator.getEntitiesConfigurations().get(entityName).addToOneRelation(
|
||||
persistentPropertyAuditingData.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", name);
|
||||
properties.addAttribute("name", persistentPropertyAuditingData.getName());
|
||||
|
||||
MetadataTools.prefixNamesInPropertyElement(properties, lastPropertyPrefix,
|
||||
MetadataTools.getColumnNameIterator(value.getColumnIterator()), false);
|
||||
parent.add(properties);
|
||||
|
||||
// Adding mapper for the id
|
||||
mapper.addComposite(name, new ToOneIdMapper(relMapper, name, referencedEntityName));
|
||||
PropertyData propertyData = persistentPropertyAuditingData.getPropertyData();
|
||||
mapper.addComposite(propertyData, new ToOneIdMapper(relMapper, propertyData, referencedEntityName));
|
||||
}
|
||||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
void addOneToOneNotOwning(String name, Value value, CompositeMapperBuilder mapper, String entityName) {
|
||||
void addOneToOneNotOwning(PersistentPropertyAuditingData persistentPropertyAuditingData, Value value,
|
||||
CompositeMapperBuilder mapper, String entityName) {
|
||||
OneToOne propertyValue = (OneToOne) value;
|
||||
|
||||
String owningReferencePropertyName = propertyValue.getReferencedPropertyName(); // mappedBy
|
||||
|
@ -102,11 +107,13 @@ public final class ToOneRelationMetadataGenerator {
|
|||
IdMapper ownedIdMapper = ownedIdMapping.getIdMapper().prefixMappedProperties(lastPropertyPrefix);
|
||||
|
||||
// Storing information about this relation
|
||||
mainGenerator.getEntitiesConfigurations().get(entityName).addToOneNotOwningRelation(name, owningReferencePropertyName,
|
||||
mainGenerator.getEntitiesConfigurations().get(entityName).addToOneNotOwningRelation(
|
||||
persistentPropertyAuditingData.getName(), owningReferencePropertyName,
|
||||
referencedEntityName, ownedIdMapper);
|
||||
|
||||
// Adding mapper for the id
|
||||
mapper.addComposite(name, new OneToOneNotOwningMapper(owningReferencePropertyName,
|
||||
referencedEntityName, name));
|
||||
PropertyData propertyData = persistentPropertyAuditingData.getPropertyData();
|
||||
mapper.addComposite(propertyData, new OneToOneNotOwningMapper(owningReferencePropertyName,
|
||||
referencedEntityName, propertyData));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -67,7 +67,7 @@ public class EntityInstantiator {
|
|||
|
||||
// First mapping the primary key
|
||||
IdMapper idMapper = verCfg.getEntCfg().get(entityName).getIdMapper();
|
||||
Map originalId = (Map) versionsEntity.get(verCfg.getVerEntCfg().getOriginalIdPropName());
|
||||
Map originalId = (Map) versionsEntity.get(verCfg.getAuditEntCfg().getOriginalIdPropName());
|
||||
|
||||
Object primaryKey = idMapper.mapToIdFromMap(originalId);
|
||||
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Middleware LLC.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.envers.entities;
|
||||
|
||||
import org.hibernate.envers.ModificationStore;
|
||||
|
||||
/**
|
||||
* Holds information on a property that is audited.
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public class PropertyData {
|
||||
private final String name;
|
||||
private final String accessType;
|
||||
private final ModificationStore store;
|
||||
|
||||
/**
|
||||
* Copies the given property data, except the name.
|
||||
* @param newName New name.
|
||||
* @param propertyData Property data to copy the rest of properties from.
|
||||
*/
|
||||
public PropertyData(String newName, PropertyData propertyData) {
|
||||
this.name = newName;
|
||||
this.accessType = propertyData.accessType;
|
||||
this.store = propertyData.store;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param name Name of the property.
|
||||
* @param accessType Accessor type for this property.
|
||||
* @param store How this property should be stored.
|
||||
*/
|
||||
public PropertyData(String name, String accessType, ModificationStore store) {
|
||||
this.name = name;
|
||||
this.accessType = accessType;
|
||||
this.store = store;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public String getAccessType() {
|
||||
return accessType;
|
||||
}
|
||||
|
||||
public ModificationStore getStore() {
|
||||
return store;
|
||||
}
|
||||
}
|
|
@ -23,10 +23,12 @@
|
|||
*/
|
||||
package org.hibernate.envers.entities.mapper;
|
||||
|
||||
import org.hibernate.envers.entities.PropertyData;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public interface CompositeMapperBuilder extends SimpleMapperBuilder {
|
||||
public CompositeMapperBuilder addComposite(String propertyName);
|
||||
public void addComposite(String propertyName, PropertyMapper propertyMapper);
|
||||
public CompositeMapperBuilder addComposite(PropertyData propertyData);
|
||||
public void addComposite(PropertyData propertyData, PropertyMapper propertyMapper);
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ import java.util.HashMap;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.hibernate.envers.ModificationStore;
|
||||
import org.hibernate.envers.entities.PropertyData;
|
||||
import org.hibernate.envers.configuration.AuditConfiguration;
|
||||
import org.hibernate.envers.exception.AuditException;
|
||||
import org.hibernate.envers.reader.AuditReaderImplementor;
|
||||
|
@ -43,29 +43,29 @@ import org.hibernate.util.ReflectHelper;
|
|||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public class MapPropertyMapper implements PropertyMapper, CompositeMapperBuilder {
|
||||
private String propertyName;
|
||||
private PropertyData propertyData;
|
||||
private ExtendedPropertyMapper delegate;
|
||||
|
||||
public MapPropertyMapper(String propertyName) {
|
||||
this.propertyName = propertyName;
|
||||
public MapPropertyMapper(PropertyData propertyData) {
|
||||
this.propertyData = propertyData;
|
||||
this.delegate = new MultiPropertyMapper();
|
||||
}
|
||||
|
||||
public void add(String propertyName, ModificationStore modStore) {
|
||||
delegate.add(propertyName, modStore);
|
||||
public void add(PropertyData propertyData) {
|
||||
delegate.add(propertyData);
|
||||
}
|
||||
|
||||
public CompositeMapperBuilder addComposite(String propertyName) {
|
||||
return delegate.addComposite(propertyName);
|
||||
public CompositeMapperBuilder addComposite(PropertyData propertyData) {
|
||||
return delegate.addComposite(propertyData);
|
||||
}
|
||||
|
||||
public void addComposite(String propertyName, PropertyMapper propertyMapper) {
|
||||
delegate.addComposite(propertyName, propertyMapper);
|
||||
public void addComposite(PropertyData propertyData, PropertyMapper propertyMapper) {
|
||||
delegate.addComposite(propertyData, propertyMapper);
|
||||
}
|
||||
|
||||
public boolean mapToMapFromEntity(Map<String, Object> data, Object newObj, Object oldObj) {
|
||||
Map<String, Object> newData = new HashMap<String, Object>();
|
||||
data.put(propertyName, newData);
|
||||
data.put(propertyData.getName(), newData);
|
||||
|
||||
return delegate.mapToMapFromEntity(newData, newObj, oldObj);
|
||||
}
|
||||
|
@ -75,13 +75,13 @@ public class MapPropertyMapper implements PropertyMapper, CompositeMapperBuilder
|
|||
return;
|
||||
}
|
||||
|
||||
Getter getter = ReflectionTools.getGetter(obj.getClass(), propertyName);
|
||||
Setter setter = ReflectionTools.getSetter(obj.getClass(), propertyName);
|
||||
Getter getter = ReflectionTools.getGetter(obj.getClass(), propertyData);
|
||||
Setter setter = ReflectionTools.getSetter(obj.getClass(), propertyData);
|
||||
|
||||
try {
|
||||
Object subObj = ReflectHelper.getDefaultConstructor(getter.getReturnType()).newInstance();
|
||||
setter.set(obj, subObj, null);
|
||||
delegate.mapToEntityFromMap(verCfg, subObj, (Map) data.get(propertyName), primaryKey, versionsReader, revision);
|
||||
delegate.mapToEntityFromMap(verCfg, subObj, (Map) data.get(propertyData.getName()), primaryKey, versionsReader, revision);
|
||||
} catch (Exception e) {
|
||||
throw new AuditException(e);
|
||||
}
|
||||
|
|
|
@ -24,14 +24,14 @@
|
|||
package org.hibernate.envers.entities.mapper;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.hibernate.envers.ModificationStore;
|
||||
import org.hibernate.envers.entities.PropertyData;
|
||||
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.MappingException;
|
||||
import org.hibernate.collection.PersistentCollection;
|
||||
|
@ -41,31 +41,36 @@ import org.hibernate.property.Getter;
|
|||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public class MultiPropertyMapper implements ExtendedPropertyMapper {
|
||||
protected Map<String, PropertyMapper> properties;
|
||||
protected final Map<PropertyData, PropertyMapper> properties;
|
||||
private final Map<String, PropertyData> propertyDatas;
|
||||
|
||||
public MultiPropertyMapper() {
|
||||
properties = new HashMap<String, PropertyMapper>();
|
||||
properties = Tools.newHashMap();
|
||||
propertyDatas = Tools.newHashMap();
|
||||
}
|
||||
|
||||
public void add(String propertyName, ModificationStore modStore) {
|
||||
public void add(PropertyData propertyData) {
|
||||
SinglePropertyMapper single = new SinglePropertyMapper();
|
||||
single.add(propertyName, modStore);
|
||||
properties.put(propertyName, single);
|
||||
single.add(propertyData);
|
||||
properties.put(propertyData, single);
|
||||
propertyDatas.put(propertyData.getName(), propertyData);
|
||||
}
|
||||
|
||||
public CompositeMapperBuilder addComposite(String propertyName) {
|
||||
if (properties.get(propertyName) != null) {
|
||||
throw new MappingException("Mapping for " + propertyName + " already added!");
|
||||
public CompositeMapperBuilder addComposite(PropertyData propertyData) {
|
||||
if (properties.get(propertyData) != null) {
|
||||
throw new MappingException("Mapping for " + propertyData.getName() + " already added!");
|
||||
}
|
||||
|
||||
MapPropertyMapper mapperBuilder = new MapPropertyMapper(propertyName);
|
||||
properties.put(propertyName, mapperBuilder);
|
||||
MapPropertyMapper mapperBuilder = new MapPropertyMapper(propertyData);
|
||||
properties.put(propertyData, mapperBuilder);
|
||||
propertyDatas.put(propertyData.getName(), propertyData);
|
||||
|
||||
return mapperBuilder;
|
||||
}
|
||||
|
||||
public void addComposite(String propertyName, PropertyMapper propertyMapper) {
|
||||
properties.put(propertyName, propertyMapper);
|
||||
public void addComposite(PropertyData propertyData, PropertyMapper propertyMapper) {
|
||||
properties.put(propertyData, propertyMapper);
|
||||
propertyDatas.put(propertyData.getName(), propertyData);
|
||||
}
|
||||
|
||||
private Object getAtIndexOrNull(Object[] array, int index) { return array == null ? null : array[index]; }
|
||||
|
@ -75,8 +80,8 @@ public class MultiPropertyMapper implements ExtendedPropertyMapper {
|
|||
for (int i=0; i<propertyNames.length; i++) {
|
||||
String propertyName = propertyNames[i];
|
||||
|
||||
if (properties.containsKey(propertyName)) {
|
||||
ret |= properties.get(propertyName).mapToMapFromEntity(data,
|
||||
if (propertyDatas.containsKey(propertyName)) {
|
||||
ret |= properties.get(propertyDatas.get(propertyName)).mapToMapFromEntity(data,
|
||||
getAtIndexOrNull(newState, i),
|
||||
getAtIndexOrNull(oldState, i));
|
||||
}
|
||||
|
@ -87,17 +92,17 @@ public class MultiPropertyMapper implements ExtendedPropertyMapper {
|
|||
|
||||
public boolean mapToMapFromEntity(Map<String, Object> data, Object newObj, Object oldObj) {
|
||||
boolean ret = false;
|
||||
for (String propertyName : properties.keySet()) {
|
||||
for (PropertyData propertyData : properties.keySet()) {
|
||||
Getter getter;
|
||||
if (newObj != null) {
|
||||
getter = ReflectionTools.getGetter(newObj.getClass(), propertyName);
|
||||
getter = ReflectionTools.getGetter(newObj.getClass(), propertyData);
|
||||
} else if (oldObj != null) {
|
||||
getter = ReflectionTools.getGetter(oldObj.getClass(), propertyName);
|
||||
getter = ReflectionTools.getGetter(oldObj.getClass(), propertyData);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
ret |= properties.get(propertyName).mapToMapFromEntity(data,
|
||||
ret |= properties.get(propertyData).mapToMapFromEntity(data,
|
||||
newObj == null ? null : getter.get(newObj),
|
||||
oldObj == null ? null : getter.get(oldObj));
|
||||
}
|
||||
|
@ -105,9 +110,10 @@ public class MultiPropertyMapper implements ExtendedPropertyMapper {
|
|||
return ret;
|
||||
}
|
||||
|
||||
public void mapToEntityFromMap(AuditConfiguration verCfg, Object obj, Map data, Object primaryKey, AuditReaderImplementor versionsReader, Number revision) {
|
||||
for (String propertyName : properties.keySet()) {
|
||||
properties.get(propertyName).mapToEntityFromMap(verCfg, obj, data, primaryKey, versionsReader, revision);
|
||||
public void mapToEntityFromMap(AuditConfiguration verCfg, Object obj, Map data, Object primaryKey,
|
||||
AuditReaderImplementor versionsReader, Number revision) {
|
||||
for (PropertyMapper mapper : properties.values()) {
|
||||
mapper.mapToEntityFromMap(verCfg, obj, data, primaryKey, versionsReader, revision);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -115,7 +121,7 @@ public class MultiPropertyMapper implements ExtendedPropertyMapper {
|
|||
PersistentCollection newColl,
|
||||
Serializable oldColl,
|
||||
Serializable id) {
|
||||
PropertyMapper mapper = properties.get(referencingPropertyName);
|
||||
PropertyMapper mapper = properties.get(propertyDatas.get(referencingPropertyName));
|
||||
if (mapper != null) {
|
||||
return mapper.mapCollectionChanges(referencingPropertyName, newColl, oldColl, id);
|
||||
} else {
|
||||
|
|
|
@ -23,11 +23,11 @@
|
|||
*/
|
||||
package org.hibernate.envers.entities.mapper;
|
||||
|
||||
import org.hibernate.envers.ModificationStore;
|
||||
import org.hibernate.envers.entities.PropertyData;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public interface SimpleMapperBuilder {
|
||||
public void add(String propertyName, ModificationStore modStore);
|
||||
public void add(PropertyData propertyData);
|
||||
}
|
|
@ -27,7 +27,7 @@ import java.io.Serializable;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.hibernate.envers.ModificationStore;
|
||||
import org.hibernate.envers.entities.PropertyData;
|
||||
import org.hibernate.envers.configuration.AuditConfiguration;
|
||||
import org.hibernate.envers.exception.AuditException;
|
||||
import org.hibernate.envers.reader.AuditReaderImplementor;
|
||||
|
@ -42,37 +42,38 @@ import org.hibernate.property.Setter;
|
|||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public class SinglePropertyMapper implements PropertyMapper, SimpleMapperBuilder {
|
||||
private String propertyName;
|
||||
private PropertyData propertyData;
|
||||
|
||||
public SinglePropertyMapper() { }
|
||||
|
||||
public void add(String propertyName, ModificationStore modStore) {
|
||||
if (this.propertyName != null) {
|
||||
public void add(PropertyData propertyData) {
|
||||
if (this.propertyData != null) {
|
||||
throw new AuditException("Only one property can be added!");
|
||||
}
|
||||
|
||||
this.propertyName = propertyName;
|
||||
this.propertyData = propertyData;
|
||||
}
|
||||
|
||||
public boolean mapToMapFromEntity(Map<String, Object> data, Object newObj, Object oldObj) {
|
||||
data.put(propertyName, newObj);
|
||||
data.put(propertyData.getName(), newObj);
|
||||
|
||||
return !Tools.objectsEqual(newObj, oldObj);
|
||||
}
|
||||
|
||||
public void mapToEntityFromMap(AuditConfiguration verCfg, Object obj, Map data, Object primaryKey, AuditReaderImplementor versionsReader, Number revision) {
|
||||
public void mapToEntityFromMap(AuditConfiguration verCfg, Object obj, Map data, Object primaryKey,
|
||||
AuditReaderImplementor versionsReader, Number revision) {
|
||||
if (data == null || obj == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Setter setter = ReflectionTools.getSetter(obj.getClass(), propertyName);
|
||||
setter.set(obj, data.get(propertyName), null);
|
||||
Setter setter = ReflectionTools.getSetter(obj.getClass(), propertyData);
|
||||
setter.set(obj, data.get(propertyData.getName()), null);
|
||||
}
|
||||
|
||||
public List<PersistentCollectionChangeData> mapCollectionChanges(String referencingPropertyName,
|
||||
PersistentCollection newColl,
|
||||
Serializable oldColl,
|
||||
Serializable id) {
|
||||
PersistentCollection newColl,
|
||||
Serializable oldColl,
|
||||
Serializable id) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ import java.io.Serializable;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.hibernate.envers.ModificationStore;
|
||||
import org.hibernate.envers.entities.PropertyData;
|
||||
import org.hibernate.envers.configuration.AuditConfiguration;
|
||||
import org.hibernate.envers.reader.AuditReaderImplementor;
|
||||
|
||||
|
@ -80,15 +80,15 @@ public class SubclassPropertyMapper implements ExtendedPropertyMapper {
|
|||
}
|
||||
}
|
||||
|
||||
public CompositeMapperBuilder addComposite(String propertyName) {
|
||||
return main.addComposite(propertyName);
|
||||
public CompositeMapperBuilder addComposite(PropertyData propertyData) {
|
||||
return main.addComposite(propertyData);
|
||||
}
|
||||
|
||||
public void addComposite(String propertyName, PropertyMapper propertyMapper) {
|
||||
main.addComposite(propertyName, propertyMapper);
|
||||
public void addComposite(PropertyData propertyData, PropertyMapper propertyMapper) {
|
||||
main.addComposite(propertyData, propertyMapper);
|
||||
}
|
||||
|
||||
public void add(String propertyName, ModificationStore modStore) {
|
||||
main.add(propertyName, modStore);
|
||||
public void add(PropertyData propertyData) {
|
||||
main.add(propertyData);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,27 +23,27 @@
|
|||
*/
|
||||
package org.hibernate.envers.entities.mapper.id;
|
||||
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.hibernate.envers.ModificationStore;
|
||||
import org.hibernate.envers.entities.PropertyData;
|
||||
import org.hibernate.envers.exception.AuditException;
|
||||
import org.hibernate.envers.tools.Tools;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public abstract class AbstractCompositeIdMapper extends AbstractIdMapper implements SimpleIdMapperBuilder {
|
||||
protected Map<String, SingleIdMapper> ids;
|
||||
protected Map<PropertyData, SingleIdMapper> ids;
|
||||
protected String compositeIdClass;
|
||||
|
||||
protected AbstractCompositeIdMapper(String compositeIdClass) {
|
||||
ids = new LinkedHashMap<String, SingleIdMapper>();
|
||||
ids = Tools.newLinkedHashMap();
|
||||
|
||||
this.compositeIdClass = compositeIdClass;
|
||||
}
|
||||
|
||||
public void add(String propertyName, ModificationStore modStore) {
|
||||
ids.put(propertyName, new SingleIdMapper(propertyName));
|
||||
public void add(PropertyData propertyData) {
|
||||
ids.put(propertyData, new SingleIdMapper(propertyData));
|
||||
}
|
||||
|
||||
public Object mapToIdFromMap(Map data) {
|
||||
|
|
|
@ -30,6 +30,7 @@ import java.util.Map;
|
|||
|
||||
import org.hibernate.envers.exception.AuditException;
|
||||
import org.hibernate.envers.tools.reflection.ReflectionTools;
|
||||
import org.hibernate.envers.entities.PropertyData;
|
||||
|
||||
import org.hibernate.property.Getter;
|
||||
import org.hibernate.property.Setter;
|
||||
|
@ -39,12 +40,12 @@ import org.hibernate.util.ReflectHelper;
|
|||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public class EmbeddedIdMapper extends AbstractCompositeIdMapper implements SimpleIdMapperBuilder {
|
||||
private String idPropertyName;
|
||||
private PropertyData idPropertyData;
|
||||
|
||||
public EmbeddedIdMapper(String idPropertyName, String compositeIdClass) {
|
||||
public EmbeddedIdMapper(PropertyData idPropertyData, String compositeIdClass) {
|
||||
super(compositeIdClass);
|
||||
|
||||
this.idPropertyName = idPropertyName;
|
||||
this.idPropertyData = idPropertyData;
|
||||
}
|
||||
|
||||
public void mapToMapFromId(Map<String, Object> data, Object obj) {
|
||||
|
@ -58,7 +59,7 @@ public class EmbeddedIdMapper extends AbstractCompositeIdMapper implements Simpl
|
|||
return;
|
||||
}
|
||||
|
||||
Getter getter = ReflectionTools.getGetter(obj.getClass(), idPropertyName);
|
||||
Getter getter = ReflectionTools.getGetter(obj.getClass(), idPropertyData);
|
||||
mapToMapFromId(data, getter.get(obj));
|
||||
}
|
||||
|
||||
|
@ -67,8 +68,8 @@ public class EmbeddedIdMapper extends AbstractCompositeIdMapper implements Simpl
|
|||
return;
|
||||
}
|
||||
|
||||
Getter getter = ReflectionTools.getGetter(obj.getClass(), idPropertyName);
|
||||
Setter setter = ReflectionTools.getSetter(obj.getClass(), idPropertyName);
|
||||
Getter getter = ReflectionTools.getGetter(obj.getClass(), idPropertyData);
|
||||
Setter setter = ReflectionTools.getSetter(obj.getClass(), idPropertyData);
|
||||
|
||||
try {
|
||||
Object subObj = ReflectHelper.getDefaultConstructor(getter.getReturnType()).newInstance();
|
||||
|
@ -83,10 +84,12 @@ public class EmbeddedIdMapper extends AbstractCompositeIdMapper implements Simpl
|
|||
}
|
||||
|
||||
public IdMapper prefixMappedProperties(String prefix) {
|
||||
EmbeddedIdMapper ret = new EmbeddedIdMapper(idPropertyName, compositeIdClass);
|
||||
EmbeddedIdMapper ret = new EmbeddedIdMapper(idPropertyData, compositeIdClass);
|
||||
|
||||
for (String propertyName : ids.keySet()) {
|
||||
ret.ids.put(propertyName, new SingleIdMapper(propertyName, prefix + propertyName));
|
||||
for (PropertyData propertyData : ids.keySet()) {
|
||||
String propertyName = propertyData.getName();
|
||||
ret.ids.put(propertyData, new SingleIdMapper(propertyName,
|
||||
new PropertyData(prefix + propertyName, propertyData)));
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
@ -97,7 +100,7 @@ public class EmbeddedIdMapper extends AbstractCompositeIdMapper implements Simpl
|
|||
return null;
|
||||
}
|
||||
|
||||
Getter getter = ReflectionTools.getGetter(data.getClass(), idPropertyName);
|
||||
Getter getter = ReflectionTools.getGetter(data.getClass(), idPropertyData);
|
||||
return getter.get(data);
|
||||
}
|
||||
|
||||
|
|
|
@ -29,6 +29,7 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
|
||||
import org.hibernate.envers.exception.AuditException;
|
||||
import org.hibernate.envers.entities.PropertyData;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
|
@ -57,8 +58,10 @@ public class MultipleIdMapper extends AbstractCompositeIdMapper implements Simpl
|
|||
public IdMapper prefixMappedProperties(String prefix) {
|
||||
MultipleIdMapper ret = new MultipleIdMapper(compositeIdClass);
|
||||
|
||||
for (String propertyName : ids.keySet()) {
|
||||
ret.ids.put(propertyName, new SingleIdMapper(propertyName, prefix + propertyName));
|
||||
for (PropertyData propertyData : ids.keySet()) {
|
||||
String propertyName = propertyData.getName();
|
||||
ret.ids.put(propertyData, new SingleIdMapper(propertyName,
|
||||
new PropertyData(prefix + propertyName, propertyData)));
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
|
|
@ -27,7 +27,7 @@ import java.util.ArrayList;
|
|||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.hibernate.envers.ModificationStore;
|
||||
import org.hibernate.envers.entities.PropertyData;
|
||||
import org.hibernate.envers.exception.AuditException;
|
||||
import org.hibernate.envers.tools.reflection.ReflectionTools;
|
||||
|
||||
|
@ -39,28 +39,28 @@ import org.hibernate.property.Setter;
|
|||
*/
|
||||
public class SingleIdMapper extends AbstractIdMapper implements SimpleIdMapperBuilder {
|
||||
private String beanPropertyName;
|
||||
private String propertyName;
|
||||
private PropertyData propertyData;
|
||||
|
||||
public SingleIdMapper() {
|
||||
}
|
||||
|
||||
public SingleIdMapper(String beanPropertyName, String propertyName) {
|
||||
public SingleIdMapper(String beanPropertyName, PropertyData propertyData) {
|
||||
this.beanPropertyName = beanPropertyName;
|
||||
this.propertyName = propertyName;
|
||||
this.propertyData = propertyData;
|
||||
}
|
||||
|
||||
public SingleIdMapper(String propertyName) {
|
||||
this.beanPropertyName = propertyName;
|
||||
this.propertyName = propertyName;
|
||||
public SingleIdMapper(PropertyData propertyData) {
|
||||
this.beanPropertyName = propertyData.getName();
|
||||
this.propertyData = propertyData;
|
||||
}
|
||||
|
||||
public void add(String propertyName, ModificationStore modStore) {
|
||||
if (this.propertyName != null) {
|
||||
public void add(PropertyData propertyData) {
|
||||
if (this.propertyData != null) {
|
||||
throw new AuditException("Only one property can be added!");
|
||||
}
|
||||
|
||||
this.propertyName = propertyName;
|
||||
this.beanPropertyName = propertyName;
|
||||
this.propertyData = propertyData;
|
||||
this.beanPropertyName = propertyData.getName();
|
||||
}
|
||||
|
||||
public void mapToEntityFromMap(Object obj, Map data) {
|
||||
|
@ -68,8 +68,8 @@ public class SingleIdMapper extends AbstractIdMapper implements SimpleIdMapperBu
|
|||
return;
|
||||
}
|
||||
|
||||
Setter setter = ReflectionTools.getSetter(obj.getClass(), beanPropertyName);
|
||||
setter.set(obj, data.get(propertyName), null);
|
||||
Setter setter = ReflectionTools.getSetter(obj.getClass(), beanPropertyName, propertyData.getAccessType());
|
||||
setter.set(obj, data.get(propertyData.getName()), null);
|
||||
}
|
||||
|
||||
public Object mapToIdFromMap(Map data) {
|
||||
|
@ -77,7 +77,7 @@ public class SingleIdMapper extends AbstractIdMapper implements SimpleIdMapperBu
|
|||
return null;
|
||||
}
|
||||
|
||||
return data.get(propertyName);
|
||||
return data.get(propertyData.getName());
|
||||
}
|
||||
|
||||
public Object mapToIdFromEntity(Object data) {
|
||||
|
@ -85,22 +85,22 @@ public class SingleIdMapper extends AbstractIdMapper implements SimpleIdMapperBu
|
|||
return null;
|
||||
}
|
||||
|
||||
Getter getter = ReflectionTools.getGetter(data.getClass(), beanPropertyName);
|
||||
Getter getter = ReflectionTools.getGetter(data.getClass(), beanPropertyName, propertyData.getAccessType());
|
||||
return getter.get(data);
|
||||
}
|
||||
|
||||
public void mapToMapFromId(Map<String, Object> data, Object obj) {
|
||||
if (data != null) {
|
||||
data.put(propertyName, obj);
|
||||
data.put(propertyData.getName(), obj);
|
||||
}
|
||||
}
|
||||
|
||||
public void mapToMapFromEntity(Map<String, Object> data, Object obj) {
|
||||
if (obj == null) {
|
||||
data.put(propertyName, null);
|
||||
data.put(propertyData.getName(), null);
|
||||
} else {
|
||||
Getter getter = ReflectionTools.getGetter(obj.getClass(), beanPropertyName);
|
||||
data.put(propertyName, getter.get(obj));
|
||||
Getter getter = ReflectionTools.getGetter(obj.getClass(), beanPropertyName, propertyData.getAccessType());
|
||||
data.put(propertyData.getName(), getter.get(obj));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -109,19 +109,20 @@ public class SingleIdMapper extends AbstractIdMapper implements SimpleIdMapperBu
|
|||
return;
|
||||
}
|
||||
|
||||
Getter getter = ReflectionTools.getGetter(objFrom.getClass(), beanPropertyName);
|
||||
Setter setter = ReflectionTools.getSetter(objTo.getClass(), beanPropertyName);
|
||||
Getter getter = ReflectionTools.getGetter(objFrom.getClass(), beanPropertyName, propertyData.getAccessType());
|
||||
Setter setter = ReflectionTools.getSetter(objTo.getClass(), beanPropertyName, propertyData.getAccessType());
|
||||
setter.set(objTo, getter.get(objFrom), null);
|
||||
}
|
||||
|
||||
public IdMapper prefixMappedProperties(String prefix) {
|
||||
return new SingleIdMapper(propertyName, prefix + propertyName);
|
||||
return new SingleIdMapper(propertyData.getName(),
|
||||
new PropertyData(prefix + propertyData.getName(), propertyData));
|
||||
}
|
||||
|
||||
public List<QueryParameterData> mapToQueryParametersFromId(Object obj) {
|
||||
List<QueryParameterData> ret = new ArrayList<QueryParameterData>();
|
||||
|
||||
ret.add(new QueryParameterData(propertyName, obj));
|
||||
ret.add(new QueryParameterData(propertyData.getName(), obj));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -101,7 +101,8 @@ public abstract class AbstractCollectionMapper<T> implements PropertyMapper {
|
|||
public List<PersistentCollectionChangeData> mapCollectionChanges(String referencingPropertyName,
|
||||
PersistentCollection newColl,
|
||||
Serializable oldColl, Serializable id) {
|
||||
if (!commonCollectionMapperData.getCollectionReferencingPropertyName().equals(referencingPropertyName)) {
|
||||
if (!commonCollectionMapperData.getCollectionReferencingPropertyData().getName()
|
||||
.equals(referencingPropertyName)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
@ -138,7 +139,7 @@ public abstract class AbstractCollectionMapper<T> implements PropertyMapper {
|
|||
public void mapToEntityFromMap(AuditConfiguration verCfg, Object obj, Map data, Object primaryKey,
|
||||
AuditReaderImplementor versionsReader, Number revision) {
|
||||
Setter setter = ReflectionTools.getSetter(obj.getClass(),
|
||||
commonCollectionMapperData.getCollectionReferencingPropertyName());
|
||||
commonCollectionMapperData.getCollectionReferencingPropertyData());
|
||||
try {
|
||||
setter.set(obj, proxyConstructor.newInstance(getInitializor(verCfg, versionsReader, primaryKey, revision)), null);
|
||||
} catch (InstantiationException e) {
|
||||
|
|
|
@ -25,6 +25,7 @@ package org.hibernate.envers.entities.mapper.relation;
|
|||
|
||||
import org.hibernate.envers.configuration.AuditEntitiesConfiguration;
|
||||
import org.hibernate.envers.entities.mapper.relation.query.RelationQueryGenerator;
|
||||
import org.hibernate.envers.entities.PropertyData;
|
||||
|
||||
/**
|
||||
* Data that is used by all collection mappers, regardless of the type.
|
||||
|
@ -33,16 +34,16 @@ import org.hibernate.envers.entities.mapper.relation.query.RelationQueryGenerato
|
|||
public final class CommonCollectionMapperData {
|
||||
private final AuditEntitiesConfiguration verEntCfg;
|
||||
private final String versionsMiddleEntityName;
|
||||
private final String collectionReferencingPropertyName;
|
||||
private final PropertyData collectionReferencingPropertyData;
|
||||
private final MiddleIdData referencingIdData;
|
||||
private final RelationQueryGenerator queryGenerator;
|
||||
|
||||
public CommonCollectionMapperData(AuditEntitiesConfiguration verEntCfg, String versionsMiddleEntityName,
|
||||
String collectionReferencingPropertyName, MiddleIdData referencingIdData,
|
||||
PropertyData collectionReferencingPropertyData, MiddleIdData referencingIdData,
|
||||
RelationQueryGenerator queryGenerator) {
|
||||
this.verEntCfg = verEntCfg;
|
||||
this.versionsMiddleEntityName = versionsMiddleEntityName;
|
||||
this.collectionReferencingPropertyName = collectionReferencingPropertyName;
|
||||
this.collectionReferencingPropertyData = collectionReferencingPropertyData;
|
||||
this.referencingIdData = referencingIdData;
|
||||
this.queryGenerator = queryGenerator;
|
||||
}
|
||||
|
@ -55,8 +56,8 @@ public final class CommonCollectionMapperData {
|
|||
return versionsMiddleEntityName;
|
||||
}
|
||||
|
||||
public String getCollectionReferencingPropertyName() {
|
||||
return collectionReferencingPropertyName;
|
||||
public PropertyData getCollectionReferencingPropertyData() {
|
||||
return collectionReferencingPropertyData;
|
||||
}
|
||||
|
||||
public MiddleIdData getReferencingIdData() {
|
||||
|
|
|
@ -31,6 +31,7 @@ import javax.persistence.NoResultException;
|
|||
import org.hibernate.envers.configuration.AuditConfiguration;
|
||||
import org.hibernate.envers.entities.mapper.PersistentCollectionChangeData;
|
||||
import org.hibernate.envers.entities.mapper.PropertyMapper;
|
||||
import org.hibernate.envers.entities.PropertyData;
|
||||
import org.hibernate.envers.exception.AuditException;
|
||||
import org.hibernate.envers.query.AuditRestrictions;
|
||||
import org.hibernate.envers.reader.AuditReaderImplementor;
|
||||
|
@ -46,12 +47,13 @@ import org.hibernate.property.Setter;
|
|||
public class OneToOneNotOwningMapper implements PropertyMapper {
|
||||
private String owningReferencePropertyName;
|
||||
private String owningEntityName;
|
||||
private String propertyName;
|
||||
private PropertyData propertyData;
|
||||
|
||||
public OneToOneNotOwningMapper(String owningReferencePropertyName, String owningEntityName, String propertyName) {
|
||||
public OneToOneNotOwningMapper(String owningReferencePropertyName, String owningEntityName,
|
||||
PropertyData propertyData) {
|
||||
this.owningReferencePropertyName = owningReferencePropertyName;
|
||||
this.owningEntityName = owningEntityName;
|
||||
this.propertyName = propertyName;
|
||||
this.propertyData = propertyData;
|
||||
}
|
||||
|
||||
public boolean mapToMapFromEntity(Map<String, Object> data, Object newObj, Object oldObj) {
|
||||
|
@ -77,7 +79,7 @@ public class OneToOneNotOwningMapper implements PropertyMapper {
|
|||
", " + owningReferencePropertyName + ")");
|
||||
}
|
||||
|
||||
Setter setter = ReflectionTools.getSetter(obj.getClass(), propertyName);
|
||||
Setter setter = ReflectionTools.getSetter(obj.getClass(), propertyData);
|
||||
setter.set(obj, value, null);
|
||||
}
|
||||
|
||||
|
|
|
@ -33,6 +33,7 @@ import org.hibernate.envers.entities.mapper.PersistentCollectionChangeData;
|
|||
import org.hibernate.envers.entities.mapper.PropertyMapper;
|
||||
import org.hibernate.envers.entities.mapper.id.IdMapper;
|
||||
import org.hibernate.envers.entities.mapper.relation.lazy.ToOneDelegateSessionImplementor;
|
||||
import org.hibernate.envers.entities.PropertyData;
|
||||
import org.hibernate.envers.reader.AuditReaderImplementor;
|
||||
import org.hibernate.envers.tools.Tools;
|
||||
import org.hibernate.envers.tools.reflection.ReflectionTools;
|
||||
|
@ -45,18 +46,18 @@ import org.hibernate.property.Setter;
|
|||
*/
|
||||
public class ToOneIdMapper implements PropertyMapper {
|
||||
private final IdMapper delegate;
|
||||
private final String propertyName;
|
||||
private final PropertyData propertyData;
|
||||
private final String referencedEntityName;
|
||||
|
||||
public ToOneIdMapper(IdMapper delegate, String propertyName, String referencedEntityName) {
|
||||
public ToOneIdMapper(IdMapper delegate, PropertyData propertyData, String referencedEntityName) {
|
||||
this.delegate = delegate;
|
||||
this.propertyName = propertyName;
|
||||
this.propertyData = propertyData;
|
||||
this.referencedEntityName = referencedEntityName;
|
||||
}
|
||||
|
||||
public boolean mapToMapFromEntity(Map<String, Object> data, Object newObj, Object oldObj) {
|
||||
HashMap<String, Object> newData = new HashMap<String, Object>();
|
||||
data.put(propertyName, newData);
|
||||
data.put(propertyData.getName(), newData);
|
||||
|
||||
delegate.mapToMapFromEntity(newData, newObj);
|
||||
|
||||
|
@ -69,7 +70,7 @@ public class ToOneIdMapper implements PropertyMapper {
|
|||
return;
|
||||
}
|
||||
|
||||
Object entityId = delegate.mapToIdFromMap((Map) data.get(propertyName));
|
||||
Object entityId = delegate.mapToIdFromMap((Map) data.get(propertyData.getName()));
|
||||
Object value;
|
||||
if (entityId == null) {
|
||||
value = null;
|
||||
|
@ -84,7 +85,7 @@ public class ToOneIdMapper implements PropertyMapper {
|
|||
}
|
||||
}
|
||||
|
||||
Setter setter = ReflectionTools.getSetter(obj.getClass(), propertyName);
|
||||
Setter setter = ReflectionTools.getSetter(obj.getClass(), propertyData);
|
||||
setter.set(obj, value, null);
|
||||
}
|
||||
|
||||
|
|
|
@ -35,17 +35,19 @@ import org.hibernate.envers.tools.reflection.ReflectionTools;
|
|||
* so <code>mapToMapFromObject</code> is empty.
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
public final class MiddleMapKeyPropertyComponentMapper implements MiddleComponentMapper {
|
||||
public class MiddleMapKeyPropertyComponentMapper implements MiddleComponentMapper {
|
||||
private final String propertyName;
|
||||
private final String accessType;
|
||||
|
||||
public MiddleMapKeyPropertyComponentMapper(String propertyName) {
|
||||
public MiddleMapKeyPropertyComponentMapper(String propertyName, String accessType) {
|
||||
this.propertyName = propertyName;
|
||||
this.accessType = accessType;
|
||||
}
|
||||
|
||||
public Object mapToObjectFromFullMap(EntityInstantiator entityInstantiator, Map<String, Object> data,
|
||||
Object dataObject, Number revision) {
|
||||
// dataObject is not null, as this mapper can only be used in an index.
|
||||
return ReflectionTools.getGetter(dataObject.getClass(), propertyName).get(dataObject);
|
||||
return ReflectionTools.getGetter(dataObject.getClass(), propertyName, accessType).get(dataObject);
|
||||
}
|
||||
|
||||
public void mapToMapFromObject(Map<String, Object> data, Object obj) {
|
||||
|
|
|
@ -124,6 +124,6 @@ public class RevisionProperty implements AuditProjection {
|
|||
}
|
||||
|
||||
public Triple<String, String, Boolean> getData(AuditConfiguration verCfg) {
|
||||
return Triple.make(null, verCfg.getVerEntCfg().getRevisionPropPath(), false);
|
||||
return Triple.make(null, verCfg.getAuditEntCfg().getRevisionPropPath(), false);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,6 +42,6 @@ public class RevisionTypeProperty implements AuditProjection {
|
|||
}
|
||||
|
||||
public Triple<String, String, Boolean> getData(AuditConfiguration verCfg) {
|
||||
return Triple.make(null, verCfg.getVerEntCfg().getRevisionTypePropName(), false);
|
||||
return Triple.make(null, verCfg.getAuditEntCfg().getRevisionTypePropName(), false);
|
||||
}
|
||||
}
|
|
@ -39,6 +39,6 @@ public class IdentifierEqVersionsExpression implements AuditCriterion {
|
|||
|
||||
public void addToQuery(AuditConfiguration verCfg, String entityName, QueryBuilder qb, Parameters parameters) {
|
||||
verCfg.getEntCfg().get(entityName).getIdMapper()
|
||||
.addIdEqualsToQuery(parameters, id, verCfg.getVerEntCfg().getOriginalIdPropName(), true);
|
||||
.addIdEqualsToQuery(parameters, id, verCfg.getAuditEntCfg().getOriginalIdPropName(), true);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,6 +40,6 @@ public class RevisionVersionsExpression implements AuditCriterion {
|
|||
}
|
||||
|
||||
public void addToQuery(AuditConfiguration verCfg, String entityName, QueryBuilder qb, Parameters parameters) {
|
||||
parameters.addWhereWithParam(verCfg.getVerEntCfg().getRevisionPropPath(), op, value);
|
||||
parameters.addWhereWithParam(verCfg.getAuditEntCfg().getRevisionPropPath(), op, value);
|
||||
}
|
||||
}
|
|
@ -73,7 +73,7 @@ public abstract class AbstractVersionsQuery implements AuditQuery {
|
|||
entityInstantiator = new EntityInstantiator(verCfg, versionsReader);
|
||||
|
||||
entityName = cls.getName();
|
||||
versionsEntityName = verCfg.getVerEntCfg().getVersionsEntityName(entityName);
|
||||
versionsEntityName = verCfg.getAuditEntCfg().getVersionsEntityName(entityName);
|
||||
|
||||
qb = new QueryBuilder(versionsEntityName, "e");
|
||||
}
|
||||
|
@ -84,8 +84,6 @@ public abstract class AbstractVersionsQuery implements AuditQuery {
|
|||
|
||||
qb.build(querySb, queryParamValues);
|
||||
|
||||
System.out.println("QUERY: " + querySb.toString());
|
||||
|
||||
Query query = versionsReader.getSession().createQuery(querySb.toString());
|
||||
for (Map.Entry<String, Object> paramValue : queryParamValues.entrySet()) {
|
||||
query.setParameter(paramValue.getKey(), paramValue.getValue());
|
||||
|
|
|
@ -59,7 +59,7 @@ public class EntitiesAtRevisionQuery extends AbstractVersionsQuery {
|
|||
|
||||
QueryBuilder maxRevQb = qb.newSubQueryBuilder(versionsEntityName, "e2");
|
||||
|
||||
AuditEntitiesConfiguration verEntCfg = verCfg.getVerEntCfg();
|
||||
AuditEntitiesConfiguration verEntCfg = verCfg.getAuditEntCfg();
|
||||
|
||||
String revisionPropertyPath = verEntCfg.getRevisionPropPath();
|
||||
String originalIdPropertyName = verEntCfg.getOriginalIdPropName();
|
||||
|
|
|
@ -54,7 +54,7 @@ public class RevisionsOfEntityQuery extends AbstractVersionsQuery {
|
|||
}
|
||||
|
||||
private Number getRevisionNumber(Map versionsEntity) {
|
||||
AuditEntitiesConfiguration verEntCfg = verCfg.getVerEntCfg();
|
||||
AuditEntitiesConfiguration verEntCfg = verCfg.getAuditEntCfg();
|
||||
|
||||
String originalId = verEntCfg.getOriginalIdPropName();
|
||||
String revisionPropertyName = verEntCfg.getRevisionPropName();
|
||||
|
@ -71,7 +71,7 @@ public class RevisionsOfEntityQuery extends AbstractVersionsQuery {
|
|||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
public List list() throws AuditException {
|
||||
AuditEntitiesConfiguration verEntCfg = verCfg.getVerEntCfg();
|
||||
AuditEntitiesConfiguration verEntCfg = verCfg.getAuditEntCfg();
|
||||
|
||||
/*
|
||||
The query that should be executed in the versions table:
|
||||
|
@ -97,8 +97,8 @@ public class RevisionsOfEntityQuery extends AbstractVersionsQuery {
|
|||
}
|
||||
|
||||
if (!selectEntitiesOnly) {
|
||||
qb.addFrom(verCfg.getVerEntCfg().getRevisionInfoEntityName(), "r");
|
||||
qb.getRootParameters().addWhere(verCfg.getVerEntCfg().getRevisionPropPath(), true, "=", "r.id", false);
|
||||
qb.addFrom(verCfg.getAuditEntCfg().getRevisionInfoEntityName(), "r");
|
||||
qb.getRootParameters().addWhere(verCfg.getAuditEntCfg().getRevisionPropPath(), true, "=", "r.id", false);
|
||||
}
|
||||
|
||||
List<Object> queryResult = buildAndExecuteQuery();
|
||||
|
|
|
@ -37,7 +37,7 @@ public class RevisionVersionsOrder implements AuditOrder {
|
|||
}
|
||||
|
||||
public Pair<String, Boolean> getData(AuditConfiguration verCfg) {
|
||||
String revisionPropPath = verCfg.getVerEntCfg().getRevisionPropPath();
|
||||
String revisionPropPath = verCfg.getAuditEntCfg().getRevisionPropPath();
|
||||
return Pair.make(revisionPropPath, asc);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,7 +45,7 @@ public class RevisionVersionsProjection implements AuditProjection {
|
|||
}
|
||||
|
||||
public Triple<String, String, Boolean> getData(AuditConfiguration verCfg) {
|
||||
String revisionPropPath = verCfg.getVerEntCfg().getRevisionPropPath();
|
||||
String revisionPropPath = verCfg.getAuditEntCfg().getRevisionPropPath();
|
||||
|
||||
switch (type) {
|
||||
case MAX: return Triple.make("max", revisionPropPath, false);
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
package org.hibernate.envers.revisioninfo;
|
||||
|
||||
import org.hibernate.envers.RevisionListener;
|
||||
import org.hibernate.envers.entities.PropertyData;
|
||||
import org.hibernate.envers.tools.reflection.ReflectionTools;
|
||||
|
||||
import org.hibernate.MappingException;
|
||||
|
@ -41,11 +42,11 @@ public class DefaultRevisionInfoGenerator implements RevisionInfoGenerator {
|
|||
|
||||
public DefaultRevisionInfoGenerator(String revisionInfoEntityName, Class<?> revisionInfoClass,
|
||||
Class<? extends RevisionListener> listenerClass,
|
||||
String revisionInfoTimestampName) {
|
||||
PropertyData revisionInfoTimestampData) {
|
||||
this.revisionInfoEntityName = revisionInfoEntityName;
|
||||
this.revisionInfoClass = revisionInfoClass;
|
||||
|
||||
revisionTimestampSetter = ReflectionTools.getSetter(revisionInfoClass, revisionInfoTimestampName);
|
||||
revisionTimestampSetter = ReflectionTools.getSetter(revisionInfoClass, revisionInfoTimestampData);
|
||||
|
||||
if (!listenerClass.equals(RevisionListener.class)) {
|
||||
// This is not the default value.
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
package org.hibernate.envers.revisioninfo;
|
||||
|
||||
import org.hibernate.envers.tools.reflection.ReflectionTools;
|
||||
import org.hibernate.envers.entities.PropertyData;
|
||||
|
||||
import org.hibernate.property.Getter;
|
||||
|
||||
|
@ -33,8 +34,8 @@ import org.hibernate.property.Getter;
|
|||
*/
|
||||
public class RevisionInfoNumberReader {
|
||||
private final Getter revisionIdGetter;
|
||||
public RevisionInfoNumberReader(Class<?> revisionInfoClass, String revisionInfoIdName) {
|
||||
revisionIdGetter = ReflectionTools.getGetter(revisionInfoClass, revisionInfoIdName);
|
||||
public RevisionInfoNumberReader(Class<?> revisionInfoClass, PropertyData revisionInfoIdData) {
|
||||
revisionIdGetter = ReflectionTools.getGetter(revisionInfoClass, revisionInfoIdData);
|
||||
}
|
||||
|
||||
public Number getRevisionNumber(Object revision) {
|
||||
|
|
|
@ -51,7 +51,7 @@ public abstract class AbstractAuditWorkUnit implements AuditWorkUnit {
|
|||
}
|
||||
|
||||
protected void fillDataWithId(Map<String, Object> data, Object revision, RevisionType revisionType) {
|
||||
AuditEntitiesConfiguration entitiesCfg = verCfg.getVerEntCfg();
|
||||
AuditEntitiesConfiguration entitiesCfg = verCfg.getAuditEntCfg();
|
||||
|
||||
Map<String, Object> originalId = new HashMap<String, Object>();
|
||||
originalId.put(entitiesCfg.getRevisionPropName(), revision);
|
||||
|
@ -79,7 +79,7 @@ public abstract class AbstractAuditWorkUnit implements AuditWorkUnit {
|
|||
|
||||
public void undo(Session session) {
|
||||
if (isPerformed()) {
|
||||
session.delete(verCfg.getVerEntCfg().getVersionsEntityName(getEntityName()), performedData);
|
||||
session.delete(verCfg.getAuditEntCfg().getVersionsEntityName(getEntityName()), performedData);
|
||||
session.flush();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -58,7 +58,7 @@ public class AddWorkUnit extends AbstractAuditWorkUnit implements AuditWorkUnit
|
|||
|
||||
verCfg.getEntCfg().get(getEntityName()).getPropertyMapper().map(data, propertyNames, state, null);
|
||||
|
||||
session.save(verCfg.getVerEntCfg().getVersionsEntityName(getEntityName()), data);
|
||||
session.save(verCfg.getAuditEntCfg().getVersionsEntityName(getEntityName()), data);
|
||||
|
||||
setPerformed(data);
|
||||
}
|
||||
|
|
|
@ -54,7 +54,7 @@ public class CollectionChangeWorkUnit extends AbstractAuditWorkUnit implements A
|
|||
|
||||
verCfg.getEntCfg().get(getEntityName()).getPropertyMapper().mapToMapFromEntity(data, entity, null);
|
||||
|
||||
session.save(verCfg.getVerEntCfg().getVersionsEntityName(getEntityName()), data);
|
||||
session.save(verCfg.getAuditEntCfg().getVersionsEntityName(getEntityName()), data);
|
||||
|
||||
setPerformed(data);
|
||||
}
|
||||
|
|
|
@ -48,7 +48,7 @@ public class DelWorkUnit extends AbstractAuditWorkUnit implements AuditWorkUnit
|
|||
Map<String, Object> data = new HashMap<String, Object>();
|
||||
fillDataWithId(data, revisionData, RevisionType.DEL);
|
||||
|
||||
session.save(verCfg.getVerEntCfg().getVersionsEntityName(getEntityName()), data);
|
||||
session.save(verCfg.getAuditEntCfg().getVersionsEntityName(getEntityName()), data);
|
||||
|
||||
setPerformed(data);
|
||||
}
|
||||
|
|
|
@ -56,7 +56,7 @@ public class ModWorkUnit extends AbstractAuditWorkUnit implements AuditWorkUnit
|
|||
public void perform(Session session, Object revisionData) {
|
||||
fillDataWithId(data, revisionData, RevisionType.MOD);
|
||||
|
||||
session.save(verCfg.getVerEntCfg().getVersionsEntityName(getEntityName()), data);
|
||||
session.save(verCfg.getAuditEntCfg().getVersionsEntityName(getEntityName()), data);
|
||||
|
||||
setPerformed(data);
|
||||
}
|
||||
|
|
|
@ -58,7 +58,7 @@ public class PersistentCollectionChangeWorkUnit extends AbstractAuditWorkUnit im
|
|||
|
||||
@SuppressWarnings({"unchecked"})
|
||||
public void perform(Session session, Object revisionData) {
|
||||
AuditEntitiesConfiguration entitiesCfg = verCfg.getVerEntCfg();
|
||||
AuditEntitiesConfiguration entitiesCfg = verCfg.getAuditEntCfg();
|
||||
|
||||
for (PersistentCollectionChangeData persistentCollectionChangeData : collectionChanges) {
|
||||
// Setting the revision number
|
||||
|
|
|
@ -23,11 +23,7 @@
|
|||
*/
|
||||
package org.hibernate.envers.tools;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
|
@ -37,6 +33,14 @@ public class Tools {
|
|||
return new HashMap<K,V>();
|
||||
}
|
||||
|
||||
public static <E> Set<E> newHashSet() {
|
||||
return new HashSet<E>();
|
||||
}
|
||||
|
||||
public static <K,V> Map<K,V> newLinkedHashMap() {
|
||||
return new LinkedHashMap<K,V>();
|
||||
}
|
||||
|
||||
public static boolean objectsEqual(Object obj1, Object obj2) {
|
||||
if (obj1 == null) {
|
||||
return obj2 == null;
|
||||
|
|
|
@ -29,12 +29,9 @@ import org.hibernate.envers.exception.AuditException;
|
|||
import org.hibernate.envers.tools.ConcurrentReferenceHashMap;
|
||||
import org.hibernate.envers.tools.Pair;
|
||||
import static org.hibernate.envers.tools.Pair.make;
|
||||
import org.hibernate.envers.entities.PropertyData;
|
||||
|
||||
import org.hibernate.property.BasicPropertyAccessor;
|
||||
import org.hibernate.property.Getter;
|
||||
import org.hibernate.property.PropertyAccessor;
|
||||
import org.hibernate.property.Setter;
|
||||
import org.hibernate.util.ReflectHelper;
|
||||
import org.hibernate.property.*;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
|
@ -49,8 +46,6 @@ public class ReflectionTools {
|
|||
ConcurrentReferenceHashMap.ReferenceType.SOFT,
|
||||
ConcurrentReferenceHashMap.ReferenceType.SOFT);
|
||||
|
||||
private static final PropertyAccessor BASIC_PROPERTY_ACCESSOR = new BasicPropertyAccessor();
|
||||
|
||||
public static Class<?> loadClass(String name) {
|
||||
try {
|
||||
return Thread.currentThread().getContextClassLoader().loadClass(name);
|
||||
|
@ -59,11 +54,19 @@ public class ReflectionTools {
|
|||
}
|
||||
}
|
||||
|
||||
public static Getter getGetter(Class cls, String propertyName) {
|
||||
private static PropertyAccessor getAccessor(String accessorType) {
|
||||
return PropertyAccessorFactory.getPropertyAccessor(accessorType);
|
||||
}
|
||||
|
||||
public static Getter getGetter(Class cls, PropertyData propertyData) {
|
||||
return getGetter(cls, propertyData.getName(), propertyData.getAccessType());
|
||||
}
|
||||
|
||||
public static Getter getGetter(Class cls, String propertyName, String accessorType) {
|
||||
Pair<Class, String> key = make(cls, propertyName);
|
||||
Getter value = getterCache.get(key);
|
||||
if (value == null) {
|
||||
value = ReflectHelper.getGetter(cls, propertyName);
|
||||
value = getAccessor(accessorType).getGetter(cls, propertyName);
|
||||
// It's ok if two getters are generated concurrently
|
||||
getterCache.put(key, value);
|
||||
}
|
||||
|
@ -71,11 +74,15 @@ public class ReflectionTools {
|
|||
return value;
|
||||
}
|
||||
|
||||
public static Setter getSetter(Class cls, String propertyName) {
|
||||
public static Setter getSetter(Class cls, PropertyData propertyData) {
|
||||
return getSetter(cls, propertyData.getName(), propertyData.getAccessType());
|
||||
}
|
||||
|
||||
public static Setter getSetter(Class cls, String propertyName, String accessorType) {
|
||||
Pair<Class, String> key = make(cls, propertyName);
|
||||
Setter value = setterCache.get(key);
|
||||
if (value == null) {
|
||||
value = BASIC_PROPERTY_ACCESSOR.getSetter(cls, propertyName);
|
||||
value = getAccessor(accessorType).getSetter(cls, propertyName);
|
||||
// It's ok if two setters are generated concurrently
|
||||
setterCache.put(key, value);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* 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.accesstype;
|
||||
|
||||
import java.util.Arrays;
|
||||
import javax.persistence.EntityManager;
|
||||
|
||||
import org.hibernate.envers.test.AbstractEntityTest;
|
||||
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 FieldAccessType extends AbstractEntityTest {
|
||||
private Integer id1;
|
||||
|
||||
public void configure(Ejb3Configuration cfg) {
|
||||
cfg.addAnnotatedClass(FieldAccessTypeEntity.class);
|
||||
}
|
||||
|
||||
@BeforeClass(dependsOnMethods = "init")
|
||||
public void initData() {
|
||||
EntityManager em = getEntityManager();
|
||||
em.getTransaction().begin();
|
||||
FieldAccessTypeEntity fate = new FieldAccessTypeEntity("data");
|
||||
em.persist(fate);
|
||||
id1 = fate.readId();
|
||||
em.getTransaction().commit();
|
||||
|
||||
em.getTransaction().begin();
|
||||
fate = em.find(FieldAccessTypeEntity.class, id1);
|
||||
fate.writeData("data2");
|
||||
em.getTransaction().commit();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRevisionsCounts() {
|
||||
assert Arrays.asList(1, 2).equals(getVersionsReader().getRevisions(FieldAccessTypeEntity.class, id1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHistoryOfId1() {
|
||||
FieldAccessTypeEntity ver1 = new FieldAccessTypeEntity(id1, "data");
|
||||
FieldAccessTypeEntity ver2 = new FieldAccessTypeEntity(id1, "data2");
|
||||
|
||||
assert getVersionsReader().find(FieldAccessTypeEntity.class, id1, 1).equals(ver1);
|
||||
assert getVersionsReader().find(FieldAccessTypeEntity.class, id1, 2).equals(ver2);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,99 @@
|
|||
/*
|
||||
* 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.accesstype;
|
||||
|
||||
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 FieldAccessTypeEntity {
|
||||
@Id
|
||||
@GeneratedValue
|
||||
private Integer id;
|
||||
|
||||
@Audited
|
||||
private String data;
|
||||
|
||||
public FieldAccessTypeEntity() {
|
||||
}
|
||||
|
||||
public FieldAccessTypeEntity(String data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public FieldAccessTypeEntity(Integer id, String data) {
|
||||
this.id = id;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public Integer getId() {
|
||||
throw new RuntimeException();
|
||||
}
|
||||
|
||||
public void setId(Integer id) {
|
||||
throw new RuntimeException();
|
||||
}
|
||||
|
||||
public String getData() {
|
||||
throw new RuntimeException();
|
||||
}
|
||||
|
||||
public void setData(String data) {
|
||||
throw new RuntimeException();
|
||||
}
|
||||
|
||||
public Integer readId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void writeData(String data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof FieldAccessTypeEntity)) return false;
|
||||
|
||||
FieldAccessTypeEntity that = (FieldAccessTypeEntity) o;
|
||||
|
||||
if (data != null ? !data.equals(that.data) : that.data != null) return false;
|
||||
if (id != null ? !id.equals(that.id) : that.id != null) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
int result;
|
||||
result = (id != null ? id.hashCode() : 0);
|
||||
result = 31 * result + (data != null ? data.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,79 @@
|
|||
/*
|
||||
* 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.accesstype;
|
||||
|
||||
import java.util.Arrays;
|
||||
import javax.persistence.EntityManager;
|
||||
|
||||
import org.hibernate.envers.test.AbstractEntityTest;
|
||||
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 MixedAccessType extends AbstractEntityTest {
|
||||
private Integer id1;
|
||||
|
||||
public void configure(Ejb3Configuration cfg) {
|
||||
cfg.addAnnotatedClass(MixedAccessTypeEntity.class);
|
||||
}
|
||||
|
||||
@BeforeClass(dependsOnMethods = "init")
|
||||
public void initData() {
|
||||
EntityManager em = getEntityManager();
|
||||
em.getTransaction().begin();
|
||||
MixedAccessTypeEntity mate = new MixedAccessTypeEntity("data");
|
||||
em.persist(mate);
|
||||
id1 = mate.readId();
|
||||
em.getTransaction().commit();
|
||||
|
||||
em.getTransaction().begin();
|
||||
mate = em.find(MixedAccessTypeEntity.class, id1);
|
||||
mate.writeData("data2");
|
||||
em.getTransaction().commit();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRevisionsCounts() {
|
||||
assert Arrays.asList(1, 2).equals(getVersionsReader().getRevisions(MixedAccessTypeEntity.class, id1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHistoryOfId1() {
|
||||
MixedAccessTypeEntity ver1 = new MixedAccessTypeEntity(id1, "data");
|
||||
MixedAccessTypeEntity ver2 = new MixedAccessTypeEntity(id1, "data2");
|
||||
|
||||
MixedAccessTypeEntity rev1 = getVersionsReader().find(MixedAccessTypeEntity.class, id1, 1);
|
||||
MixedAccessTypeEntity rev2 = getVersionsReader().find(MixedAccessTypeEntity.class, id1, 2);
|
||||
|
||||
assert rev1.isDataSet();
|
||||
assert rev2.isDataSet();
|
||||
|
||||
assert rev1.equals(ver1);
|
||||
assert rev2.equals(ver2);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,111 @@
|
|||
/*
|
||||
* 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.accesstype;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Transient;
|
||||
|
||||
import org.hibernate.envers.Audited;
|
||||
import org.hibernate.annotations.AccessType;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
@Entity
|
||||
public class MixedAccessTypeEntity {
|
||||
@Id
|
||||
@GeneratedValue
|
||||
private Integer id;
|
||||
|
||||
@AccessType("property")
|
||||
private String data;
|
||||
|
||||
@Transient
|
||||
private boolean dataSet;
|
||||
|
||||
public MixedAccessTypeEntity() {
|
||||
}
|
||||
|
||||
public MixedAccessTypeEntity(String data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public MixedAccessTypeEntity(Integer id, String data) {
|
||||
this.id = id;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public Integer getId() {
|
||||
throw new RuntimeException();
|
||||
}
|
||||
|
||||
public void setId(Integer id) {
|
||||
throw new RuntimeException();
|
||||
}
|
||||
|
||||
// TODO: this should be on the property. But how to discover in AnnotationsMetadataReader that the
|
||||
// we should read annotations from fields, even though the access type is "property"?
|
||||
@Audited
|
||||
public String getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public void setData(String data) {
|
||||
this.data = data;
|
||||
dataSet = true;
|
||||
}
|
||||
|
||||
public boolean isDataSet() {
|
||||
return dataSet;
|
||||
}
|
||||
|
||||
public Integer readId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void writeData(String data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof MixedAccessTypeEntity)) return false;
|
||||
|
||||
MixedAccessTypeEntity that = (MixedAccessTypeEntity) o;
|
||||
|
||||
if (data != null ? !data.equals(that.data) : that.data != null) return false;
|
||||
if (id != null ? !id.equals(that.id) : that.id != null) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
int result;
|
||||
result = (id != null ? id.hashCode() : 0);
|
||||
result = 31 * result + (data != null ? data.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
* 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.accesstype;
|
||||
|
||||
import java.util.Arrays;
|
||||
import javax.persistence.EntityManager;
|
||||
|
||||
import org.hibernate.envers.test.AbstractEntityTest;
|
||||
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 PropertyAccessType extends AbstractEntityTest {
|
||||
private Integer id1;
|
||||
|
||||
public void configure(Ejb3Configuration cfg) {
|
||||
cfg.addAnnotatedClass(PropertyAccessTypeEntity.class);
|
||||
}
|
||||
|
||||
@BeforeClass(dependsOnMethods = "init")
|
||||
public void initData() {
|
||||
EntityManager em = getEntityManager();
|
||||
em.getTransaction().begin();
|
||||
PropertyAccessTypeEntity pate = new PropertyAccessTypeEntity("data");
|
||||
em.persist(pate);
|
||||
id1 = pate.getId();
|
||||
em.getTransaction().commit();
|
||||
|
||||
em.getTransaction().begin();
|
||||
pate = em.find(PropertyAccessTypeEntity.class, id1);
|
||||
pate.writeData("data2");
|
||||
em.getTransaction().commit();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRevisionsCounts() {
|
||||
assert Arrays.asList(1, 2).equals(getVersionsReader().getRevisions(PropertyAccessTypeEntity.class, id1));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHistoryOfId1() {
|
||||
PropertyAccessTypeEntity ver1 = new PropertyAccessTypeEntity(id1, "data");
|
||||
PropertyAccessTypeEntity ver2 = new PropertyAccessTypeEntity(id1, "data2");
|
||||
|
||||
PropertyAccessTypeEntity rev1 = getVersionsReader().find(PropertyAccessTypeEntity.class, id1, 1);
|
||||
PropertyAccessTypeEntity rev2 = getVersionsReader().find(PropertyAccessTypeEntity.class, id1, 2);
|
||||
|
||||
assert rev1.isIdSet();
|
||||
assert rev2.isIdSet();
|
||||
|
||||
assert rev1.isDataSet();
|
||||
assert rev2.isDataSet();
|
||||
|
||||
assert rev1.equals(ver1);
|
||||
assert rev2.equals(ver2);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,110 @@
|
|||
/*
|
||||
* 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.accesstype;
|
||||
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Transient;
|
||||
|
||||
import org.hibernate.envers.Audited;
|
||||
|
||||
/**
|
||||
* @author Adam Warski (adam at warski dot org)
|
||||
*/
|
||||
@Entity
|
||||
public class PropertyAccessTypeEntity {
|
||||
private Integer id;
|
||||
private String data;
|
||||
|
||||
private boolean idSet;
|
||||
private boolean dataSet;
|
||||
|
||||
public PropertyAccessTypeEntity() {
|
||||
}
|
||||
|
||||
public PropertyAccessTypeEntity(String data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public PropertyAccessTypeEntity(Integer id, String data) {
|
||||
this.id = id;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
@Id
|
||||
@GeneratedValue
|
||||
public Integer getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(Integer id) {
|
||||
this.id = id;
|
||||
idSet = true;
|
||||
}
|
||||
|
||||
@Audited
|
||||
public String getData() {
|
||||
return data;
|
||||
}
|
||||
|
||||
public void setData(String data) {
|
||||
this.data = data;
|
||||
dataSet = true;
|
||||
}
|
||||
|
||||
@Transient
|
||||
public boolean isIdSet() {
|
||||
return idSet;
|
||||
}
|
||||
|
||||
@Transient
|
||||
public boolean isDataSet() {
|
||||
return dataSet;
|
||||
}
|
||||
|
||||
public void writeData(String data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (!(o instanceof PropertyAccessTypeEntity)) return false;
|
||||
|
||||
PropertyAccessTypeEntity that = (PropertyAccessTypeEntity) o;
|
||||
|
||||
if (data != null ? !data.equals(that.data) : that.data != null) return false;
|
||||
if (id != null ? !id.equals(that.id) : that.id != null) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
int result;
|
||||
result = (id != null ? id.hashCode() : 0);
|
||||
result = 31 * result + (data != null ? data.hashCode() : 0);
|
||||
return result;
|
||||
}
|
||||
}
|
|
@ -17,6 +17,12 @@
|
|||
<property name="connection.username">sa</property>
|
||||
<property name="connection.password"></property>
|
||||
|
||||
<!--<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
|
||||
<property name="connection.url">jdbc:mysql:///hibernate_tests?useUnicode=true&characterEncoding=UTF-8</property>
|
||||
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
|
||||
<property name="connection.username">root</property>
|
||||
<property name="connection.password"></property>-->
|
||||
|
||||
<event type="post-insert">
|
||||
<listener class="org.hibernate.envers.event.VersionsEventListener" />
|
||||
</event>
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
<suite name="Envers">
|
||||
<test name="All">
|
||||
<packages>
|
||||
<package name="org.hibernate.envers.test.integration.accesstype" />
|
||||
<package name="org.hibernate.envers.test.integration.basic" />
|
||||
<package name="org.hibernate.envers.test.integration.cache" />
|
||||
<package name="org.hibernate.envers.test.integration.collection" />
|
||||
|
|
Loading…
Reference in New Issue