Merge pull request #112 from lukasz-antoniak/HHH-5917
HHH-5917 - Adding @Audited(auditedParents={classes})
This commit is contained in:
commit
9129cf38ce
|
@ -308,6 +308,14 @@
|
||||||
<literal>@Audited(targetAuditMode = RelationTargetAuditMode.NOT_AUDITED)</literal>. Then, when reading historic
|
<literal>@Audited(targetAuditMode = RelationTargetAuditMode.NOT_AUDITED)</literal>. Then, when reading historic
|
||||||
versions of your entity, the relation will always point to the "current" related entity.
|
versions of your entity, the relation will always point to the "current" related entity.
|
||||||
</para>
|
</para>
|
||||||
|
|
||||||
|
<para>
|
||||||
|
If you'd like to audit properties encapsulated by any subset of your entity's mapped superclasses (which are
|
||||||
|
not explicitly audited), list desired supertypes in <literal>auditParents</literal> attribute of
|
||||||
|
<interfacename>@Audited</interfacename> annotation. If any <interfacename>@MappedSuperclass</interfacename>
|
||||||
|
(or any of it's properties) is marked as <interfacename>@Audited</interfacename>, it's behavior is implicitly
|
||||||
|
inherited by all audited subclasses.
|
||||||
|
</para>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section>
|
<section>
|
||||||
|
|
|
@ -32,6 +32,7 @@ import java.lang.annotation.Target;
|
||||||
* When applied to a field, indicates that this field should be audited.
|
* When applied to a field, indicates that this field should be audited.
|
||||||
* @author Adam Warski (adam at warski dot org)
|
* @author Adam Warski (adam at warski dot org)
|
||||||
* @author Tomasz Bech
|
* @author Tomasz Bech
|
||||||
|
* @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com)
|
||||||
*/
|
*/
|
||||||
@Retention(RetentionPolicy.RUNTIME)
|
@Retention(RetentionPolicy.RUNTIME)
|
||||||
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD})
|
@Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD})
|
||||||
|
@ -44,4 +45,12 @@ public @interface Audited {
|
||||||
* This is useful for dictionary-like entities, which don't change and don't need to be audited.
|
* This is useful for dictionary-like entities, which don't change and don't need to be audited.
|
||||||
*/
|
*/
|
||||||
RelationTargetAuditMode targetAuditMode() default RelationTargetAuditMode.AUDITED;
|
RelationTargetAuditMode targetAuditMode() default RelationTargetAuditMode.AUDITED;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Set of superclasses which properties shall be audited. The behavior of listed classes
|
||||||
|
* is the same as if they had {@link Audited} annotation applied on a type level. The scope of this functionality
|
||||||
|
* is limited to the context of actually mapped entity and its class hierarchy. If a parent type lists any of
|
||||||
|
* its parent types using this attribute, all fields encapsulated by marked classes are implicitly audited.
|
||||||
|
*/
|
||||||
|
Class[] auditParents() default {};
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package org.hibernate.envers.configuration.metadata.reader;
|
package org.hibernate.envers.configuration.metadata.reader;
|
||||||
import static org.hibernate.envers.tools.Tools.newHashSet;
|
import static org.hibernate.envers.tools.Tools.newHashSet;
|
||||||
import java.lang.annotation.Annotation;
|
import java.lang.annotation.Annotation;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
@ -33,6 +34,7 @@ import org.hibernate.mapping.Value;
|
||||||
* @author Adam Warski (adam at warski dot org)
|
* @author Adam Warski (adam at warski dot org)
|
||||||
* @author Erik-Berndt Scheper
|
* @author Erik-Berndt Scheper
|
||||||
* @author Hern&aacut;n Chanfreau
|
* @author Hern&aacut;n Chanfreau
|
||||||
|
* @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com)
|
||||||
*/
|
*/
|
||||||
public class AuditedPropertiesReader {
|
public class AuditedPropertiesReader {
|
||||||
protected final ModificationStore defaultStore;
|
protected final ModificationStore defaultStore;
|
||||||
|
@ -66,8 +68,48 @@ public class AuditedPropertiesReader {
|
||||||
// First reading the access types for the persistent properties.
|
// First reading the access types for the persistent properties.
|
||||||
readPersistentPropertiesAccess();
|
readPersistentPropertiesAccess();
|
||||||
|
|
||||||
|
// Retrieve classes that are explicitly marked for auditing process by any superclass of currently mapped
|
||||||
|
// entity or itself.
|
||||||
|
XClass clazz = persistentPropertiesSource.getXClass();
|
||||||
|
Set<XClass> declaredAuditedSuperclasses = new HashSet<XClass>();
|
||||||
|
doGetDeclaredAuditedSuperclasses(clazz, declaredAuditedSuperclasses);
|
||||||
|
|
||||||
// Adding all properties from the given class.
|
// Adding all properties from the given class.
|
||||||
addPropertiesFromClass(persistentPropertiesSource.getXClass());
|
addPropertiesFromClass(clazz, declaredAuditedSuperclasses);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Recursively constructs a set of classes that have been declared for auditing process.
|
||||||
|
* @param clazz Class that is being processed. Currently mapped entity shall be passed during first invocation.
|
||||||
|
* @param declaredAuditedSuperclasses Total collection of classes listed in {@link Audited#auditParents()} property
|
||||||
|
* by any superclass starting with class specified as the first argument.
|
||||||
|
*/
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
private void doGetDeclaredAuditedSuperclasses(XClass clazz, Set<XClass> declaredAuditedSuperclasses) {
|
||||||
|
Audited allClassAudited = clazz.getAnnotation(Audited.class);
|
||||||
|
if (allClassAudited != null && allClassAudited.auditParents().length > 0) {
|
||||||
|
for (Class c : allClassAudited.auditParents()) {
|
||||||
|
XClass parentClass = reflectionManager.toXClass(c);
|
||||||
|
checkSuperclass(clazz, parentClass);
|
||||||
|
declaredAuditedSuperclasses.add(parentClass);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
XClass superclass = clazz.getSuperclass();
|
||||||
|
if (!clazz.isInterface() && !Object.class.getName().equals(superclass.getName())) {
|
||||||
|
doGetDeclaredAuditedSuperclasses(superclass, declaredAuditedSuperclasses);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether one class is assignable from another. If not {@link MappingException} is thrown.
|
||||||
|
* @param child Subclass.
|
||||||
|
* @param parent Superclass.
|
||||||
|
*/
|
||||||
|
private void checkSuperclass(XClass child, XClass parent) {
|
||||||
|
if (!parent.isAssignableFrom(child)) {
|
||||||
|
throw new MappingException("Class " + parent.getName() + " is not assignable from " + child.getName() + ". " +
|
||||||
|
"Please revise @Audited.auditParents value in " + child.getName() + " type.");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void readPersistentPropertiesAccess() {
|
private void readPersistentPropertiesAccess() {
|
||||||
|
@ -82,8 +124,34 @@ public class AuditedPropertiesReader {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addPropertiesFromClass(XClass clazz) {
|
/**
|
||||||
|
* @param clazz Class which properties are currently being added.
|
||||||
|
* @param declaredAuditedSuperclasses Collection of superclasses that have been explicitly declared to be audited.
|
||||||
|
* @return {@link Audited} annotation of specified class. If processed type hasn't been explicitly marked, method
|
||||||
|
* checks whether given class exists in collection passed as the second argument. In case of success,
|
||||||
|
* {@link Audited} configuration of currently mapped entity is returned, otherwise {@code null}.
|
||||||
|
*/
|
||||||
|
private Audited computeAuditConfiguration(XClass clazz, Set<XClass> declaredAuditedSuperclasses) {
|
||||||
Audited allClassAudited = clazz.getAnnotation(Audited.class);
|
Audited allClassAudited = clazz.getAnnotation(Audited.class);
|
||||||
|
// If processed class is not explicitly marked with @Audited annotation, check whether auditing is
|
||||||
|
// forced by any of its child entities configuration (@Audited.auditParents).
|
||||||
|
if (allClassAudited == null && declaredAuditedSuperclasses.contains(clazz)) {
|
||||||
|
// Declared audited parent copies @Audited.modStore and @Audited.targetAuditMode configuration from
|
||||||
|
// currently mapped entity.
|
||||||
|
allClassAudited = persistentPropertiesSource.getXClass().getAnnotation(Audited.class);
|
||||||
|
}
|
||||||
|
return allClassAudited;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Recursively adds all audited properties of entity class and its superclasses.
|
||||||
|
* @param clazz Currently processed class.
|
||||||
|
* @param declaredAuditedSuperclasses Collection of classes that are declared to be audited
|
||||||
|
* (see {@link Audited#auditParents()}).
|
||||||
|
*/
|
||||||
|
private void addPropertiesFromClass(XClass clazz, Set<XClass> declaredAuditedSuperclasses) {
|
||||||
|
Audited allClassAudited = computeAuditConfiguration(clazz, declaredAuditedSuperclasses);
|
||||||
|
|
||||||
//look in the class
|
//look in the class
|
||||||
addFromProperties(clazz.getDeclaredProperties("field"), "field", fieldAccessedPersistentProperties, allClassAudited);
|
addFromProperties(clazz.getDeclaredProperties("field"), "field", fieldAccessedPersistentProperties, allClassAudited);
|
||||||
addFromProperties(clazz.getDeclaredProperties("property"), "property", propertyAccessedPersistentProperties, allClassAudited);
|
addFromProperties(clazz.getDeclaredProperties("property"), "property", propertyAccessedPersistentProperties, allClassAudited);
|
||||||
|
@ -91,7 +159,7 @@ public class AuditedPropertiesReader {
|
||||||
if(allClassAudited != null || !auditedPropertiesHolder.isEmpty()) {
|
if(allClassAudited != null || !auditedPropertiesHolder.isEmpty()) {
|
||||||
XClass superclazz = clazz.getSuperclass();
|
XClass superclazz = clazz.getSuperclass();
|
||||||
if (!clazz.isInterface() && !"java.lang.Object".equals(superclazz.getName())) {
|
if (!clazz.isInterface() && !"java.lang.Object".equals(superclazz.getName())) {
|
||||||
addPropertiesFromClass(superclazz);
|
addPropertiesFromClass(superclazz, declaredAuditedSuperclasses);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,53 @@
|
||||||
|
package org.hibernate.envers.test.integration.superclass.auditparents;
|
||||||
|
|
||||||
|
import org.hibernate.envers.Audited;
|
||||||
|
import org.hibernate.envers.test.entities.StrIntTestEntity;
|
||||||
|
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com)
|
||||||
|
*/
|
||||||
|
@Entity
|
||||||
|
@Audited(auditParents = {MappedParentEntity.class})
|
||||||
|
public class BabyCompleteEntity extends ChildCompleteEntity {
|
||||||
|
private String baby;
|
||||||
|
|
||||||
|
public BabyCompleteEntity() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public BabyCompleteEntity(Long id, String grandparent, String notAudited, String parent, String child, StrIntTestEntity relation, String baby) {
|
||||||
|
super(id, grandparent, notAudited, parent, child, relation);
|
||||||
|
this.baby = baby;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (!(o instanceof BabyCompleteEntity)) return false;
|
||||||
|
if (!super.equals(o)) return false;
|
||||||
|
|
||||||
|
BabyCompleteEntity that = (BabyCompleteEntity) o;
|
||||||
|
|
||||||
|
if (baby != null ? !baby.equals(that.baby) : that.baby != null) return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int hashCode() {
|
||||||
|
int result = super.hashCode();
|
||||||
|
result = 31 * result + (baby != null ? baby.hashCode() : 0);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return "BabyCompleteEntity(" + super.toString() + ", baby = " + baby + ")";
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getBaby() {
|
||||||
|
return baby;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBaby(String baby) {
|
||||||
|
this.baby = baby;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
package org.hibernate.envers.test.integration.superclass.auditparents;
|
||||||
|
|
||||||
|
import org.hibernate.envers.Audited;
|
||||||
|
import org.hibernate.envers.test.entities.StrIntTestEntity;
|
||||||
|
|
||||||
|
import javax.persistence.MappedSuperclass;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com)
|
||||||
|
*/
|
||||||
|
@MappedSuperclass
|
||||||
|
@Audited(auditParents = {MappedGrandparentEntity.class})
|
||||||
|
public class ChildCompleteEntity extends MappedParentEntity {
|
||||||
|
private String child;
|
||||||
|
|
||||||
|
public ChildCompleteEntity() {
|
||||||
|
super(null, null, null, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ChildCompleteEntity(Long id, String grandparent, String notAudited, String parent, String child, StrIntTestEntity relation) {
|
||||||
|
super(id, grandparent, notAudited, parent, relation);
|
||||||
|
this.child = child;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (!(o instanceof ChildCompleteEntity)) return false;
|
||||||
|
if (!super.equals(o)) return false;
|
||||||
|
|
||||||
|
ChildCompleteEntity that = (ChildCompleteEntity) o;
|
||||||
|
|
||||||
|
if (child != null ? !child.equals(that.child) : that.child != null) return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int hashCode() {
|
||||||
|
int result = super.hashCode();
|
||||||
|
result = 31 * result + (child != null ? child.hashCode() : 0);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return "ChildCompleteEntity(" + super.toString() + ", child = " + child + ")";
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getChild() {
|
||||||
|
return child;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setChild(String child) {
|
||||||
|
this.child = child;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,55 @@
|
||||||
|
package org.hibernate.envers.test.integration.superclass.auditparents;
|
||||||
|
|
||||||
|
import org.hibernate.envers.Audited;
|
||||||
|
import org.hibernate.envers.test.entities.StrIntTestEntity;
|
||||||
|
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com)
|
||||||
|
*/
|
||||||
|
@Entity
|
||||||
|
@Audited(auditParents = {MappedParentEntity.class, MappedGrandparentEntity.class})
|
||||||
|
public class ChildMultipleParentsEntity extends MappedParentEntity {
|
||||||
|
private String child;
|
||||||
|
|
||||||
|
public ChildMultipleParentsEntity() {
|
||||||
|
super(null, null, null, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ChildMultipleParentsEntity(Long id, String grandparent, String notAudited, String parent, String child, StrIntTestEntity relation) {
|
||||||
|
super(id, grandparent, notAudited, parent, relation);
|
||||||
|
this.child = child;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (!(o instanceof ChildMultipleParentsEntity)) return false;
|
||||||
|
if (!super.equals(o)) return false;
|
||||||
|
|
||||||
|
ChildMultipleParentsEntity that = (ChildMultipleParentsEntity) o;
|
||||||
|
|
||||||
|
if (child != null ? !child.equals(that.child) : that.child != null) return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int hashCode() {
|
||||||
|
int result = super.hashCode();
|
||||||
|
result = 31 * result + (child != null ? child.hashCode() : 0);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return "ChildMultipleParentsEntity(" + super.toString() + ", child = " + child + ")";
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getChild() {
|
||||||
|
return child;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setChild(String child) {
|
||||||
|
this.child = child;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
package org.hibernate.envers.test.integration.superclass.auditparents;
|
||||||
|
|
||||||
|
import org.hibernate.envers.Audited;
|
||||||
|
import org.hibernate.envers.test.entities.StrIntTestEntity;
|
||||||
|
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com)
|
||||||
|
*/
|
||||||
|
@Entity
|
||||||
|
@Audited(auditParents = {MappedGrandparentEntity.class})
|
||||||
|
public class ChildSingleParentEntity extends MappedParentEntity {
|
||||||
|
private String child;
|
||||||
|
|
||||||
|
public ChildSingleParentEntity() {
|
||||||
|
super(null, null, null, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ChildSingleParentEntity(Long id, String grandparent, String notAudited, String parent, String child, StrIntTestEntity relation) {
|
||||||
|
super(id, grandparent, notAudited, parent, relation);
|
||||||
|
this.child = child;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (!(o instanceof ChildSingleParentEntity)) return false;
|
||||||
|
if (!super.equals(o)) return false;
|
||||||
|
|
||||||
|
ChildSingleParentEntity that = (ChildSingleParentEntity) o;
|
||||||
|
|
||||||
|
if (child != null ? !child.equals(that.child) : that.child != null) return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int hashCode() {
|
||||||
|
int result = super.hashCode();
|
||||||
|
result = 31 * result + (child != null ? child.hashCode() : 0);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return "ChildSingleParentEntity(" + super.toString() + ", child = " + child + ")";
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getChild() {
|
||||||
|
return child;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setChild(String child) {
|
||||||
|
this.child = child;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,53 @@
|
||||||
|
package org.hibernate.envers.test.integration.superclass.auditparents;
|
||||||
|
|
||||||
|
import org.hibernate.envers.Audited;
|
||||||
|
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com)
|
||||||
|
*/
|
||||||
|
@Entity
|
||||||
|
@Audited(auditParents = {TransitiveParentEntity.class})
|
||||||
|
public class ExplicitTransitiveChildEntity extends TransitiveParentEntity {
|
||||||
|
private String child;
|
||||||
|
|
||||||
|
public ExplicitTransitiveChildEntity() {
|
||||||
|
super(null, null, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ExplicitTransitiveChildEntity(Long id, String grandparent, String notAudited, String parent, String child) {
|
||||||
|
super(id, grandparent, notAudited, parent);
|
||||||
|
this.child = child;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (!(o instanceof ExplicitTransitiveChildEntity)) return false;
|
||||||
|
if (!super.equals(o)) return false;
|
||||||
|
|
||||||
|
ExplicitTransitiveChildEntity that = (ExplicitTransitiveChildEntity) o;
|
||||||
|
|
||||||
|
if (child != null ? !child.equals(that.child) : that.child != null) return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int hashCode() {
|
||||||
|
int result = super.hashCode();
|
||||||
|
result = 31 * result + (child != null ? child.hashCode() : 0);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return "ExplicitTransitiveChildEntity(" + super.toString() + ", child = " + child + ")";
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getChild() {
|
||||||
|
return child;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setChild(String child) {
|
||||||
|
this.child = child;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,53 @@
|
||||||
|
package org.hibernate.envers.test.integration.superclass.auditparents;
|
||||||
|
|
||||||
|
import org.hibernate.envers.Audited;
|
||||||
|
|
||||||
|
import javax.persistence.Entity;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com)
|
||||||
|
*/
|
||||||
|
@Entity
|
||||||
|
@Audited
|
||||||
|
public class ImplicitTransitiveChildEntity extends TransitiveParentEntity {
|
||||||
|
private String child;
|
||||||
|
|
||||||
|
public ImplicitTransitiveChildEntity() {
|
||||||
|
super(null, null, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ImplicitTransitiveChildEntity(Long id, String grandparent, String notAudited, String parent, String child) {
|
||||||
|
super(id, grandparent, notAudited, parent);
|
||||||
|
this.child = child;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (!(o instanceof ImplicitTransitiveChildEntity)) return false;
|
||||||
|
if (!super.equals(o)) return false;
|
||||||
|
|
||||||
|
ImplicitTransitiveChildEntity that = (ImplicitTransitiveChildEntity) o;
|
||||||
|
|
||||||
|
if (child != null ? !child.equals(that.child) : that.child != null) return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int hashCode() {
|
||||||
|
int result = super.hashCode();
|
||||||
|
result = 31 * result + (child != null ? child.hashCode() : 0);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return "ImplicitTransitiveChildEntity(" + super.toString() + ", child = " + child + ")";
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getChild() {
|
||||||
|
return child;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setChild(String child) {
|
||||||
|
this.child = child;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,74 @@
|
||||||
|
package org.hibernate.envers.test.integration.superclass.auditparents;
|
||||||
|
|
||||||
|
import org.hibernate.envers.NotAudited;
|
||||||
|
|
||||||
|
import javax.persistence.Id;
|
||||||
|
import javax.persistence.MappedSuperclass;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com)
|
||||||
|
*/
|
||||||
|
@MappedSuperclass
|
||||||
|
public class MappedGrandparentEntity {
|
||||||
|
@Id
|
||||||
|
private Long id;
|
||||||
|
|
||||||
|
private String grandparent;
|
||||||
|
|
||||||
|
@NotAudited
|
||||||
|
private String notAudited;
|
||||||
|
|
||||||
|
public MappedGrandparentEntity(Long id, String grandparent, String notAudited) {
|
||||||
|
this.id = id;
|
||||||
|
this.grandparent = grandparent;
|
||||||
|
this.notAudited = notAudited;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (!(o instanceof MappedGrandparentEntity)) return false;
|
||||||
|
|
||||||
|
MappedGrandparentEntity that = (MappedGrandparentEntity) o;
|
||||||
|
|
||||||
|
if (id != null ? !id.equals(that.id) : that.id != null) return false;
|
||||||
|
if (grandparent != null ? !grandparent.equals(that.grandparent) : that.grandparent != null) return false;
|
||||||
|
if (notAudited != null ? !notAudited.equals(that.notAudited) : that.notAudited != null) return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int hashCode() {
|
||||||
|
int result = (id != null ? id.hashCode() : 0);
|
||||||
|
result = 31 * result + (grandparent != null ? grandparent.hashCode() : 0);
|
||||||
|
result = 31 * result + (notAudited != null ? notAudited.hashCode() : 0);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return "MappedGrandparentEntity(id = " + id + ", grandparent = " + grandparent + ", notAudited = " + notAudited + ")";
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setId(Long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getGrandparent() {
|
||||||
|
return grandparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGrandparent(String grandparent) {
|
||||||
|
this.grandparent = grandparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getNotAudited() {
|
||||||
|
return notAudited;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setNotAudited(String notAudited) {
|
||||||
|
this.notAudited = notAudited;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,61 @@
|
||||||
|
package org.hibernate.envers.test.integration.superclass.auditparents;
|
||||||
|
|
||||||
|
import org.hibernate.envers.test.entities.StrIntTestEntity;
|
||||||
|
|
||||||
|
import javax.persistence.ManyToOne;
|
||||||
|
import javax.persistence.MappedSuperclass;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com)
|
||||||
|
*/
|
||||||
|
@MappedSuperclass
|
||||||
|
public class MappedParentEntity extends MappedGrandparentEntity {
|
||||||
|
private String parent;
|
||||||
|
|
||||||
|
@ManyToOne
|
||||||
|
private StrIntTestEntity relation;
|
||||||
|
|
||||||
|
public MappedParentEntity(Long id, String grandparent, String notAudited, String parent, StrIntTestEntity relation) {
|
||||||
|
super(id, grandparent, notAudited);
|
||||||
|
this.parent = parent;
|
||||||
|
this.relation = relation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (!(o instanceof MappedParentEntity)) return false;
|
||||||
|
if (!super.equals(o)) return false;
|
||||||
|
|
||||||
|
MappedParentEntity that = (MappedParentEntity) o;
|
||||||
|
|
||||||
|
if (parent != null ? !parent.equals(that.parent) : that.parent != null) return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int hashCode() {
|
||||||
|
int result = super.hashCode();
|
||||||
|
result = 31 * result + (parent != null ? parent.hashCode() : 0);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return "MappedParentEntity(" + super.toString() + ", parent = " + parent + ", relation = " + relation + ")";
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getParent() {
|
||||||
|
return parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setParent(String parent) {
|
||||||
|
this.parent = parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public StrIntTestEntity getRelation() {
|
||||||
|
return relation;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRelation(StrIntTestEntity relation) {
|
||||||
|
this.relation = relation;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,73 @@
|
||||||
|
package org.hibernate.envers.test.integration.superclass.auditparents;
|
||||||
|
|
||||||
|
import org.hibernate.ejb.Ejb3Configuration;
|
||||||
|
import org.hibernate.envers.Audited;
|
||||||
|
import org.hibernate.envers.test.AbstractEntityTest;
|
||||||
|
import org.hibernate.envers.test.Priority;
|
||||||
|
import org.hibernate.envers.test.entities.StrIntTestEntity;
|
||||||
|
import org.hibernate.envers.test.tools.TestTools;
|
||||||
|
import org.hibernate.mapping.Column;
|
||||||
|
import org.hibernate.mapping.Table;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import javax.persistence.EntityManager;
|
||||||
|
import javax.persistence.MappedSuperclass;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests mapping of child entity that declares all of its ancestors as audited with {@link Audited#auditParents()} property.
|
||||||
|
* All supperclasses are marked with {@link MappedSuperclass} annotation but not {@link Audited}.
|
||||||
|
* @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com)
|
||||||
|
*/
|
||||||
|
public class MultipleAuditParentsTest extends AbstractEntityTest {
|
||||||
|
private long childMultipleId = 1L;
|
||||||
|
private Integer siteMultipleId = null;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void configure(Ejb3Configuration cfg) {
|
||||||
|
cfg.addAnnotatedClass(MappedGrandparentEntity.class);
|
||||||
|
cfg.addAnnotatedClass(MappedParentEntity.class);
|
||||||
|
cfg.addAnnotatedClass(ChildMultipleParentsEntity.class);
|
||||||
|
cfg.addAnnotatedClass(StrIntTestEntity.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Priority(10)
|
||||||
|
public void initData() {
|
||||||
|
EntityManager em = getEntityManager();
|
||||||
|
// Revision 1
|
||||||
|
em.getTransaction().begin();
|
||||||
|
StrIntTestEntity siteMultiple = new StrIntTestEntity("data 1", 1);
|
||||||
|
em.persist(siteMultiple);
|
||||||
|
em.persist(new ChildMultipleParentsEntity(childMultipleId, "grandparent 1", "notAudited 1", "parent 1", "child 1", siteMultiple));
|
||||||
|
em.getTransaction().commit();
|
||||||
|
siteMultipleId = siteMultiple.getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCreatedAuditTable() {
|
||||||
|
Set<String> expectedColumns = TestTools.makeSet("child", "parent", "relation_id", "grandparent", "id");
|
||||||
|
Set<String> unexpectedColumns = TestTools.makeSet("notAudited");
|
||||||
|
|
||||||
|
Table table = getCfg().getClassMapping("org.hibernate.envers.test.integration.superclass.auditparents.ChildMultipleParentsEntity_AUD").getTable();
|
||||||
|
|
||||||
|
for (String columnName : expectedColumns) {
|
||||||
|
// Check whether expected column exists.
|
||||||
|
Assert.assertNotNull(table.getColumn(new Column(columnName)));
|
||||||
|
}
|
||||||
|
for (String columnName : unexpectedColumns) {
|
||||||
|
// Check whether unexpected column does not exist.
|
||||||
|
Assert.assertNull(table.getColumn(new Column(columnName)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testMultipleAuditParents() {
|
||||||
|
// expectedMultipleChild.notAudited shall be null, because it is not audited.
|
||||||
|
ChildMultipleParentsEntity expectedMultipleChild = new ChildMultipleParentsEntity(childMultipleId, "grandparent 1", null, "parent 1", "child 1", new StrIntTestEntity("data 1", 1, siteMultipleId));
|
||||||
|
ChildMultipleParentsEntity child = getAuditReader().find(ChildMultipleParentsEntity.class, childMultipleId, 1);
|
||||||
|
Assert.assertEquals(expectedMultipleChild, child);
|
||||||
|
Assert.assertEquals(expectedMultipleChild.getRelation().getId(), child.getRelation().getId());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,73 @@
|
||||||
|
package org.hibernate.envers.test.integration.superclass.auditparents;
|
||||||
|
|
||||||
|
import org.hibernate.ejb.Ejb3Configuration;
|
||||||
|
import org.hibernate.envers.Audited;
|
||||||
|
import org.hibernate.envers.test.AbstractEntityTest;
|
||||||
|
import org.hibernate.envers.test.Priority;
|
||||||
|
import org.hibernate.envers.test.entities.StrIntTestEntity;
|
||||||
|
import org.hibernate.envers.test.tools.TestTools;
|
||||||
|
import org.hibernate.mapping.Column;
|
||||||
|
import org.hibernate.mapping.Table;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import javax.persistence.EntityManager;
|
||||||
|
import javax.persistence.MappedSuperclass;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests mapping of child entity that declares one of its ancestors as audited with {@link Audited#auditParents()} property.
|
||||||
|
* All supperclasses are marked with {@link MappedSuperclass} annotation but not {@link Audited}.
|
||||||
|
* @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com)
|
||||||
|
*/
|
||||||
|
public class SingleAuditParentsTest extends AbstractEntityTest {
|
||||||
|
private long childSingleId = 1L;
|
||||||
|
private Integer siteSingleId = null;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void configure(Ejb3Configuration cfg) {
|
||||||
|
cfg.addAnnotatedClass(MappedGrandparentEntity.class);
|
||||||
|
cfg.addAnnotatedClass(MappedParentEntity.class);
|
||||||
|
cfg.addAnnotatedClass(ChildSingleParentEntity.class);
|
||||||
|
cfg.addAnnotatedClass(StrIntTestEntity.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Priority(10)
|
||||||
|
public void initData() {
|
||||||
|
EntityManager em = getEntityManager();
|
||||||
|
// Revision 1
|
||||||
|
em.getTransaction().begin();
|
||||||
|
StrIntTestEntity siteSingle = new StrIntTestEntity("data 1", 1);
|
||||||
|
em.persist(siteSingle);
|
||||||
|
em.persist(new ChildSingleParentEntity(childSingleId, "grandparent 1", "notAudited 1", "parent 1", "child 1", siteSingle));
|
||||||
|
em.getTransaction().commit();
|
||||||
|
siteSingleId = siteSingle.getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCreatedAuditTable() {
|
||||||
|
Set<String> expectedColumns = TestTools.makeSet("child", "grandparent", "id");
|
||||||
|
Set<String> unexpectedColumns = TestTools.makeSet("parent", "relation_id", "notAudited");
|
||||||
|
|
||||||
|
Table table = getCfg().getClassMapping("org.hibernate.envers.test.integration.superclass.auditparents.ChildSingleParentEntity_AUD").getTable();
|
||||||
|
|
||||||
|
for (String columnName : expectedColumns) {
|
||||||
|
// Check whether expected column exists.
|
||||||
|
Assert.assertNotNull(table.getColumn(new Column(columnName)));
|
||||||
|
}
|
||||||
|
for (String columnName : unexpectedColumns) {
|
||||||
|
// Check whether unexpected column does not exist.
|
||||||
|
Assert.assertNull(table.getColumn(new Column(columnName)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSingleAuditParent() {
|
||||||
|
// expectedSingleChild.parent, expectedSingleChild.relation and expectedSingleChild.notAudited shall be null, because they are not audited.
|
||||||
|
ChildSingleParentEntity expectedSingleChild = new ChildSingleParentEntity(childSingleId, "grandparent 1", null, null, "child 1", null);
|
||||||
|
ChildSingleParentEntity child = getAuditReader().find(ChildSingleParentEntity.class, childSingleId, 1);
|
||||||
|
Assert.assertEquals(expectedSingleChild, child);
|
||||||
|
Assert.assertNull(child.getRelation());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,74 @@
|
||||||
|
package org.hibernate.envers.test.integration.superclass.auditparents;
|
||||||
|
|
||||||
|
import org.hibernate.ejb.Ejb3Configuration;
|
||||||
|
import org.hibernate.envers.Audited;
|
||||||
|
import org.hibernate.envers.test.AbstractEntityTest;
|
||||||
|
import org.hibernate.envers.test.Priority;
|
||||||
|
import org.hibernate.envers.test.entities.StrIntTestEntity;
|
||||||
|
import org.hibernate.envers.test.tools.TestTools;
|
||||||
|
import org.hibernate.mapping.Column;
|
||||||
|
import org.hibernate.mapping.Table;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import javax.persistence.EntityManager;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests mapping of baby entity which declares its parent as audited with {@link Audited#auditParents()} property.
|
||||||
|
* Moreover, child class (mapped superclass of baby entity) declares grandparent entity as audited. In this case all
|
||||||
|
* attributes of baby class shall be audited.
|
||||||
|
* @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com)
|
||||||
|
*/
|
||||||
|
public class TotalAuditParentsTest extends AbstractEntityTest {
|
||||||
|
private long babyCompleteId = 1L;
|
||||||
|
private Integer siteCompleteId = null;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void configure(Ejb3Configuration cfg) {
|
||||||
|
cfg.addAnnotatedClass(MappedGrandparentEntity.class);
|
||||||
|
cfg.addAnnotatedClass(MappedParentEntity.class);
|
||||||
|
cfg.addAnnotatedClass(StrIntTestEntity.class);
|
||||||
|
cfg.addAnnotatedClass(ChildCompleteEntity.class);
|
||||||
|
cfg.addAnnotatedClass(BabyCompleteEntity.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Priority(10)
|
||||||
|
public void initData() {
|
||||||
|
EntityManager em = getEntityManager();
|
||||||
|
// Revision 1
|
||||||
|
em.getTransaction().begin();
|
||||||
|
StrIntTestEntity siteComplete = new StrIntTestEntity("data 1", 1);
|
||||||
|
em.persist(siteComplete);
|
||||||
|
em.persist(new BabyCompleteEntity(babyCompleteId, "grandparent 1", "notAudited 1", "parent 1", "child 1", siteComplete, "baby 1"));
|
||||||
|
em.getTransaction().commit();
|
||||||
|
siteCompleteId = siteComplete.getId();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCreatedAuditTable() {
|
||||||
|
Set<String> expectedColumns = TestTools.makeSet("baby", "child", "parent", "relation_id", "grandparent", "id");
|
||||||
|
Set<String> unexpectedColumns = TestTools.makeSet("notAudited");
|
||||||
|
|
||||||
|
Table table = getCfg().getClassMapping("org.hibernate.envers.test.integration.superclass.auditparents.BabyCompleteEntity_AUD").getTable();
|
||||||
|
|
||||||
|
for (String columnName : expectedColumns) {
|
||||||
|
// Check whether expected column exists.
|
||||||
|
Assert.assertNotNull(table.getColumn(new Column(columnName)));
|
||||||
|
}
|
||||||
|
for (String columnName : unexpectedColumns) {
|
||||||
|
// Check whether unexpected column does not exist.
|
||||||
|
Assert.assertNull(table.getColumn(new Column(columnName)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCompleteAuditParents() {
|
||||||
|
// expectedBaby.notAudited shall be null, because it is not audited.
|
||||||
|
BabyCompleteEntity expectedBaby = new BabyCompleteEntity(babyCompleteId, "grandparent 1", null, "parent 1", "child 1", new StrIntTestEntity("data 1", 1, siteCompleteId), "baby 1");
|
||||||
|
BabyCompleteEntity baby = getAuditReader().find(BabyCompleteEntity.class, babyCompleteId, 1);
|
||||||
|
Assert.assertEquals(expectedBaby, baby);
|
||||||
|
Assert.assertEquals(expectedBaby.getRelation().getId(), baby.getRelation().getId());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,84 @@
|
||||||
|
package org.hibernate.envers.test.integration.superclass.auditparents;
|
||||||
|
|
||||||
|
import org.hibernate.ejb.Ejb3Configuration;
|
||||||
|
import org.hibernate.envers.Audited;
|
||||||
|
import org.hibernate.envers.test.AbstractEntityTest;
|
||||||
|
import org.hibernate.envers.test.Priority;
|
||||||
|
import org.hibernate.envers.test.tools.TestTools;
|
||||||
|
import org.hibernate.mapping.Column;
|
||||||
|
import org.hibernate.mapping.Table;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import javax.persistence.EntityManager;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests mapping of child entity which parent declares one of its ancestors as audited with {@link Audited#auditParents()}
|
||||||
|
* property. Child entity may mark explicitly its parent as audited or not.
|
||||||
|
* @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com)
|
||||||
|
*/
|
||||||
|
public class TransitiveAuditParentsTest extends AbstractEntityTest {
|
||||||
|
private long childImpTransId = 1L;
|
||||||
|
private long childExpTransId = 2L;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void configure(Ejb3Configuration cfg) {
|
||||||
|
cfg.addAnnotatedClass(MappedGrandparentEntity.class);
|
||||||
|
cfg.addAnnotatedClass(TransitiveParentEntity.class);
|
||||||
|
cfg.addAnnotatedClass(ImplicitTransitiveChildEntity.class);
|
||||||
|
cfg.addAnnotatedClass(ExplicitTransitiveChildEntity.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
@Priority(10)
|
||||||
|
public void initData() {
|
||||||
|
EntityManager em = getEntityManager();
|
||||||
|
|
||||||
|
// Revision 1
|
||||||
|
em.getTransaction().begin();
|
||||||
|
em.persist(new ImplicitTransitiveChildEntity(childImpTransId, "grandparent 1", "notAudited 1", "parent 1", "child 1"));
|
||||||
|
em.getTransaction().commit();
|
||||||
|
|
||||||
|
// Revision 2
|
||||||
|
em.getTransaction().begin();
|
||||||
|
em.persist(new ExplicitTransitiveChildEntity(childExpTransId, "grandparent 2", "notAudited 2", "parent 2", "child 2"));
|
||||||
|
em.getTransaction().commit();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testCreatedAuditTables() {
|
||||||
|
Table explicitTransChildTable = getCfg().getClassMapping("org.hibernate.envers.test.integration.superclass.auditparents.ExplicitTransitiveChildEntity_AUD").getTable();
|
||||||
|
checkTableColumns(TestTools.makeSet("child", "parent", "grandparent", "id"), TestTools.makeSet("notAudited"), explicitTransChildTable);
|
||||||
|
|
||||||
|
Table implicitTransChildTable = getCfg().getClassMapping("org.hibernate.envers.test.integration.superclass.auditparents.ImplicitTransitiveChildEntity_AUD").getTable();
|
||||||
|
checkTableColumns(TestTools.makeSet("child", "parent", "grandparent", "id"), TestTools.makeSet("notAudited"), implicitTransChildTable);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void checkTableColumns(Set<String> expectedColumns, Set<String> unexpectedColumns, Table table) {
|
||||||
|
for (String columnName : expectedColumns) {
|
||||||
|
// Check whether expected column exists.
|
||||||
|
Assert.assertNotNull(table.getColumn(new Column(columnName)));
|
||||||
|
}
|
||||||
|
for (String columnName : unexpectedColumns) {
|
||||||
|
// Check whether unexpected column does not exist.
|
||||||
|
Assert.assertNull(table.getColumn(new Column(columnName)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testImplicitTransitiveAuditParents() {
|
||||||
|
// expectedChild.notAudited shall be null, because it is not audited.
|
||||||
|
ImplicitTransitiveChildEntity expectedChild = new ImplicitTransitiveChildEntity(childImpTransId, "grandparent 1", null, "parent 1", "child 1");
|
||||||
|
ImplicitTransitiveChildEntity child = getAuditReader().find(ImplicitTransitiveChildEntity.class, childImpTransId, 1);
|
||||||
|
Assert.assertEquals(expectedChild, child);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testExplicitTransitiveAuditParents() {
|
||||||
|
// expectedChild.notAudited shall be null, because it is not audited.
|
||||||
|
ExplicitTransitiveChildEntity expectedChild = new ExplicitTransitiveChildEntity(childExpTransId, "grandparent 2", null, "parent 2", "child 2");
|
||||||
|
ExplicitTransitiveChildEntity child = getAuditReader().find(ExplicitTransitiveChildEntity.class, childExpTransId, 2);
|
||||||
|
Assert.assertEquals(expectedChild, child);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,53 @@
|
||||||
|
package org.hibernate.envers.test.integration.superclass.auditparents;
|
||||||
|
|
||||||
|
import org.hibernate.envers.Audited;
|
||||||
|
|
||||||
|
import javax.persistence.MappedSuperclass;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com)
|
||||||
|
*/
|
||||||
|
@MappedSuperclass
|
||||||
|
@Audited(auditParents = {MappedGrandparentEntity.class})
|
||||||
|
public class TransitiveParentEntity extends MappedGrandparentEntity {
|
||||||
|
private String parent;
|
||||||
|
|
||||||
|
public TransitiveParentEntity() {
|
||||||
|
super(null, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public TransitiveParentEntity(Long id, String grandparent, String notAudited, String parent) {
|
||||||
|
super(id, grandparent, notAudited);
|
||||||
|
this.parent = parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o) return true;
|
||||||
|
if (!(o instanceof TransitiveParentEntity)) return false;
|
||||||
|
if (!super.equals(o)) return false;
|
||||||
|
|
||||||
|
TransitiveParentEntity that = (TransitiveParentEntity) o;
|
||||||
|
|
||||||
|
if (parent != null ? !parent.equals(that.parent) : that.parent != null) return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int hashCode() {
|
||||||
|
int result = super.hashCode();
|
||||||
|
result = 31 * result + (parent != null ? parent.hashCode() : 0);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString() {
|
||||||
|
return "TransitiveParentEntity(" + super.toString() + ", parent = " + parent + ")";
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getParent() {
|
||||||
|
return parent;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setParent(String parent) {
|
||||||
|
this.parent = parent;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue