HHH-5580 - Query refactoring

This commit is contained in:
Lukasz Antoniak 2011-05-17 23:14:01 +02:00
parent 7dc925fcf6
commit 403b15cae8
5 changed files with 62 additions and 111 deletions

View File

@ -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,

View File

@ -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;
}
} }

View File

@ -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;
} }

View File

@ -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;
}
}

View File

@ -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);
}
}
} }