HHH-5580 - Query refactoring
This commit is contained in:
parent
7dc925fcf6
commit
403b15cae8
|
@ -30,6 +30,7 @@ import org.hibernate.annotations.common.reflection.ReflectionManager;
|
||||||
import org.hibernate.cfg.Configuration;
|
import org.hibernate.cfg.Configuration;
|
||||||
import org.hibernate.envers.entities.EntitiesConfigurations;
|
import org.hibernate.envers.entities.EntitiesConfigurations;
|
||||||
import org.hibernate.envers.entities.PropertyData;
|
import org.hibernate.envers.entities.PropertyData;
|
||||||
|
import org.hibernate.envers.revisioninfo.ModifiedEntityTypesReader;
|
||||||
import org.hibernate.envers.revisioninfo.RevisionInfoNumberReader;
|
import org.hibernate.envers.revisioninfo.RevisionInfoNumberReader;
|
||||||
import org.hibernate.envers.revisioninfo.RevisionInfoQueryCreator;
|
import org.hibernate.envers.revisioninfo.RevisionInfoQueryCreator;
|
||||||
import org.hibernate.envers.strategy.AuditStrategy;
|
import org.hibernate.envers.strategy.AuditStrategy;
|
||||||
|
@ -50,6 +51,7 @@ public class AuditConfiguration {
|
||||||
private final EntitiesConfigurations entCfg;
|
private final EntitiesConfigurations entCfg;
|
||||||
private final RevisionInfoQueryCreator revisionInfoQueryCreator;
|
private final RevisionInfoQueryCreator revisionInfoQueryCreator;
|
||||||
private final RevisionInfoNumberReader revisionInfoNumberReader;
|
private final RevisionInfoNumberReader revisionInfoNumberReader;
|
||||||
|
private final ModifiedEntityTypesReader modifiedEntityTypesReader;
|
||||||
|
|
||||||
public AuditEntitiesConfiguration getAuditEntCfg() {
|
public AuditEntitiesConfiguration getAuditEntCfg() {
|
||||||
return auditEntCfg;
|
return auditEntCfg;
|
||||||
|
@ -75,6 +77,10 @@ public class AuditConfiguration {
|
||||||
return revisionInfoNumberReader;
|
return revisionInfoNumberReader;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ModifiedEntityTypesReader getModifiedEntityTypesReader() {
|
||||||
|
return modifiedEntityTypesReader;
|
||||||
|
}
|
||||||
|
|
||||||
public AuditStrategy getAuditStrategy() {
|
public AuditStrategy getAuditStrategy() {
|
||||||
return auditStrategy;
|
return auditStrategy;
|
||||||
}
|
}
|
||||||
|
@ -90,6 +96,7 @@ public class AuditConfiguration {
|
||||||
auditProcessManager = new AuditProcessManager(revInfoCfgResult.getRevisionInfoGenerator());
|
auditProcessManager = new AuditProcessManager(revInfoCfgResult.getRevisionInfoGenerator());
|
||||||
revisionInfoQueryCreator = revInfoCfgResult.getRevisionInfoQueryCreator();
|
revisionInfoQueryCreator = revInfoCfgResult.getRevisionInfoQueryCreator();
|
||||||
revisionInfoNumberReader = revInfoCfgResult.getRevisionInfoNumberReader();
|
revisionInfoNumberReader = revInfoCfgResult.getRevisionInfoNumberReader();
|
||||||
|
modifiedEntityTypesReader = revInfoCfgResult.getModifiedEntityTypesReader();
|
||||||
auditStrategy = initializeAuditStrategy(revInfoCfgResult.getRevisionInfoClass(),
|
auditStrategy = initializeAuditStrategy(revInfoCfgResult.getRevisionInfoClass(),
|
||||||
revInfoCfgResult.getRevisionInfoTimestampData());
|
revInfoCfgResult.getRevisionInfoTimestampData());
|
||||||
entCfg = new EntitiesConfigurator().configure(cfg, reflectionManager, globalCfg, auditEntCfg, auditStrategy,
|
entCfg = new EntitiesConfigurator().configure(cfg, reflectionManager, globalCfg, auditEntCfg, auditStrategy,
|
||||||
|
|
|
@ -309,8 +309,10 @@ public class RevisionInfoConfiguration {
|
||||||
new RevisionInfoQueryCreator(revisionInfoEntityName, revisionInfoIdData.getName(),
|
new RevisionInfoQueryCreator(revisionInfoEntityName, revisionInfoIdData.getName(),
|
||||||
revisionInfoTimestampData.getName(), isTimestampAsDate()),
|
revisionInfoTimestampData.getName(), isTimestampAsDate()),
|
||||||
generateRevisionInfoRelationMapping(),
|
generateRevisionInfoRelationMapping(),
|
||||||
new RevisionInfoNumberReader(revisionInfoClass, revisionInfoIdData), revisionInfoEntityName,
|
new RevisionInfoNumberReader(revisionInfoClass, revisionInfoIdData),
|
||||||
revisionInfoClass, revisionInfoTimestampData);
|
globalCfg.isTrackEntitiesChangedInRevisionEnabled() ? new ModifiedEntityTypesReader(revisionInfoClass, modifiedEntityTypesData)
|
||||||
|
: null,
|
||||||
|
revisionInfoEntityName, revisionInfoClass, revisionInfoTimestampData);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isTimestampAsDate() {
|
private boolean isTimestampAsDate() {
|
||||||
|
@ -325,20 +327,22 @@ class RevisionInfoConfigurationResult {
|
||||||
private final RevisionInfoQueryCreator revisionInfoQueryCreator;
|
private final RevisionInfoQueryCreator revisionInfoQueryCreator;
|
||||||
private final Element revisionInfoRelationMapping;
|
private final Element revisionInfoRelationMapping;
|
||||||
private final RevisionInfoNumberReader revisionInfoNumberReader;
|
private final RevisionInfoNumberReader revisionInfoNumberReader;
|
||||||
|
private final ModifiedEntityTypesReader modifiedEntityTypesReader;
|
||||||
private final String revisionInfoEntityName;
|
private final String revisionInfoEntityName;
|
||||||
private final Class<?> revisionInfoClass;
|
private final Class<?> revisionInfoClass;
|
||||||
private final PropertyData revisionInfoTimestampData;
|
private final PropertyData revisionInfoTimestampData;
|
||||||
|
|
||||||
RevisionInfoConfigurationResult(RevisionInfoGenerator revisionInfoGenerator,
|
RevisionInfoConfigurationResult(RevisionInfoGenerator revisionInfoGenerator,
|
||||||
Document revisionInfoXmlMapping, RevisionInfoQueryCreator revisionInfoQueryCreator,
|
Document revisionInfoXmlMapping, RevisionInfoQueryCreator revisionInfoQueryCreator,
|
||||||
Element revisionInfoRelationMapping,
|
Element revisionInfoRelationMapping, RevisionInfoNumberReader revisionInfoNumberReader,
|
||||||
RevisionInfoNumberReader revisionInfoNumberReader, String revisionInfoEntityName, Class<?> revisionInfoClass,
|
ModifiedEntityTypesReader modifiedEntityTypesReader, String revisionInfoEntityName,
|
||||||
PropertyData revisionInfoTimestampData) {
|
Class<?> revisionInfoClass, PropertyData revisionInfoTimestampData) {
|
||||||
this.revisionInfoGenerator = revisionInfoGenerator;
|
this.revisionInfoGenerator = revisionInfoGenerator;
|
||||||
this.revisionInfoXmlMapping = revisionInfoXmlMapping;
|
this.revisionInfoXmlMapping = revisionInfoXmlMapping;
|
||||||
this.revisionInfoQueryCreator = revisionInfoQueryCreator;
|
this.revisionInfoQueryCreator = revisionInfoQueryCreator;
|
||||||
this.revisionInfoRelationMapping = revisionInfoRelationMapping;
|
this.revisionInfoRelationMapping = revisionInfoRelationMapping;
|
||||||
this.revisionInfoNumberReader = revisionInfoNumberReader;
|
this.revisionInfoNumberReader = revisionInfoNumberReader;
|
||||||
|
this.modifiedEntityTypesReader = modifiedEntityTypesReader;
|
||||||
this.revisionInfoEntityName = revisionInfoEntityName;
|
this.revisionInfoEntityName = revisionInfoEntityName;
|
||||||
this.revisionInfoClass = revisionInfoClass;
|
this.revisionInfoClass = revisionInfoClass;
|
||||||
this.revisionInfoTimestampData = revisionInfoTimestampData;
|
this.revisionInfoTimestampData = revisionInfoTimestampData;
|
||||||
|
@ -375,4 +379,8 @@ class RevisionInfoConfigurationResult {
|
||||||
public PropertyData getRevisionInfoTimestampData() {
|
public PropertyData getRevisionInfoTimestampData() {
|
||||||
return revisionInfoTimestampData;
|
return revisionInfoTimestampData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ModifiedEntityTypesReader getModifiedEntityTypesReader() {
|
||||||
|
return modifiedEntityTypesReader;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,7 +33,6 @@ import org.hibernate.HibernateException;
|
||||||
import org.hibernate.NonUniqueResultException;
|
import org.hibernate.NonUniqueResultException;
|
||||||
import org.hibernate.Session;
|
import org.hibernate.Session;
|
||||||
import org.hibernate.engine.SessionImplementor;
|
import org.hibernate.engine.SessionImplementor;
|
||||||
import org.hibernate.envers.ModifiedEntityTypes;
|
|
||||||
import org.hibernate.envers.RevisionType;
|
import org.hibernate.envers.RevisionType;
|
||||||
import org.hibernate.envers.configuration.AuditConfiguration;
|
import org.hibernate.envers.configuration.AuditConfiguration;
|
||||||
import org.hibernate.envers.exception.AuditException;
|
import org.hibernate.envers.exception.AuditException;
|
||||||
|
@ -43,7 +42,6 @@ import org.hibernate.envers.query.AuditEntity;
|
||||||
import org.hibernate.envers.query.AuditQueryCreator;
|
import org.hibernate.envers.query.AuditQueryCreator;
|
||||||
import org.hibernate.envers.query.criteria.RevisionTypeAuditExpression;
|
import org.hibernate.envers.query.criteria.RevisionTypeAuditExpression;
|
||||||
import org.hibernate.envers.synchronization.AuditProcess;
|
import org.hibernate.envers.synchronization.AuditProcess;
|
||||||
import org.hibernate.envers.tools.reflection.ReflectionTools;
|
|
||||||
import org.hibernate.event.EventSource;
|
import org.hibernate.event.EventSource;
|
||||||
import org.hibernate.proxy.HibernateProxy;
|
import org.hibernate.proxy.HibernateProxy;
|
||||||
|
|
||||||
|
@ -294,22 +292,7 @@ public class AuditReaderImpl implements AuditReaderImplementor {
|
||||||
Object revisionInfo = query.uniqueResult();
|
Object revisionInfo = query.uniqueResult();
|
||||||
if (revisionInfo != null) {
|
if (revisionInfo != null) {
|
||||||
// If revision exists
|
// If revision exists
|
||||||
if (modifiedEntityTypesProperty == null) {
|
return verCfg.getModifiedEntityTypesReader().getModifiedEntityTypes(revisionInfo);
|
||||||
// Only one field or method (getter) can be marked with @ModifiedEntityTypes annotation
|
|
||||||
modifiedEntityTypesProperty = (Member) ReflectionTools.getAnnotatedMembers(revisionInfo.getClass(),
|
|
||||||
ModifiedEntityTypes.class).toArray()[0];
|
|
||||||
}
|
|
||||||
Set<String> modifiedEntityTypes = (Set<String>) ReflectionTools.getPropertyValue(modifiedEntityTypesProperty, revisionInfo);
|
|
||||||
Set<Class> result = new HashSet<Class>(modifiedEntityTypes.size());
|
|
||||||
for (String entityClassName : modifiedEntityTypes) {
|
|
||||||
try {
|
|
||||||
result.add(Class.forName(entityClassName));
|
|
||||||
} catch (ClassNotFoundException e) {
|
|
||||||
// This shall never happen
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
return Collections.EMPTY_SET;
|
return Collections.EMPTY_SET;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
package org.hibernate.envers.revisioninfo;
|
||||||
|
|
||||||
|
import org.hibernate.envers.entities.PropertyData;
|
||||||
|
import org.hibernate.envers.tools.reflection.ReflectionTools;
|
||||||
|
import org.hibernate.property.Getter;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns modified entity types from a persisted revision info entity.
|
||||||
|
* @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com)
|
||||||
|
*/
|
||||||
|
public class ModifiedEntityTypesReader {
|
||||||
|
private final Getter modifiedEntityTypesGetter;
|
||||||
|
|
||||||
|
public ModifiedEntityTypesReader(Class<?> revisionInfoClass, PropertyData modifiedEntityTypesData) {
|
||||||
|
modifiedEntityTypesGetter = ReflectionTools.getGetter(revisionInfoClass, modifiedEntityTypesData);
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings({"unchecked"})
|
||||||
|
public Set<Class> getModifiedEntityTypes(Object revisionEntity) {
|
||||||
|
// The default mechanism of tracking entity types that have been changed during each revision, stores
|
||||||
|
// fully qualified Java class names.
|
||||||
|
Set<String> modifiedEntityClassNames = (Set<String>) modifiedEntityTypesGetter.get(revisionEntity);
|
||||||
|
if (modifiedEntityClassNames != null) {
|
||||||
|
Set<Class> result = new HashSet<Class>(modifiedEntityClassNames.size());
|
||||||
|
for (String entityClassName : modifiedEntityClassNames) {
|
||||||
|
try {
|
||||||
|
result.add(Thread.currentThread().getContextClassLoader().loadClass(entityClassName));
|
||||||
|
} catch (ClassNotFoundException e) {
|
||||||
|
// This shall never happen
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
return Collections.EMPTY_SET;
|
||||||
|
}
|
||||||
|
}
|
|
@ -45,7 +45,6 @@ import static org.hibernate.envers.tools.Pair.make;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Adam Warski (adam at warski dot org)
|
* @author Adam Warski (adam at warski dot org)
|
||||||
* @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com)
|
|
||||||
*/
|
*/
|
||||||
public class ReflectionTools {
|
public class ReflectionTools {
|
||||||
private static final Map<Pair<Class, String>, Getter> getterCache =
|
private static final Map<Pair<Class, String>, Getter> getterCache =
|
||||||
|
@ -100,91 +99,4 @@ public class ReflectionTools {
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns property value by invoking getter method or directly retrieving field's reference.
|
|
||||||
* @param member Field or getter method representation.
|
|
||||||
* @param object Object instance.
|
|
||||||
* @return Property value.
|
|
||||||
*/
|
|
||||||
public static Object getPropertyValue(Member member, Object object) {
|
|
||||||
try {
|
|
||||||
if (member instanceof Field) {
|
|
||||||
Field field = (Field) member;
|
|
||||||
field.setAccessible(true);
|
|
||||||
return field.get(object);
|
|
||||||
} else if (member instanceof Method) {
|
|
||||||
Method method = (Method) member;
|
|
||||||
method.setAccessible(true);
|
|
||||||
return method.invoke(object);
|
|
||||||
}
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
throw new IllegalArgumentException("Unsupported member type: " + member + ".");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param clazz Class type.
|
|
||||||
* @param annotation Searched annotation.
|
|
||||||
* @return Set of annotated members ({@link Field} and/or {@link Method}).
|
|
||||||
*/
|
|
||||||
public static Set<Member> getAnnotatedMembers(Class clazz, Class<? extends Annotation> annotation) {
|
|
||||||
try {
|
|
||||||
Set<Field> annotatedFields = new HashSet<Field>();
|
|
||||||
Set<Method> annotatedMethods = new HashSet<Method>();
|
|
||||||
doGetAnnotatedFields(clazz, annotation, annotatedFields);
|
|
||||||
doGetAnnotatedMethods(clazz, annotation, annotatedMethods);
|
|
||||||
Set<Member> result = new HashSet<Member>(annotatedFields.size() + annotatedMethods.size());
|
|
||||||
for (Field field : annotatedFields) {
|
|
||||||
field.setAccessible(true);
|
|
||||||
result.add(field);
|
|
||||||
}
|
|
||||||
for (Method method : annotatedMethods) {
|
|
||||||
method.setAccessible(true);
|
|
||||||
result.add(method);
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Populates {@code fields} set with all properties marked with a given annotation.
|
|
||||||
* @param clazz Class type.
|
|
||||||
* @param annotation Annotation.
|
|
||||||
* @param fields Set of annotated fields. Shall be initialized externally.
|
|
||||||
*/
|
|
||||||
private static void doGetAnnotatedFields(Class clazz, Class<? extends Annotation> annotation, Set<Field> fields) {
|
|
||||||
for (Field field : clazz.getDeclaredFields()) {
|
|
||||||
field.setAccessible(true);
|
|
||||||
if (field.isAnnotationPresent(annotation)) {
|
|
||||||
fields.add(field);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Class superClass = clazz.getSuperclass();
|
|
||||||
if (!Object.class.equals(superClass)) {
|
|
||||||
doGetAnnotatedFields(superClass, annotation, fields);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Populates {@code methods} set with all functions marked with a given annotation.
|
|
||||||
* @param clazz Class type.
|
|
||||||
* @param annotation Annotation.
|
|
||||||
* @param methods Set of annotated methods. Shall be initialized externally.
|
|
||||||
*/
|
|
||||||
private static void doGetAnnotatedMethods(Class clazz, Class<? extends Annotation> annotation, Set<Method> methods) {
|
|
||||||
for (Method method : clazz.getDeclaredMethods()) {
|
|
||||||
method.setAccessible(true);
|
|
||||||
if (method.isAnnotationPresent(annotation)) {
|
|
||||||
methods.add(method);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Class superClass = clazz.getSuperclass();
|
|
||||||
if (!Object.class.equals(superClass)) {
|
|
||||||
doGetAnnotatedMethods(superClass, annotation, methods);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue