From 6e57774e42dcb936d6d89e6f99869532656aecbe Mon Sep 17 00:00:00 2001 From: Adam Warski Date: Mon, 5 Jul 2010 17:04:29 +0000 Subject: [PATCH] HHH-4716: - applying patch - thanks to Hernan Chanfreau! - supporting the entity-name concept of Hibernate - when guessing from the class name doesn't work git-svn-id: https://svn.jboss.org/repos/hibernate/core/trunk@19899 1b8cb986-b30d-0410-93ca-fae66ebed9b2 --- .../org/hibernate/envers/AuditReader.java | 34 ++++++- .../metadata/AuditMetadataGenerator.java | 5 +- .../metadata/CollectionMetadataGenerator.java | 2 +- .../envers/entities/EntityConfiguration.java | 15 ++- .../envers/entities/EntityInstantiator.java | 9 +- .../relation/OneToOneNotOwningMapper.java | 12 ++- .../mapper/relation/ToOneIdMapper.java | 12 ++- .../lazy/ToOneDelegateSessionImplementor.java | 13 +-- .../envers/event/AuditEventListener.java | 3 +- .../envers/query/AuditQueryCreator.java | 43 ++++++++ .../envers/query/impl/AbstractAuditQuery.java | 29 ++++-- .../query/impl/EntitiesAtRevisionQuery.java | 7 ++ .../query/impl/RevisionsOfEntityQuery.java | 11 ++- .../envers/reader/AuditReaderImpl.java | 28 ++++-- .../org/hibernate/envers/tools/Tools.java | 15 +-- .../envers/test/AbstractSessionTest.java | 78 +++++++++++++++ .../entityNames/auditedEntity/Person.java | 51 ++++++++++ .../ReadEntityWhtiEntityNameTest.java | 99 +++++++++++++++++++ .../entityNames/manyToManyAudited/Car.java | 56 +++++++++++ .../entityNames/manyToManyAudited/Person.java | 63 ++++++++++++ .../ReadEntityWithAuditedManyToManyTest.java | 99 +++++++++++++++++++ .../entityNames/oneToManyAudited/Car.java | 56 +++++++++++ .../entityNames/oneToManyAudited/Person.java | 51 ++++++++++ .../ReadEntityWithAuditedCollectionTest.java | 89 +++++++++++++++++ .../entityNames/oneToManyNotAudited/Car.java | 58 +++++++++++ .../oneToManyNotAudited/Person.java | 48 +++++++++ .../ReadEntityWithAuditedCollectionTest.java | 84 ++++++++++++++++ .../singleAssociatedAudited/Car.java | 54 ++++++++++ .../singleAssociatedAudited/Person.java | 51 ++++++++++ .../ReadEntityAssociatedAuditedTest.java | 77 +++++++++++++++ .../singleAssociatedNotAudited/Car.java | 56 +++++++++++ .../singleAssociatedNotAudited/Person.java | 48 +++++++++ .../ReadEntityAssociatedNotAuditedTest.java | 80 +++++++++++++++ .../resources/hibernate.test.session-cfg.xml | 46 +++++++++ .../auditedEntity/mappings.hbm.xml | 18 ++++ .../manyToManyAudited/mappings.hbm.xml | 40 ++++++++ .../oneToManyAudited/mappings.hbm.xml | 48 +++++++++ .../oneToManyNotAudited/mappings.hbm.xml | 34 +++++++ .../singleAssociatedAudited/mappings.hbm.xml | 30 ++++++ .../mappings.hbm.xml | 30 ++++++ envers/src/test/resources/testng.xml | 8 +- 41 files changed, 1644 insertions(+), 46 deletions(-) create mode 100644 envers/src/test/java/org/hibernate/envers/test/AbstractSessionTest.java create mode 100644 envers/src/test/java/org/hibernate/envers/test/entityNames/auditedEntity/Person.java create mode 100644 envers/src/test/java/org/hibernate/envers/test/entityNames/auditedEntity/ReadEntityWhtiEntityNameTest.java create mode 100644 envers/src/test/java/org/hibernate/envers/test/entityNames/manyToManyAudited/Car.java create mode 100644 envers/src/test/java/org/hibernate/envers/test/entityNames/manyToManyAudited/Person.java create mode 100644 envers/src/test/java/org/hibernate/envers/test/entityNames/manyToManyAudited/ReadEntityWithAuditedManyToManyTest.java create mode 100644 envers/src/test/java/org/hibernate/envers/test/entityNames/oneToManyAudited/Car.java create mode 100644 envers/src/test/java/org/hibernate/envers/test/entityNames/oneToManyAudited/Person.java create mode 100644 envers/src/test/java/org/hibernate/envers/test/entityNames/oneToManyAudited/ReadEntityWithAuditedCollectionTest.java create mode 100644 envers/src/test/java/org/hibernate/envers/test/entityNames/oneToManyNotAudited/Car.java create mode 100644 envers/src/test/java/org/hibernate/envers/test/entityNames/oneToManyNotAudited/Person.java create mode 100644 envers/src/test/java/org/hibernate/envers/test/entityNames/oneToManyNotAudited/ReadEntityWithAuditedCollectionTest.java create mode 100644 envers/src/test/java/org/hibernate/envers/test/entityNames/singleAssociatedAudited/Car.java create mode 100644 envers/src/test/java/org/hibernate/envers/test/entityNames/singleAssociatedAudited/Person.java create mode 100644 envers/src/test/java/org/hibernate/envers/test/entityNames/singleAssociatedAudited/ReadEntityAssociatedAuditedTest.java create mode 100644 envers/src/test/java/org/hibernate/envers/test/entityNames/singleAssociatedNotAudited/Car.java create mode 100644 envers/src/test/java/org/hibernate/envers/test/entityNames/singleAssociatedNotAudited/Person.java create mode 100644 envers/src/test/java/org/hibernate/envers/test/entityNames/singleAssociatedNotAudited/ReadEntityAssociatedNotAuditedTest.java create mode 100644 envers/src/test/resources/hibernate.test.session-cfg.xml create mode 100644 envers/src/test/resources/mappings/entityNames/auditedEntity/mappings.hbm.xml create mode 100644 envers/src/test/resources/mappings/entityNames/manyToManyAudited/mappings.hbm.xml create mode 100644 envers/src/test/resources/mappings/entityNames/oneToManyAudited/mappings.hbm.xml create mode 100644 envers/src/test/resources/mappings/entityNames/oneToManyNotAudited/mappings.hbm.xml create mode 100644 envers/src/test/resources/mappings/entityNames/singleAssociatedAudited/mappings.hbm.xml create mode 100644 envers/src/test/resources/mappings/entityNames/singleAssociatedNotAudited/mappings.hbm.xml diff --git a/envers/src/main/java/org/hibernate/envers/AuditReader.java b/envers/src/main/java/org/hibernate/envers/AuditReader.java index f8a125cb6e..267e7586a4 100644 --- a/envers/src/main/java/org/hibernate/envers/AuditReader.java +++ b/envers/src/main/java/org/hibernate/envers/AuditReader.java @@ -32,7 +32,7 @@ import org.hibernate.envers.query.AuditQueryCreator; /** * @author Adam Warski (adam at warski dot org) - * @author Hernan Chanfreau + * @author Hern�n Chanfreau */ public interface AuditReader { /** @@ -49,6 +49,23 @@ public interface AuditReader { */ T find(Class cls, Object primaryKey, Number revision) throws IllegalArgumentException, NotAuditedException, IllegalStateException; + + /** + * Find an entity by primary key at the given revision with the specified entityName. + * @param cls Class of the entity. + * @param entityName Name of the entity (if can't be guessed basing on the {@code cls}). + * @param primaryKey Primary key of the entity. + * @param revision Revision in which to get the entity. + * @return The found entity instance at the given revision (its properties may be partially filled + * if not all properties are audited) or null, if an entity with that id didn't exist at that + * revision. + * @throws IllegalArgumentException If cls or primaryKey is null or revision is less or equal to 0. + * @throws NotAuditedException When entities of the given class are not audited. + * @throws IllegalStateException If the associated entity manager is closed. + */ + T find(Class cls, String entityName, Object primaryKey, + Number revision) throws IllegalArgumentException, + NotAuditedException, IllegalStateException; /** * Get a list of revision numbers, at which an entity was modified. @@ -62,6 +79,21 @@ public interface AuditReader { */ List getRevisions(Class cls, Object primaryKey) throws IllegalArgumentException, NotAuditedException, IllegalStateException; + + /** + * Get a list of revision numbers, at which an entity was modified, looking by entityName. + * @param cls Class of the entity. + * @param entityName Name of the entity (if can't be guessed basing on the {@code cls}). + * @param primaryKey Primary key of the entity. + * @return A list of revision numbers, at which the entity was modified, sorted in ascending order (so older + * revisions come first). + * @throws NotAuditedException When entities of the given class are not audited. + * @throws IllegalArgumentException If cls or primaryKey is null. + * @throws IllegalStateException If the associated entity manager is closed. + */ + List getRevisions(Class cls, String entityName, Object primaryKey) + throws IllegalArgumentException, NotAuditedException, + IllegalStateException; /** * Get the date, at which a revision was created. diff --git a/envers/src/main/java/org/hibernate/envers/configuration/metadata/AuditMetadataGenerator.java b/envers/src/main/java/org/hibernate/envers/configuration/metadata/AuditMetadataGenerator.java index e9fd78d277..d9b9270eed 100644 --- a/envers/src/main/java/org/hibernate/envers/configuration/metadata/AuditMetadataGenerator.java +++ b/envers/src/main/java/org/hibernate/envers/configuration/metadata/AuditMetadataGenerator.java @@ -55,6 +55,7 @@ import org.slf4j.LoggerFactory; * @author Sebastian Komander * @author Tomasz Bech * @author Stephanie Pau at Markit Group Plc + * @author Hern�n Chanfreau */ public final class AuditMetadataGenerator { private static final Logger log = LoggerFactory.getLogger(AuditMetadataGenerator.class); @@ -370,7 +371,7 @@ public final class AuditMetadataGenerator { ExtendedPropertyMapper propertyMapper = null; String parentEntityName = null; - EntityConfiguration entityCfg = new EntityConfiguration(entityName, idMapper, propertyMapper, + EntityConfiguration entityCfg = new EntityConfiguration(entityName, pc.getClassName(), idMapper, propertyMapper, parentEntityName); notAuditedEntitiesConfigurations.put(entityName, entityCfg); return; @@ -444,7 +445,7 @@ public final class AuditMetadataGenerator { addJoins(pc, propertyMapper, auditingData, pc.getEntityName(), xmlMappingData, true); // Storing the generated configuration - EntityConfiguration entityCfg = new EntityConfiguration(auditEntityName, idMapper, + EntityConfiguration entityCfg = new EntityConfiguration(auditEntityName,pc.getClassName(), idMapper, propertyMapper, parentEntityName); entitiesConfigurations.put(pc.getEntityName(), entityCfg); } diff --git a/envers/src/main/java/org/hibernate/envers/configuration/metadata/CollectionMetadataGenerator.java b/envers/src/main/java/org/hibernate/envers/configuration/metadata/CollectionMetadataGenerator.java index c0c8163ed6..e9e0ff06b4 100644 --- a/envers/src/main/java/org/hibernate/envers/configuration/metadata/CollectionMetadataGenerator.java +++ b/envers/src/main/java/org/hibernate/envers/configuration/metadata/CollectionMetadataGenerator.java @@ -209,7 +209,7 @@ public final class CollectionMetadataGenerator { // The mapper will only be used to map from entity to map, so no need to provide other details // when constructing the PropertyData. new PropertyData(auditMappedBy, null, null, null), - referencedEntityName, false); + referencingEntityName, false); // Checking if there's an index defined. If so, adding a mapper for it. if (propertyAuditingData.getPositionMappedBy() != null) { diff --git a/envers/src/main/java/org/hibernate/envers/entities/EntityConfiguration.java b/envers/src/main/java/org/hibernate/envers/entities/EntityConfiguration.java index 91e1bcbac2..56b7df1378 100644 --- a/envers/src/main/java/org/hibernate/envers/entities/EntityConfiguration.java +++ b/envers/src/main/java/org/hibernate/envers/entities/EntityConfiguration.java @@ -32,18 +32,22 @@ import org.hibernate.envers.entities.mapper.id.IdMapper; /** * @author Adam Warski (adam at warski dot org) + * @author Hern�n Chanfreau */ public class EntityConfiguration { private String versionsEntityName; - private IdMappingData idMappingData; + /** Holds the className for instantiation the configured entity */ + private String entityClassName; + private IdMappingData idMappingData; private ExtendedPropertyMapper propertyMapper; // Maps from property name private Map relations; private String parentEntityName; - public EntityConfiguration(String versionsEntityName, IdMappingData idMappingData, + public EntityConfiguration(String versionsEntityName, String entityClassName, IdMappingData idMappingData, ExtendedPropertyMapper propertyMapper, String parentEntityName) { this.versionsEntityName = versionsEntityName; + this.entityClassName = entityClassName; this.idMappingData = idMappingData; this.propertyMapper = propertyMapper; this.parentEntityName = parentEntityName; @@ -113,4 +117,11 @@ public class EntityConfiguration { Iterable getRelationsIterator() { return relations.values(); } + + /** + * @return the className for the configured entity + */ + public String getEntityClassName() { + return entityClassName; + } } diff --git a/envers/src/main/java/org/hibernate/envers/entities/EntityInstantiator.java b/envers/src/main/java/org/hibernate/envers/entities/EntityInstantiator.java index 3726f95a68..7afd060695 100644 --- a/envers/src/main/java/org/hibernate/envers/entities/EntityInstantiator.java +++ b/envers/src/main/java/org/hibernate/envers/entities/EntityInstantiator.java @@ -36,6 +36,7 @@ import org.hibernate.util.ReflectHelper; /** * @author Adam Warski (adam at warski dot org) + * @author Hern�n Chanfreau */ public class EntityInstantiator { private final AuditConfiguration verCfg; @@ -80,7 +81,13 @@ public class EntityInstantiator { // If it is not in the cache, creating a new entity instance Object ret; try { - Class cls = ReflectionTools.loadClass(entityName); + EntityConfiguration entCfg = verCfg.getEntCfg().get(entityName); + if(entCfg == null) { + // a relation marked as RelationTargetAuditMode.NOT_AUDITED + entCfg = verCfg.getEntCfg().getNotVersionEntityConfiguration(entityName); + } + + Class cls = ReflectionTools.loadClass(entCfg.getEntityClassName()); ret = ReflectHelper.getDefaultConstructor(cls).newInstance(); } catch (Exception e) { throw new AuditException(e); diff --git a/envers/src/main/java/org/hibernate/envers/entities/mapper/relation/OneToOneNotOwningMapper.java b/envers/src/main/java/org/hibernate/envers/entities/mapper/relation/OneToOneNotOwningMapper.java index 90b6a8ae82..8ac7449a93 100644 --- a/envers/src/main/java/org/hibernate/envers/entities/mapper/relation/OneToOneNotOwningMapper.java +++ b/envers/src/main/java/org/hibernate/envers/entities/mapper/relation/OneToOneNotOwningMapper.java @@ -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.EntityConfiguration; import org.hibernate.envers.entities.PropertyData; import org.hibernate.envers.exception.AuditException; import org.hibernate.envers.query.AuditEntity; @@ -44,6 +45,7 @@ import org.hibernate.property.Setter; /** * @author Adam Warski (adam at warski dot org) + * @author Hern�n Chanfreau */ public class OneToOneNotOwningMapper implements PropertyMapper { private String owningReferencePropertyName; @@ -66,12 +68,18 @@ public class OneToOneNotOwningMapper implements PropertyMapper { return; } - Class entityClass = ReflectionTools.loadClass(owningEntityName); + EntityConfiguration entCfg = verCfg.getEntCfg().get(owningEntityName); + if(entCfg == null) { + // a relation marked as RelationTargetAuditMode.NOT_AUDITED + entCfg = verCfg.getEntCfg().getNotVersionEntityConfiguration(owningEntityName); + } + + Class entityClass = ReflectionTools.loadClass(entCfg.getEntityClassName()); Object value; try { - value = versionsReader.createQuery().forEntitiesAtRevision(entityClass, revision) + value = versionsReader.createQuery().forEntitiesAtRevision(entityClass, owningEntityName, revision) .add(AuditEntity.relatedId(owningReferencePropertyName).eq(primaryKey)).getSingleResult(); } catch (NoResultException e) { value = null; diff --git a/envers/src/main/java/org/hibernate/envers/entities/mapper/relation/ToOneIdMapper.java b/envers/src/main/java/org/hibernate/envers/entities/mapper/relation/ToOneIdMapper.java index d6fd5df14e..514cd57cb5 100644 --- a/envers/src/main/java/org/hibernate/envers/entities/mapper/relation/ToOneIdMapper.java +++ b/envers/src/main/java/org/hibernate/envers/entities/mapper/relation/ToOneIdMapper.java @@ -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.EntityConfiguration; import org.hibernate.envers.entities.PropertyData; import org.hibernate.envers.reader.AuditReaderImplementor; import org.hibernate.envers.tools.Tools; @@ -44,6 +45,7 @@ import org.hibernate.engine.SessionImplementor; /** * @author Adam Warski (adam at warski dot org) + * @author Hern�n Chanfreau */ public class ToOneIdMapper implements PropertyMapper { private final IdMapper delegate; @@ -68,7 +70,7 @@ public class ToOneIdMapper implements PropertyMapper { delegate.mapToMapFromEntity(newData, nonInsertableFake ? oldObj : newObj); //noinspection SimplifiableConditionalExpression - return nonInsertableFake ? false : !Tools.entitiesEqual(session, newObj, oldObj); + return nonInsertableFake ? false : !Tools.entitiesEqual(session, referencedEntityName, newObj, oldObj); } public void mapToEntityFromMap(AuditConfiguration verCfg, Object obj, Map data, Object primaryKey, @@ -85,7 +87,13 @@ public class ToOneIdMapper implements PropertyMapper { if (versionsReader.getFirstLevelCache().contains(referencedEntityName, revision, entityId)) { value = versionsReader.getFirstLevelCache().get(referencedEntityName, revision, entityId); } else { - Class entityClass = ReflectionTools.loadClass(referencedEntityName); + EntityConfiguration entCfg = verCfg.getEntCfg().get(referencedEntityName); + if(entCfg == null) { + // a relation marked as RelationTargetAuditMode.NOT_AUDITED + entCfg = verCfg.getEntCfg().getNotVersionEntityConfiguration(referencedEntityName); + } + + Class entityClass = ReflectionTools.loadClass(entCfg.getEntityClassName()); value = versionsReader.getSessionImplementor().getFactory().getEntityPersister(referencedEntityName). createProxy((Serializable)entityId, new ToOneDelegateSessionImplementor(versionsReader, entityClass, entityId, revision, verCfg)); diff --git a/envers/src/main/java/org/hibernate/envers/entities/mapper/relation/lazy/ToOneDelegateSessionImplementor.java b/envers/src/main/java/org/hibernate/envers/entities/mapper/relation/lazy/ToOneDelegateSessionImplementor.java index a577bf4aa6..bbde054d5d 100644 --- a/envers/src/main/java/org/hibernate/envers/entities/mapper/relation/lazy/ToOneDelegateSessionImplementor.java +++ b/envers/src/main/java/org/hibernate/envers/entities/mapper/relation/lazy/ToOneDelegateSessionImplementor.java @@ -27,7 +27,6 @@ import java.io.Serializable; import org.hibernate.envers.configuration.AuditConfiguration; import org.hibernate.envers.entities.EntitiesConfigurations; -import org.hibernate.envers.entities.EntityConfiguration; import org.hibernate.envers.reader.AuditReaderImplementor; import org.hibernate.HibernateException; @@ -35,6 +34,7 @@ import org.hibernate.HibernateException; /** * @author Adam Warski (adam at warski dot org) * @author Tomasz Bech + * @author Hern�n Chanfreau */ public class ToOneDelegateSessionImplementor extends AbstractDelegateSessionImplementor { private static final long serialVersionUID = 4770438372940785488L; @@ -43,7 +43,7 @@ public class ToOneDelegateSessionImplementor extends AbstractDelegateSessionImpl private final Class entityClass; private final Object entityId; private final Number revision; - private EntityConfiguration notVersionedEntityConfiguration; + private EntitiesConfigurations entCfg; public ToOneDelegateSessionImplementor(AuditReaderImplementor versionsReader, Class entityClass, Object entityId, Number revision, @@ -53,14 +53,15 @@ public class ToOneDelegateSessionImplementor extends AbstractDelegateSessionImpl this.entityClass = entityClass; this.entityId = entityId; this.revision = revision; - EntitiesConfigurations entCfg = verCfg.getEntCfg(); - notVersionedEntityConfiguration = entCfg.getNotVersionEntityConfiguration(entityClass.getName()); + this.entCfg = verCfg.getEntCfg(); } public Object doImmediateLoad(String entityName) throws HibernateException { - if (notVersionedEntityConfiguration == null) { - return versionsReader.find(entityClass, entityId, revision); + if(entCfg.getNotVersionEntityConfiguration(entityName) == null){ + // audited relation, look up entity with envers + return versionsReader.find(entityClass, entityName, entityId, revision); } else { + // notAudited relation, look up entity with hibernate return delegate.immediateLoad(entityName, (Serializable) entityId); } } diff --git a/envers/src/main/java/org/hibernate/envers/event/AuditEventListener.java b/envers/src/main/java/org/hibernate/envers/event/AuditEventListener.java index ad46581d6c..3cbfc70d4a 100644 --- a/envers/src/main/java/org/hibernate/envers/event/AuditEventListener.java +++ b/envers/src/main/java/org/hibernate/envers/event/AuditEventListener.java @@ -61,6 +61,7 @@ import org.hibernate.proxy.HibernateProxy; /** * @author Adam Warski (adam at warski dot org) + * @author Hern�n Chanfreau */ public class AuditEventListener implements PostInsertEventListener, PostUpdateEventListener, PostDeleteEventListener, PreCollectionUpdateEventListener, PreCollectionRemoveEventListener, @@ -91,7 +92,7 @@ public class AuditEventListener implements PostInsertEventListener, PostUpdateEv Object oldValue = oldState == null ? null : oldState[i]; Object newValue = newState == null ? null : newState[i]; - if (!Tools.entitiesEqual(session, oldValue, newValue)) { + if (!Tools.entitiesEqual(session, relDesc.getToEntityName(), oldValue, newValue)) { // We have to generate changes both in the old collection (size decreses) and new collection // (size increases). if (newValue != null) { diff --git a/envers/src/main/java/org/hibernate/envers/query/AuditQueryCreator.java b/envers/src/main/java/org/hibernate/envers/query/AuditQueryCreator.java index c0b0113917..b1cfe8cb5d 100644 --- a/envers/src/main/java/org/hibernate/envers/query/AuditQueryCreator.java +++ b/envers/src/main/java/org/hibernate/envers/query/AuditQueryCreator.java @@ -32,6 +32,7 @@ import static org.hibernate.envers.tools.ArgumentsTools.checkPositive; /** * @author Adam Warski (adam at warski dot org) + * @author Hern�n Chanfreau */ public class AuditQueryCreator { private final AuditConfiguration auditCfg; @@ -56,6 +57,22 @@ public class AuditQueryCreator { checkPositive(revision, "Entity revision"); return new EntitiesAtRevisionQuery(auditCfg, auditReaderImplementor, c, revision); } + + /** + * Creates a query, which will return entities satisfying some conditions (specified later), + * at a given revision and a given entityName. + * @param c Class of the entities for which to query. + * @param entityName Name of the entity (if can't be guessed basing on the {@code c}). + * @param revision Revision number at which to execute the query. + * @return A query for entities at a given revision, to which conditions can be added and which + * can then be executed. The result of the query will be a list of entities (beans), unless a + * projection is added. + */ + public AuditQuery forEntitiesAtRevision(Class c, String entityName, Number revision) { + checkNotNull(revision, "Entity revision"); + checkPositive(revision, "Entity revision"); + return new EntitiesAtRevisionQuery(auditCfg, auditReaderImplementor, c, entityName, revision); + } /** * Creates a query, which selects the revisions, at which the given entity was modified. @@ -80,4 +97,30 @@ public class AuditQueryCreator { public AuditQuery forRevisionsOfEntity(Class c, boolean selectEntitiesOnly, boolean selectDeletedEntities) { return new RevisionsOfEntityQuery(auditCfg, auditReaderImplementor, c, selectEntitiesOnly,selectDeletedEntities); } + + /** + * Creates a query, which selects the revisions, at which the given entity was modified and with a given entityName. + * Unless an explicit projection is set, the result will be a list of three-element arrays, containing: + *
    + *
  1. the entity instance
  2. + *
  3. revision entity, corresponding to the revision at which the entity was modified. If no custom + * revision entity is used, this will be an instance of {@link org.hibernate.envers.DefaultRevisionEntity}
  4. + *
  5. type of the revision (an enum instance of class {@link org.hibernate.envers.RevisionType})
  6. . + *
+ * Additional conditions that the results must satisfy may be specified. + * @param c Class of the entities for which to query. + * @param entityName Name of the entity (if can't be guessed basing on the {@code c}). + * @param selectEntitiesOnly If true, instead of a list of three-element arrays, a list of entites will be + * returned as a result of executing this query. + * @param selectDeletedEntities If true, also revisions where entities were deleted will be returned. The additional + * entities will have revision type "delete", and contain no data (all fields null), except for the id field. + * @return A query for revisions at which instances of the given entity were modified, to which + * conditions can be added (for example - a specific id of an entity of class c), and which + * can then be executed. The results of the query will be sorted in ascending order by the revision number, + * unless an order or projection is added. + */ + public AuditQuery forRevisionsOfEntity(Class c, String entityName, boolean selectEntitiesOnly, boolean selectDeletedEntities) { + return new RevisionsOfEntityQuery(auditCfg, auditReaderImplementor, c, entityName, selectEntitiesOnly,selectDeletedEntities); + } + } diff --git a/envers/src/main/java/org/hibernate/envers/query/impl/AbstractAuditQuery.java b/envers/src/main/java/org/hibernate/envers/query/impl/AbstractAuditQuery.java index 6cbb1098c6..8761ff01c8 100644 --- a/envers/src/main/java/org/hibernate/envers/query/impl/AbstractAuditQuery.java +++ b/envers/src/main/java/org/hibernate/envers/query/impl/AbstractAuditQuery.java @@ -48,12 +48,14 @@ import org.hibernate.LockOptions; /** * @author Adam Warski (adam at warski dot org) + * @author Hern�n Chanfreau */ public abstract class AbstractAuditQuery implements AuditQuery { protected EntityInstantiator entityInstantiator; protected List criterions; protected String entityName; + protected String entityClassName; protected String versionsEntityName; protected QueryBuilder qb; @@ -65,18 +67,25 @@ public abstract class AbstractAuditQuery implements AuditQuery { protected AbstractAuditQuery(AuditConfiguration verCfg, AuditReaderImplementor versionsReader, Class cls) { - this.verCfg = verCfg; - this.versionsReader = versionsReader; - - criterions = new ArrayList(); - entityInstantiator = new EntityInstantiator(verCfg, versionsReader); - - entityName = cls.getName(); - versionsEntityName = verCfg.getAuditEntCfg().getAuditEntityName(entityName); - - qb = new QueryBuilder(versionsEntityName, "e"); + this(verCfg, versionsReader, cls, cls.getName()); } + protected AbstractAuditQuery(AuditConfiguration verCfg, + AuditReaderImplementor versionsReader, Class cls, String entityName) { + this.verCfg = verCfg; + this.versionsReader = versionsReader; + + criterions = new ArrayList(); + entityInstantiator = new EntityInstantiator(verCfg, versionsReader); + + entityClassName = cls.getName(); + this.entityName = entityName; + versionsEntityName = verCfg.getAuditEntCfg().getAuditEntityName( + entityName); + + qb = new QueryBuilder(versionsEntityName, "e"); + } + protected List buildAndExecuteQuery() { Query query = qb.toQuery(versionsReader.getSession()); diff --git a/envers/src/main/java/org/hibernate/envers/query/impl/EntitiesAtRevisionQuery.java b/envers/src/main/java/org/hibernate/envers/query/impl/EntitiesAtRevisionQuery.java index 0e64a4c0a4..d0437857e0 100644 --- a/envers/src/main/java/org/hibernate/envers/query/impl/EntitiesAtRevisionQuery.java +++ b/envers/src/main/java/org/hibernate/envers/query/impl/EntitiesAtRevisionQuery.java @@ -35,6 +35,7 @@ import org.hibernate.envers.tools.query.QueryBuilder; /** * @author Adam Warski (adam at warski dot org) + * @author Hern�n Chanfreau */ public class EntitiesAtRevisionQuery extends AbstractAuditQuery { private final Number revision; @@ -45,6 +46,12 @@ public class EntitiesAtRevisionQuery extends AbstractAuditQuery { super(verCfg, versionsReader, cls); this.revision = revision; } + + public EntitiesAtRevisionQuery(AuditConfiguration verCfg, + AuditReaderImplementor versionsReader, Class cls, String entityName, Number revision) { + super(verCfg, versionsReader, cls, entityName); + this.revision = revision; + } @SuppressWarnings({"unchecked"}) public List list() { diff --git a/envers/src/main/java/org/hibernate/envers/query/impl/RevisionsOfEntityQuery.java b/envers/src/main/java/org/hibernate/envers/query/impl/RevisionsOfEntityQuery.java index 6249fbff33..545b1fde10 100644 --- a/envers/src/main/java/org/hibernate/envers/query/impl/RevisionsOfEntityQuery.java +++ b/envers/src/main/java/org/hibernate/envers/query/impl/RevisionsOfEntityQuery.java @@ -33,11 +33,11 @@ import org.hibernate.envers.configuration.AuditEntitiesConfiguration; import org.hibernate.envers.exception.AuditException; import org.hibernate.envers.query.criteria.AuditCriterion; import org.hibernate.envers.reader.AuditReaderImplementor; - import org.hibernate.proxy.HibernateProxy; /** * @author Adam Warski (adam at warski dot org) + * @author Hern�n Chanfreau */ public class RevisionsOfEntityQuery extends AbstractAuditQuery { private final boolean selectEntitiesOnly; @@ -53,6 +53,15 @@ public class RevisionsOfEntityQuery extends AbstractAuditQuery { this.selectDeletedEntities = selectDeletedEntities; } + public RevisionsOfEntityQuery(AuditConfiguration verCfg, + AuditReaderImplementor versionsReader, Class cls, String entityName, + boolean selectEntitiesOnly, boolean selectDeletedEntities) { + super(verCfg, versionsReader, cls, entityName); + + this.selectEntitiesOnly = selectEntitiesOnly; + this.selectDeletedEntities = selectDeletedEntities; + } + private Number getRevisionNumber(Map versionsEntity) { AuditEntitiesConfiguration verEntCfg = verCfg.getAuditEntCfg(); diff --git a/envers/src/main/java/org/hibernate/envers/reader/AuditReaderImpl.java b/envers/src/main/java/org/hibernate/envers/reader/AuditReaderImpl.java index 818f227151..8be955a339 100644 --- a/envers/src/main/java/org/hibernate/envers/reader/AuditReaderImpl.java +++ b/envers/src/main/java/org/hibernate/envers/reader/AuditReaderImpl.java @@ -46,7 +46,7 @@ import org.hibernate.engine.SessionImplementor; /** * @author Adam Warski (adam at warski dot org) - * @author Hernan Chanfreau + * @author Hern�n Chanfreau */ public class AuditReaderImpl implements AuditReaderImplementor { private final AuditConfiguration verCfg; @@ -81,17 +81,22 @@ public class AuditReaderImpl implements AuditReaderImplementor { return firstLevelCache; } - @SuppressWarnings({"unchecked"}) public T find(Class cls, Object primaryKey, Number revision) throws IllegalArgumentException, NotAuditedException, IllegalStateException { + + return this.find(cls, cls.getName(), primaryKey, revision); + } + + @SuppressWarnings({"unchecked"}) + public T find(Class cls, String entityName, Object primaryKey, Number revision) throws + IllegalArgumentException, NotAuditedException, IllegalStateException { checkNotNull(cls, "Entity class"); + checkNotNull(entityName, "Entity name"); checkNotNull(primaryKey, "Primary key"); checkNotNull(revision, "Entity revision"); checkPositive(revision, "Entity revision"); checkSession(); - String entityName = cls.getName(); - if (!verCfg.getEntCfg().isVersioned(entityName)) { throw new NotAuditedException(entityName, entityName + " is not versioned!"); } @@ -103,7 +108,7 @@ public class AuditReaderImpl implements AuditReaderImplementor { Object result; try { // The result is put into the cache by the entity instantiator called from the query - result = createQuery().forEntitiesAtRevision(cls, revision) + result = createQuery().forEntitiesAtRevision(cls, entityName, revision) .add(AuditEntity.id().eq(primaryKey)).getSingleResult(); } catch (NoResultException e) { result = null; @@ -112,23 +117,28 @@ public class AuditReaderImpl implements AuditReaderImplementor { } return (T) result; + } + + public List getRevisions(Class cls, Object primaryKey) + throws IllegalArgumentException, NotAuditedException, IllegalStateException { + + return this.getRevisions(cls, cls.getName(), primaryKey); } @SuppressWarnings({"unchecked"}) - public List getRevisions(Class cls, Object primaryKey) + public List getRevisions(Class cls, String entityName, Object primaryKey) throws IllegalArgumentException, NotAuditedException, IllegalStateException { // todo: if a class is not versioned from the beginning, there's a missing ADD rev - what then? checkNotNull(cls, "Entity class"); + checkNotNull(entityName, "Entity name"); checkNotNull(primaryKey, "Primary key"); checkSession(); - String entityName = cls.getName(); - if (!verCfg.getEntCfg().isVersioned(entityName)) { throw new NotAuditedException(entityName, entityName + " is not versioned!"); } - return createQuery().forRevisionsOfEntity(cls, false, true) + return createQuery().forRevisionsOfEntity(cls, entityName, false, true) .addProjection(AuditEntity.revisionNumber()) .add(AuditEntity.id().eq(primaryKey)) .getResultList(); diff --git a/envers/src/main/java/org/hibernate/envers/tools/Tools.java b/envers/src/main/java/org/hibernate/envers/tools/Tools.java index a699ae36d2..6a420588b3 100644 --- a/envers/src/main/java/org/hibernate/envers/tools/Tools.java +++ b/envers/src/main/java/org/hibernate/envers/tools/Tools.java @@ -32,6 +32,7 @@ import java.util.*; /** * @author Adam Warski (adam at warski dot org) + * @author Hern�n Chanfreau */ public class Tools { public static Map newHashMap() { @@ -46,14 +47,14 @@ public class Tools { return new LinkedHashMap(); } - public static boolean entitiesEqual(SessionImplementor session, Object obj1, Object obj2) { - Object id1 = getIdentifier(session, obj1); - Object id2 = getIdentifier(session, obj2); + public static boolean entitiesEqual(SessionImplementor session, String entityName, Object obj1, Object obj2) { + Object id1 = getIdentifier(session, entityName, obj1); + Object id2 = getIdentifier(session, entityName, obj2); return objectsEqual(id1, id2); - } + } - public static Object getIdentifier(SessionImplementor session, Object obj) { + public static Object getIdentifier(SessionImplementor session, String entityName, Object obj) { if (obj == null) { return null; } @@ -63,9 +64,9 @@ public class Tools { return hibernateProxy.getHibernateLazyInitializer().getIdentifier(); } + return session.getEntityPersister(entityName, obj).getIdentifier(obj, session); + } - return session.getEntityPersister( null, obj ).getIdentifier( obj, session ); - } public static Object getTargetFromProxy(SessionFactoryImplementor sessionFactoryImplementor, HibernateProxy proxy) { if (!proxy.getHibernateLazyInitializer().isUninitialized()) { diff --git a/envers/src/test/java/org/hibernate/envers/test/AbstractSessionTest.java b/envers/src/test/java/org/hibernate/envers/test/AbstractSessionTest.java new file mode 100644 index 0000000000..d8488b3fbe --- /dev/null +++ b/envers/src/test/java/org/hibernate/envers/test/AbstractSessionTest.java @@ -0,0 +1,78 @@ +package org.hibernate.envers.test; + +import java.io.File; +import java.net.URISyntaxException; +import java.net.URL; + +import org.hibernate.MappingException; +import org.hibernate.Session; +import org.hibernate.SessionFactory; +import org.hibernate.cfg.AnnotationConfiguration; +import org.hibernate.cfg.Configuration; +import org.hibernate.envers.AuditReader; +import org.hibernate.envers.AuditReaderFactory; +import org.testng.annotations.*; + +/** + * Base class for testing envers with Session. + * + * @author Hern�n Chanfreau + * + */ +public abstract class AbstractSessionTest { + + protected Configuration config; + private SessionFactory sessionFactory; + private Session session ; + private AuditReader auditReader; + + + @BeforeClass + @Parameters("auditStrategy") + public void init(@Optional String auditStrategy) throws URISyntaxException { + config = new AnnotationConfiguration(); + URL url = Thread.currentThread().getContextClassLoader().getResource("hibernate.test.session-cfg.xml"); + config.configure(new File(url.toURI())); + + if (auditStrategy != null && !"".equals(auditStrategy)) { + config.setProperty("org.hibernate.envers.audit_strategy", auditStrategy); + } + + this.initMappings(); + + sessionFactory = config.buildSessionFactory(); + } + + protected abstract void initMappings() throws MappingException, URISyntaxException ; + + + + private SessionFactory getSessionFactory(){ + return sessionFactory; + } + + + @BeforeMethod + public void newSessionFactory() { + session = getSessionFactory().openSession(); + auditReader = AuditReaderFactory.get(session); + } + + @AfterClass + public void closeSessionFactory() { + sessionFactory.close(); + } + + + protected Session getSession() { + return session; + } + + + + protected AuditReader getAuditReader() { + return auditReader; + } + +} + diff --git a/envers/src/test/java/org/hibernate/envers/test/entityNames/auditedEntity/Person.java b/envers/src/test/java/org/hibernate/envers/test/entityNames/auditedEntity/Person.java new file mode 100644 index 0000000000..5e1d3851a5 --- /dev/null +++ b/envers/src/test/java/org/hibernate/envers/test/entityNames/auditedEntity/Person.java @@ -0,0 +1,51 @@ +package org.hibernate.envers.test.entityNames.auditedEntity; + +import org.hibernate.envers.Audited; + +/** + * @author Hern�n Chanfreau + * + */ + +@Audited +public class Person { + + private long id; + + private String name; + + private int age; + + public Person(){ } + + public Person(String name, int age){ + this.name = name; + this.age = age; + } + + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + +} diff --git a/envers/src/test/java/org/hibernate/envers/test/entityNames/auditedEntity/ReadEntityWhtiEntityNameTest.java b/envers/src/test/java/org/hibernate/envers/test/entityNames/auditedEntity/ReadEntityWhtiEntityNameTest.java new file mode 100644 index 0000000000..57ab54297d --- /dev/null +++ b/envers/src/test/java/org/hibernate/envers/test/entityNames/auditedEntity/ReadEntityWhtiEntityNameTest.java @@ -0,0 +1,99 @@ +package org.hibernate.envers.test.entityNames.auditedEntity; + +import java.io.File; +import java.net.URISyntaxException; +import java.net.URL; +import java.util.List; + +import org.hibernate.MappingException; +import org.hibernate.envers.test.AbstractSessionTest; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +/** + * @author Hern�n Chanfreau + * + */ + +public class ReadEntityWhtiEntityNameTest extends AbstractSessionTest{ + + private long id_pers1; + private long id_pers2; + private long id_pers3; + + + protected void initMappings() throws MappingException, URISyntaxException { + URL url = Thread.currentThread().getContextClassLoader().getResource("mappings/entityNames/auditedEntity/mappings.hbm.xml"); + config.addFile(new File(url.toURI())); + } + + + @BeforeClass(dependsOnMethods = "init") + public void initData() { + + newSessionFactory(); + + Person pers1 = new Person("Hernan", 28); + Person pers2 = new Person("Leandro", 29); + Person pers3 = new Person("Barba", 30); + + //REV 1 + getSession().getTransaction().begin(); + getSession().persist("Personaje",pers1); + id_pers1 = pers1.getId(); + getSession().getTransaction().commit(); + + //REV 2 + getSession().getTransaction().begin(); + pers1 = (Person)getSession().get("Personaje", id_pers1); + pers1.setAge(29); + getSession().persist("Personaje",pers1); + getSession().persist("Personaje",pers2); + id_pers2 = pers2.getId(); + getSession().getTransaction().commit(); + + //REV + getSession().getTransaction().begin(); + pers1 = (Person)getSession().get("Personaje", id_pers1); + pers1.setName("Hernan David"); + pers2 = (Person)getSession().get("Personaje", id_pers2); + pers2.setAge(30); + getSession().persist("Personaje",pers1); + getSession().persist("Personaje",pers2); + getSession().persist("Personaje",pers3); + id_pers3 = pers3.getId(); + getSession().getTransaction().commit(); + + } + + + @Test + public void testRetrieveRevisionsWithEntityName() { + List pers1Revs = getAuditReader().getRevisions(Person.class,"Personaje", id_pers1); + List pers2Revs = getAuditReader().getRevisions(Person.class,"Personaje", id_pers2); + List pers3Revs = getAuditReader().getRevisions(Person.class,"Personaje", id_pers3); + + assert(pers1Revs.size() == 3); + assert(pers2Revs.size() == 2); + assert(pers3Revs.size() == 1); + } + + @Test + public void testRetrieveAuditedEntityWithEntityName() { + Person Person1 = getAuditReader().find(Person.class, "Personaje", id_pers1, 1); + Person Person2 = getAuditReader().find(Person.class, "Personaje", id_pers1, 2); + Person Person3 = getAuditReader().find(Person.class, "Personaje", id_pers1, 3); + + System.out.println("Revision 1:"); + System.out.println(" > Name: " + Person1.getName()); + System.out.println(" > Age: " + Person1.getAge()); + System.out.println("Revision 2:"); + System.out.println(" > Name: " + Person2.getName()); + System.out.println(" > Age: " + Person2.getAge()); + System.out.println("Revision 3:"); + System.out.println(" > Name: " + Person3.getName()); + System.out.println(" > Age: " + Person3.getAge()); + } + + +} diff --git a/envers/src/test/java/org/hibernate/envers/test/entityNames/manyToManyAudited/Car.java b/envers/src/test/java/org/hibernate/envers/test/entityNames/manyToManyAudited/Car.java new file mode 100644 index 0000000000..020d2e818b --- /dev/null +++ b/envers/src/test/java/org/hibernate/envers/test/entityNames/manyToManyAudited/Car.java @@ -0,0 +1,56 @@ +package org.hibernate.envers.test.entityNames.manyToManyAudited; + +import java.util.List; + +import org.hibernate.envers.Audited; + +/** + * @author Hern�n Chanfreau + * + */ + +@Audited +public class Car { + + private long id; + + private int number; + + private List owners; + + + public Car() { } + + public Car(int number, List owners) { + this.number = number; + this.owners = owners; + } + + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + public List getOwners() { + return owners; + } + + public void setOwners(List owners) { + this.owners = owners; + } + + public int getNumber() { + return number; + } + + public void setNumber(int number) { + this.number = number; + } + + + +} diff --git a/envers/src/test/java/org/hibernate/envers/test/entityNames/manyToManyAudited/Person.java b/envers/src/test/java/org/hibernate/envers/test/entityNames/manyToManyAudited/Person.java new file mode 100644 index 0000000000..d67224f00b --- /dev/null +++ b/envers/src/test/java/org/hibernate/envers/test/entityNames/manyToManyAudited/Person.java @@ -0,0 +1,63 @@ +package org.hibernate.envers.test.entityNames.manyToManyAudited; + +import java.util.List; + +import org.hibernate.envers.Audited; + +/** + * @author Hern�n Chanfreau + * + */ + +@Audited +public class Person { + + private long id; + + private String name; + + private int age; + + private List cars; + + public Person(){ } + + public Person(String name, int age){ + this.name = name; + this.age = age; + } + + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + + public List getCars() { + return cars; + } + + public void setCars(List cars) { + this.cars = cars; + } + +} diff --git a/envers/src/test/java/org/hibernate/envers/test/entityNames/manyToManyAudited/ReadEntityWithAuditedManyToManyTest.java b/envers/src/test/java/org/hibernate/envers/test/entityNames/manyToManyAudited/ReadEntityWithAuditedManyToManyTest.java new file mode 100644 index 0000000000..b9b8616c71 --- /dev/null +++ b/envers/src/test/java/org/hibernate/envers/test/entityNames/manyToManyAudited/ReadEntityWithAuditedManyToManyTest.java @@ -0,0 +1,99 @@ +package org.hibernate.envers.test.entityNames.manyToManyAudited; + +import java.io.File; +import java.net.URISyntaxException; +import java.net.URL; +import java.util.ArrayList; +import java.util.List; + +import org.hibernate.MappingException; +import org.hibernate.envers.test.AbstractSessionTest; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +/** + * @author Hern�n Chanfreau + * + */ + +public class ReadEntityWithAuditedManyToManyTest extends AbstractSessionTest{ + + private long id_car1; + private long id_car2; + + private long id_pers1; + + protected void initMappings() throws MappingException, URISyntaxException { + URL url = Thread.currentThread().getContextClassLoader().getResource("mappings/entityNames/manyToManyAudited/mappings.hbm.xml"); + config.addFile(new File(url.toURI())); + } + + + @BeforeClass(dependsOnMethods = "init") + public void initData() { + + newSessionFactory(); + + Person pers1 = new Person("Hernan", 28); + Person pers2 = new Person("Leandro", 29); + Person pers3 = new Person("Barba", 32); + Person pers4 = new Person("Camomo", 15); + + //REV 1 + getSession().getTransaction().begin(); + List owners = new ArrayList(); + owners.add(pers1); + owners.add(pers2); + owners.add(pers3); + Car car1 = new Car(5, owners); + + getSession().persist(car1); + getSession().getTransaction().commit(); + id_pers1 = pers1.getId(); + id_car1 = car1.getId(); + + owners = new ArrayList(); + owners.add(pers2); + owners.add(pers3); + owners.add(pers4); + Car car2 = new Car(27, owners); + //REV 2 + getSession().getTransaction().begin(); + Person person1 = (Person)getSession().get("Personaje", id_pers1); + person1.setName("Hernan David"); + person1.setAge(40); + getSession().persist(car1); + getSession().persist(car2); + getSession().getTransaction().commit(); + id_car2 = car2.getId(); + + } + + @Test + public void testObtainManyYoManyWithEntityName() { + + Car car1 = getAuditReader().find(Car.class, id_car1, 2); + Car car2 = getAuditReader().find(Car.class, id_car2, 2); + + System.out.println(" > Car: " + car1.getNumber()); + System.out.println(" > Owners:"); + for (Person owner : car1.getOwners()) { + System.out.println(" > Name: " + owner.getName() + " - Age:" + owner.getAge()); + System.out.println(" > Cars owned:"); + for (Car ownedCar : owner.getCars()) { + System.out.println(" o Car: " + ownedCar.getNumber()); + } + } + System.out.println(" > Car: " + car2.getNumber()); + System.out.println(" > Owners:"); + for (Person owner : car2.getOwners()) { + System.out.println(" > Name: " + owner.getName() + " - Age:" + owner.getAge()); + System.out.println(" > Cars owned:"); + for (Car ownedCar : owner.getCars()) { + System.out.println(" o Car: " + ownedCar.getNumber()); + } + } + } + + +} diff --git a/envers/src/test/java/org/hibernate/envers/test/entityNames/oneToManyAudited/Car.java b/envers/src/test/java/org/hibernate/envers/test/entityNames/oneToManyAudited/Car.java new file mode 100644 index 0000000000..9e441290e5 --- /dev/null +++ b/envers/src/test/java/org/hibernate/envers/test/entityNames/oneToManyAudited/Car.java @@ -0,0 +1,56 @@ +package org.hibernate.envers.test.entityNames.oneToManyAudited; + +import java.util.List; + +import org.hibernate.envers.Audited; + +/** + * @author Hern�n Chanfreau + * + */ + +@Audited +public class Car { + + private long id; + + private int number; + + private List owners; + + + public Car() { } + + public Car(int number, List owners) { + this.number = number; + this.owners = owners; + } + + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + public List getOwners() { + return owners; + } + + public void setOwners(List owners) { + this.owners = owners; + } + + public int getNumber() { + return number; + } + + public void setNumber(int number) { + this.number = number; + } + + + +} diff --git a/envers/src/test/java/org/hibernate/envers/test/entityNames/oneToManyAudited/Person.java b/envers/src/test/java/org/hibernate/envers/test/entityNames/oneToManyAudited/Person.java new file mode 100644 index 0000000000..d040942d0b --- /dev/null +++ b/envers/src/test/java/org/hibernate/envers/test/entityNames/oneToManyAudited/Person.java @@ -0,0 +1,51 @@ +package org.hibernate.envers.test.entityNames.oneToManyAudited; + +import org.hibernate.envers.Audited; + +/** + * @author Hern�n Chanfreau + * + */ + +@Audited +public class Person { + + private long id; + + private String name; + + private int age; + + public Person(){ } + + public Person(String name, int age){ + this.name = name; + this.age = age; + } + + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + +} diff --git a/envers/src/test/java/org/hibernate/envers/test/entityNames/oneToManyAudited/ReadEntityWithAuditedCollectionTest.java b/envers/src/test/java/org/hibernate/envers/test/entityNames/oneToManyAudited/ReadEntityWithAuditedCollectionTest.java new file mode 100644 index 0000000000..9e03483e36 --- /dev/null +++ b/envers/src/test/java/org/hibernate/envers/test/entityNames/oneToManyAudited/ReadEntityWithAuditedCollectionTest.java @@ -0,0 +1,89 @@ +package org.hibernate.envers.test.entityNames.oneToManyAudited; + +import java.io.File; +import java.net.URISyntaxException; +import java.net.URL; +import java.util.ArrayList; +import java.util.List; + +import org.hibernate.MappingException; +import org.hibernate.envers.test.AbstractSessionTest; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +/** + * @author Hern�n Chanfreau + * + */ + +public class ReadEntityWithAuditedCollectionTest extends AbstractSessionTest{ + + private long id_car1; + private long id_car2; + + private long id_pers1; + + protected void initMappings() throws MappingException, URISyntaxException { + URL url = Thread.currentThread().getContextClassLoader().getResource("mappings/entityNames/oneToManyAudited/mappings.hbm.xml"); + config.addFile(new File(url.toURI())); + } + + + @BeforeClass(dependsOnMethods = "init") + public void initData() { + + newSessionFactory(); + + Person pers1 = new Person("Hernan", 28); + Person pers2 = new Person("Leandro", 29); + Person pers3 = new Person("Barba", 32); + Person pers4 = new Person("Camomo", 15); + + List owners = new ArrayList(); + owners.add(pers1); + owners.add(pers2); + Car car1 = new Car(5, owners); + + //REV 1 + getSession().getTransaction().begin(); + getSession().persist(car1); + getSession().getTransaction().commit(); + id_pers1 = pers1.getId(); + id_car1 = car1.getId(); + + owners = new ArrayList(); + owners.add(pers2); + owners.add(pers4); + Car car2 = new Car(27, owners); + //REV 2 + getSession().getTransaction().begin(); + Person person1 = (Person)getSession().get("Personaje", id_pers1); + person1.setName("Hernan David"); + person1.setAge(40); + getSession().persist(car1); + getSession().persist(car2); + getSession().getTransaction().commit(); + id_car2 = car2.getId(); + + } + + @Test + public void testObtainCollectionWithEntityName() { + + Car car1 = getAuditReader().find(Car.class, id_car1, 2); + Car car2 = getAuditReader().find(Car.class, id_car2, 2); + + System.out.println(" > Car: " + car1.getNumber()); + System.out.println(" > Owners:"); + for (Person owner : car1.getOwners()) { + System.out.println(" > Name: " + owner.getName() + " - Age:" + owner.getAge()); + } + System.out.println(" > Car: " + car2.getNumber()); + System.out.println(" > Owners:"); + for (Person owner : car2.getOwners()) { + System.out.println(" > Name: " + owner.getName() + " - Age:" + owner.getAge()); + } + } + + +} diff --git a/envers/src/test/java/org/hibernate/envers/test/entityNames/oneToManyNotAudited/Car.java b/envers/src/test/java/org/hibernate/envers/test/entityNames/oneToManyNotAudited/Car.java new file mode 100644 index 0000000000..677758d44f --- /dev/null +++ b/envers/src/test/java/org/hibernate/envers/test/entityNames/oneToManyNotAudited/Car.java @@ -0,0 +1,58 @@ +package org.hibernate.envers.test.entityNames.oneToManyNotAudited; + +import java.util.List; + +import org.hibernate.envers.Audited; +import org.hibernate.envers.RelationTargetAuditMode; + +/** + * @author Hern�n Chanfreau + * + */ + +public class Car { + + private long id; + + private int number; + + private List owners; + + + public Car() { } + + public Car(int number, List owners) { + this.number = number; + this.owners = owners; + } + + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + @Audited(targetAuditMode=RelationTargetAuditMode.NOT_AUDITED) + public List getOwners() { + return owners; + } + + public void setOwners(List owners) { + this.owners = owners; + } + + @Audited + public int getNumber() { + return number; + } + + public void setNumber(int number) { + this.number = number; + } + + + +} diff --git a/envers/src/test/java/org/hibernate/envers/test/entityNames/oneToManyNotAudited/Person.java b/envers/src/test/java/org/hibernate/envers/test/entityNames/oneToManyNotAudited/Person.java new file mode 100644 index 0000000000..925933b8ed --- /dev/null +++ b/envers/src/test/java/org/hibernate/envers/test/entityNames/oneToManyNotAudited/Person.java @@ -0,0 +1,48 @@ +package org.hibernate.envers.test.entityNames.oneToManyNotAudited; + +/** + * @author Hern�n Chanfreau + * + */ + +public class Person { + + private long id; + + private String name; + + private int age; + + public Person(){ } + + public Person(String name, int age){ + this.name = name; + this.age = age; + } + + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + +} diff --git a/envers/src/test/java/org/hibernate/envers/test/entityNames/oneToManyNotAudited/ReadEntityWithAuditedCollectionTest.java b/envers/src/test/java/org/hibernate/envers/test/entityNames/oneToManyNotAudited/ReadEntityWithAuditedCollectionTest.java new file mode 100644 index 0000000000..77b94492c1 --- /dev/null +++ b/envers/src/test/java/org/hibernate/envers/test/entityNames/oneToManyNotAudited/ReadEntityWithAuditedCollectionTest.java @@ -0,0 +1,84 @@ +package org.hibernate.envers.test.entityNames.oneToManyNotAudited; + +import java.io.File; +import java.net.URISyntaxException; +import java.net.URL; +import java.util.ArrayList; +import java.util.List; + +import org.hibernate.MappingException; +import org.hibernate.envers.test.AbstractSessionTest; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +public class ReadEntityWithAuditedCollectionTest extends AbstractSessionTest{ + + private long id_car1; + private long id_car2; + + private long id_pers1; + + protected void initMappings() throws MappingException, URISyntaxException { + URL url = Thread.currentThread().getContextClassLoader().getResource("mappings/entityNames/oneToManyNotAudited/mappings.hbm.xml"); + config.addFile(new File(url.toURI())); + } + + + @BeforeClass(dependsOnMethods = "init") + public void initData() { + + newSessionFactory(); + + Person pers1 = new Person("Hernan", 28); + Person pers2 = new Person("Leandro", 29); + Person pers3 = new Person("Barba", 32); + Person pers4 = new Person("Camomo", 15); + + List owners = new ArrayList(); + owners.add(pers1); + owners.add(pers2); + Car car1 = new Car(5, owners); + + //REV 1 + getSession().getTransaction().begin(); + getSession().persist(car1); + getSession().getTransaction().commit(); + id_pers1 = pers1.getId(); + id_car1 = car1.getId(); + + owners = new ArrayList(); + owners.add(pers2); + owners.add(pers4); + Car car2 = new Car(27, owners); + //REV 2 + getSession().getTransaction().begin(); + Person person1 = (Person)getSession().get("Personaje", id_pers1); + person1.setName("Hernan David"); + person1.setAge(40); + getSession().persist(car1); + getSession().persist(car2); + getSession().getTransaction().commit(); + id_car2 = car2.getId(); + + } + + @Test + public void testObtainCollectionWithEntityNameAndNotAuditedMode() { + + Car car1 = getAuditReader().find(Car.class, id_car1, 2); + Car car2 = getAuditReader().find(Car.class, id_car2, 2); + + System.out.println(" > Car: " + car1.getNumber()); + System.out.println(" > Owners:"); + for (Person owner : car1.getOwners()) { + System.out.println(" > Name: " + owner.getName() + " - Age:" + owner.getAge()); + } + System.out.println(" > Car: " + car2.getNumber()); + System.out.println(" > Owners:"); + for (Person owner : car2.getOwners()) { + System.out.println(" > Name: " + owner.getName() + " - Age:" + owner.getAge()); + } + } + + +} diff --git a/envers/src/test/java/org/hibernate/envers/test/entityNames/singleAssociatedAudited/Car.java b/envers/src/test/java/org/hibernate/envers/test/entityNames/singleAssociatedAudited/Car.java new file mode 100644 index 0000000000..80c046a2bb --- /dev/null +++ b/envers/src/test/java/org/hibernate/envers/test/entityNames/singleAssociatedAudited/Car.java @@ -0,0 +1,54 @@ +package org.hibernate.envers.test.entityNames.singleAssociatedAudited; + +import org.hibernate.envers.Audited; + +/** + * @author Hern�n Chanfreau + * + */ + +@Audited +public class Car { + + private long id; + + private int number; + + private Person owner; + + + public Car() { } + + public Car(int number, Person owner) { + this.number = number; + this.owner = owner; + } + + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + public Person getOwner() { + return owner; + } + + public void setOwner(Person owner) { + this.owner = owner; + } + + public int getNumber() { + return number; + } + + public void setNumber(int number) { + this.number = number; + } + + + +} diff --git a/envers/src/test/java/org/hibernate/envers/test/entityNames/singleAssociatedAudited/Person.java b/envers/src/test/java/org/hibernate/envers/test/entityNames/singleAssociatedAudited/Person.java new file mode 100644 index 0000000000..ae36685483 --- /dev/null +++ b/envers/src/test/java/org/hibernate/envers/test/entityNames/singleAssociatedAudited/Person.java @@ -0,0 +1,51 @@ +package org.hibernate.envers.test.entityNames.singleAssociatedAudited; + +import org.hibernate.envers.Audited; + +/** + * @author Hern�n Chanfreau + * + */ + +@Audited +public class Person { + + private long id; + + private String name; + + private int age; + + public Person(){ } + + public Person(String name, int age){ + this.name = name; + this.age = age; + } + + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + +} diff --git a/envers/src/test/java/org/hibernate/envers/test/entityNames/singleAssociatedAudited/ReadEntityAssociatedAuditedTest.java b/envers/src/test/java/org/hibernate/envers/test/entityNames/singleAssociatedAudited/ReadEntityAssociatedAuditedTest.java new file mode 100644 index 0000000000..19f5e435c0 --- /dev/null +++ b/envers/src/test/java/org/hibernate/envers/test/entityNames/singleAssociatedAudited/ReadEntityAssociatedAuditedTest.java @@ -0,0 +1,77 @@ +package org.hibernate.envers.test.entityNames.singleAssociatedAudited; + +import java.io.File; +import java.net.URISyntaxException; +import java.net.URL; + +import org.hibernate.MappingException; +import org.hibernate.envers.test.AbstractSessionTest; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +/** + * @author Hern�n Chanfreau + * + */ + +public class ReadEntityAssociatedAuditedTest extends AbstractSessionTest{ + + private long id_car1; + private long id_car2; + + private long id_pers1; + private long id_pers2; + + + protected void initMappings() throws MappingException, URISyntaxException { + URL url = Thread.currentThread().getContextClassLoader().getResource("mappings/entityNames/singleAssociatedAudited/mappings.hbm.xml"); + config.addFile(new File(url.toURI())); + } + + + @BeforeClass(dependsOnMethods = "init") + public void initData() { + + newSessionFactory(); + + Person pers1 = new Person("Hernan", 15); + Person pers2 = new Person("Leandro", 19); + + Car car1 = new Car(1, pers1); + Car car2 = new Car(2, pers2); + + //REV 1 + getSession().getTransaction().begin(); + getSession().persist("Personaje",pers1); + getSession().persist(car1); + getSession().getTransaction().commit(); + id_car1 = car1.getId(); + id_pers1 = pers1.getId(); + + //REV 2 + getSession().getTransaction().begin(); + pers1.setAge(50); + getSession().persist("Personaje", pers1); + getSession().persist("Personaje", pers2); + getSession().persist(car2); + getSession().getTransaction().commit(); + id_car2 = car2.getId(); + id_pers2 = pers2.getId(); + + } + + @Test + public void testGetAssociationWithEntityName() { + + Person person1 = (Person)getSession().get("Personaje", id_pers1); + Car car1 = getAuditReader().find(Car.class, id_car1, 1); + Person person1_1 = car1.getOwner(); + assert(person1.getAge() != person1_1.getAge()); + + Person person2 = (Person)getSession().get("Personaje", id_pers2); + Car car2 = getAuditReader().find(Car.class, id_car2, 2); + Person person2_1 = car2.getOwner(); + assert(person2.getAge() == person2_1.getAge()); + } + +} diff --git a/envers/src/test/java/org/hibernate/envers/test/entityNames/singleAssociatedNotAudited/Car.java b/envers/src/test/java/org/hibernate/envers/test/entityNames/singleAssociatedNotAudited/Car.java new file mode 100644 index 0000000000..e66431da05 --- /dev/null +++ b/envers/src/test/java/org/hibernate/envers/test/entityNames/singleAssociatedNotAudited/Car.java @@ -0,0 +1,56 @@ +package org.hibernate.envers.test.entityNames.singleAssociatedNotAudited; + +import org.hibernate.envers.Audited; +import org.hibernate.envers.RelationTargetAuditMode; + +/** + * @author Hern�n Chanfreau + * + */ + +public class Car { + + private long id; + + private int number; + + private Person owner; + + + public Car() { } + + public Car(int number, Person owner) { + this.number = number; + this.owner = owner; + } + + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + @Audited(targetAuditMode=RelationTargetAuditMode.NOT_AUDITED) + public Person getOwner() { + return owner; + } + + public void setOwner(Person owner) { + this.owner = owner; + } + + @Audited + public int getNumber() { + return number; + } + + public void setNumber(int number) { + this.number = number; + } + + + +} diff --git a/envers/src/test/java/org/hibernate/envers/test/entityNames/singleAssociatedNotAudited/Person.java b/envers/src/test/java/org/hibernate/envers/test/entityNames/singleAssociatedNotAudited/Person.java new file mode 100644 index 0000000000..58d35b5e2d --- /dev/null +++ b/envers/src/test/java/org/hibernate/envers/test/entityNames/singleAssociatedNotAudited/Person.java @@ -0,0 +1,48 @@ +package org.hibernate.envers.test.entityNames.singleAssociatedNotAudited; + +/** + * @author Hern�n Chanfreau + * + */ + +public class Person { + + private long id; + + private String name; + + private int age; + + public Person(){ } + + public Person(String name, int age){ + this.name = name; + this.age = age; + } + + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public int getAge() { + return age; + } + + public void setAge(int age) { + this.age = age; + } + +} diff --git a/envers/src/test/java/org/hibernate/envers/test/entityNames/singleAssociatedNotAudited/ReadEntityAssociatedNotAuditedTest.java b/envers/src/test/java/org/hibernate/envers/test/entityNames/singleAssociatedNotAudited/ReadEntityAssociatedNotAuditedTest.java new file mode 100644 index 0000000000..92fc089e98 --- /dev/null +++ b/envers/src/test/java/org/hibernate/envers/test/entityNames/singleAssociatedNotAudited/ReadEntityAssociatedNotAuditedTest.java @@ -0,0 +1,80 @@ +package org.hibernate.envers.test.entityNames.singleAssociatedNotAudited; + +import java.io.File; +import java.net.URISyntaxException; +import java.net.URL; + +import org.hibernate.MappingException; +import org.hibernate.envers.test.AbstractSessionTest; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.Test; + +/** + * @author Hern�n Chanfreau + * + */ + +public class ReadEntityAssociatedNotAuditedTest extends AbstractSessionTest{ + + private long id_car1; + private long id_car2; + + private long id_pers1; + private long id_pers2; + + + protected void initMappings() throws MappingException, URISyntaxException { + URL url = Thread.currentThread().getContextClassLoader().getResource("mappings/entityNames/singleAssociatedNotAudited/mappings.hbm.xml"); + config.addFile(new File(url.toURI())); + } + + + @BeforeClass(dependsOnMethods = "init") + public void initData() { + + newSessionFactory(); + + Person pers1 = new Person("Hernan", 15); + Person pers2 = new Person("Leandro", 19); + + Car car1 = new Car(1, pers1); + Car car2 = new Car(2, pers2); + + //REV 1 + getSession().getTransaction().begin(); + getSession().persist("Personaje",pers1); + getSession().persist(car1); + getSession().getTransaction().commit(); + id_car1 = car1.getId(); + id_pers1 = pers1.getId(); + + //REV 2 + getSession().getTransaction().begin(); + pers1.setAge(50); + getSession().persist("Personaje", pers1); + getSession().persist("Personaje", pers2); + getSession().persist(car2); + getSession().getTransaction().commit(); + id_car2 = car2.getId(); + id_pers2 = pers2.getId(); + + } + + @Test + public void testGetAssociationWithEntityNameAndNotAuditedMode() { + // persons from "actual" model + Person person1 = (Person)getSession().get("Personaje", id_pers1); + Person person2 = (Person)getSession().get("Personaje", id_pers2); + + Car car1 = getAuditReader().find(Car.class, id_car1, 1); + Car car2 = getAuditReader().find(Car.class, id_car2, 2); + + // persons from "historic" model + Person person1_1 = car1.getOwner(); + Person person2_1 = car2.getOwner(); + + assert(person1.getAge() == person1_1.getAge()); + assert(person2.getAge() == person2_1.getAge()); + } + +} diff --git a/envers/src/test/resources/hibernate.test.session-cfg.xml b/envers/src/test/resources/hibernate.test.session-cfg.xml new file mode 100644 index 0000000000..a5823a1ad1 --- /dev/null +++ b/envers/src/test/resources/hibernate.test.session-cfg.xml @@ -0,0 +1,46 @@ + + + + + + create-drop + + false + false + + org.hibernate.dialect.H2Dialect + jdbc:h2:mem:envers + org.h2.Driver + sa + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/envers/src/test/resources/mappings/entityNames/auditedEntity/mappings.hbm.xml b/envers/src/test/resources/mappings/entityNames/auditedEntity/mappings.hbm.xml new file mode 100644 index 0000000000..213b138e14 --- /dev/null +++ b/envers/src/test/resources/mappings/entityNames/auditedEntity/mappings.hbm.xml @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + diff --git a/envers/src/test/resources/mappings/entityNames/manyToManyAudited/mappings.hbm.xml b/envers/src/test/resources/mappings/entityNames/manyToManyAudited/mappings.hbm.xml new file mode 100644 index 0000000000..b32d654fa8 --- /dev/null +++ b/envers/src/test/resources/mappings/entityNames/manyToManyAudited/mappings.hbm.xml @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/envers/src/test/resources/mappings/entityNames/oneToManyAudited/mappings.hbm.xml b/envers/src/test/resources/mappings/entityNames/oneToManyAudited/mappings.hbm.xml new file mode 100644 index 0000000000..6d5b2e1b6e --- /dev/null +++ b/envers/src/test/resources/mappings/entityNames/oneToManyAudited/mappings.hbm.xml @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/envers/src/test/resources/mappings/entityNames/oneToManyNotAudited/mappings.hbm.xml b/envers/src/test/resources/mappings/entityNames/oneToManyNotAudited/mappings.hbm.xml new file mode 100644 index 0000000000..e9683d8718 --- /dev/null +++ b/envers/src/test/resources/mappings/entityNames/oneToManyNotAudited/mappings.hbm.xml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/envers/src/test/resources/mappings/entityNames/singleAssociatedAudited/mappings.hbm.xml b/envers/src/test/resources/mappings/entityNames/singleAssociatedAudited/mappings.hbm.xml new file mode 100644 index 0000000000..6cb5675034 --- /dev/null +++ b/envers/src/test/resources/mappings/entityNames/singleAssociatedAudited/mappings.hbm.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/envers/src/test/resources/mappings/entityNames/singleAssociatedNotAudited/mappings.hbm.xml b/envers/src/test/resources/mappings/entityNames/singleAssociatedNotAudited/mappings.hbm.xml new file mode 100644 index 0000000000..a7011fbda7 --- /dev/null +++ b/envers/src/test/resources/mappings/entityNames/singleAssociatedNotAudited/mappings.hbm.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/envers/src/test/resources/testng.xml b/envers/src/test/resources/testng.xml index 7bff7593cb..97371278b7 100644 --- a/envers/src/test/resources/testng.xml +++ b/envers/src/test/resources/testng.xml @@ -67,7 +67,13 @@ - + + + + + + + '> ]>