From 6f6b3264f3b87ea1478c7af2e0b8ac8bb046be4a Mon Sep 17 00:00:00 2001 From: Eric Haas Date: Fri, 16 Jan 2015 14:22:46 -0600 Subject: [PATCH] HHH-9043 Added the ability to customize the modified field name for audited fields. --- .../java/org/hibernate/envers/Audited.java | 6 ++ .../metadata/AuditMetadataGenerator.java | 5 +- .../internal/metadata/MetadataTools.java | 4 +- .../reader/AuditedPropertiesReader.java | 26 +++--- .../ComponentAuditedPropertiesReader.java | 12 ++- .../metadata/reader/PropertyAuditingData.java | 4 + .../naming/AuditColumnNameTest.java | 44 +++++++++++ .../integration/naming/NamingTestEntity2.java | 79 +++++++++++++++++++ 8 files changed, 164 insertions(+), 16 deletions(-) create mode 100644 hibernate-envers/src/test/java/org/hibernate/envers/test/integration/naming/AuditColumnNameTest.java create mode 100644 hibernate-envers/src/test/java/org/hibernate/envers/test/integration/naming/NamingTestEntity2.java diff --git a/hibernate-envers/src/main/java/org/hibernate/envers/Audited.java b/hibernate-envers/src/main/java/org/hibernate/envers/Audited.java index 5afb0f5905..e4e83a9c1f 100644 --- a/hibernate-envers/src/main/java/org/hibernate/envers/Audited.java +++ b/hibernate-envers/src/main/java/org/hibernate/envers/Audited.java @@ -73,4 +73,10 @@ public @interface Audited { * This can be used for example in queries. */ boolean withModifiedFlag() default false; + + /** + * The column name of the modified field. Analogous to the name attribute of the @{@link javax.persistence.Column} + * annotation. Ignored if withModifiedFlag is false. + */ + String modifiedColumnName() default ""; } diff --git a/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/metadata/AuditMetadataGenerator.java b/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/metadata/AuditMetadataGenerator.java index adb256a6d0..f24f214390 100644 --- a/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/metadata/AuditMetadataGenerator.java +++ b/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/metadata/AuditMetadataGenerator.java @@ -141,7 +141,7 @@ public final class AuditMetadataGenerator { revMapping.addAttribute( "name", verEntCfg.getRevisionFieldName() ); if ( globalCfg.isCascadeDeleteRevision() ) { revMapping.addAttribute( "on-delete", "cascade" ); - } + } MetadataTools.addOrModifyColumn( revMapping, verEntCfg.getRevisionFieldName() ); @@ -325,7 +325,8 @@ public final class AuditMetadataGenerator { MetadataTools.addModifiedFlagProperty( parent, propertyAuditingData.getName(), - globalCfg.getModifiedFlagSuffix() + globalCfg.getModifiedFlagSuffix(), + propertyAuditingData.getModifiedFlagName() ); } } diff --git a/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/metadata/MetadataTools.java b/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/metadata/MetadataTools.java index 4e74fe43e0..87f4972648 100644 --- a/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/metadata/MetadataTools.java +++ b/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/metadata/MetadataTools.java @@ -101,10 +101,10 @@ public final class MetadataTools { return addProperty( parent, name, type, insertable, false, key ); } - public static Element addModifiedFlagProperty(Element parent, String propertyName, String suffix) { + public static Element addModifiedFlagProperty(Element parent, String propertyName, String suffix, String modifiedFlagName) { return addProperty( parent, - getModifiedFlagPropertyName( propertyName, suffix ), + (modifiedFlagName != null) ? modifiedFlagName : getModifiedFlagPropertyName( propertyName, suffix ), "boolean", true, false, diff --git a/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/metadata/reader/AuditedPropertiesReader.java b/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/metadata/reader/AuditedPropertiesReader.java index cfc9218e7c..5b4c7f59ea 100644 --- a/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/metadata/reader/AuditedPropertiesReader.java +++ b/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/metadata/reader/AuditedPropertiesReader.java @@ -518,19 +518,12 @@ public class AuditedPropertiesReader { } } - - if ( !this.checkAudited( property, propertyData, allClassAudited ) ) { + final String propertyName = propertyNamePrefix + property.getName(); + if ( !this.checkAudited( property, propertyData,propertyName, allClassAudited, globalCfg.getModifiedFlagSuffix() ) ) { return false; } - final String propertyName = propertyNamePrefix + property.getName(); propertyData.setName( propertyName ); - propertyData.setModifiedFlagName( - MetadataTools.getModifiedFlagPropertyName( - propertyName, - globalCfg.getModifiedFlagSuffix() - ) - ); propertyData.setBeanName( property.getName() ); propertyData.setAccessType( accessType ); @@ -550,7 +543,8 @@ public class AuditedPropertiesReader { protected boolean checkAudited( XProperty property, - PropertyAuditingData propertyData, Audited allClassAudited) { + PropertyAuditingData propertyData, String propertyName, + Audited allClassAudited, String modifiedFlagSuffix) { // Checking if this property is explicitly audited or if all properties are. Audited aud = ( property.isAnnotationPresent( Audited.class ) ) ? property.getAnnotation( Audited.class ) @@ -566,6 +560,13 @@ public class AuditedPropertiesReader { propertyData.setStore( aud.modStore() ); propertyData.setRelationTargetAuditMode( aud.targetAuditMode() ); propertyData.setUsingModifiedFlag( checkUsingModifiedFlag( aud ) ); + if(aud.modifiedColumnName() != null && !"".equals(aud.modifiedColumnName())) { + propertyData.setModifiedFlagName(aud.modifiedColumnName()); + } else { + propertyData.setModifiedFlagName( + MetadataTools.getModifiedFlagPropertyName(propertyName, modifiedFlagSuffix) + ); + } return true; } else { @@ -682,6 +683,11 @@ public class AuditedPropertiesReader { return false; } + @Override + public String modifiedColumnName() { + return ""; + } + @Override public Class annotationType() { return this.getClass(); diff --git a/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/metadata/reader/ComponentAuditedPropertiesReader.java b/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/metadata/reader/ComponentAuditedPropertiesReader.java index fa7d250237..b4768f8aab 100644 --- a/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/metadata/reader/ComponentAuditedPropertiesReader.java +++ b/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/metadata/reader/ComponentAuditedPropertiesReader.java @@ -28,6 +28,7 @@ import org.hibernate.annotations.common.reflection.XProperty; import org.hibernate.envers.Audited; import org.hibernate.envers.ModificationStore; import org.hibernate.envers.configuration.internal.GlobalConfiguration; +import org.hibernate.envers.configuration.internal.metadata.MetadataTools; /** * Reads the audited properties for components. @@ -52,14 +53,21 @@ public class ComponentAuditedPropertiesReader extends AuditedPropertiesReader { @Override protected boolean checkAudited( XProperty property, - PropertyAuditingData propertyData, - Audited allClassAudited) { + PropertyAuditingData propertyData, String propertyName, + Audited allClassAudited, String modifiedFlagSuffix) { // Checking if this property is explicitly audited or if all properties are. final Audited aud = property.getAnnotation( Audited.class ); if ( aud != null ) { propertyData.setStore( aud.modStore() ); propertyData.setRelationTargetAuditMode( aud.targetAuditMode() ); propertyData.setUsingModifiedFlag( checkUsingModifiedFlag( aud ) ); + if(aud.modifiedColumnName() != null && !"".equals(aud.modifiedColumnName())) { + propertyData.setModifiedFlagName(aud.modifiedColumnName()); + } else { + propertyData.setModifiedFlagName( + MetadataTools.getModifiedFlagPropertyName( propertyName, modifiedFlagSuffix ) + ); + } } else { propertyData.setStore( ModificationStore.FULL ); diff --git a/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/metadata/reader/PropertyAuditingData.java b/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/metadata/reader/PropertyAuditingData.java index 85d4424c8d..b4982c5e50 100644 --- a/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/metadata/reader/PropertyAuditingData.java +++ b/hibernate-envers/src/main/java/org/hibernate/envers/configuration/internal/metadata/reader/PropertyAuditingData.java @@ -170,6 +170,10 @@ public class PropertyAuditingData { this.usingModifiedFlag = usingModifiedFlag; } + public String getModifiedFlagName() { + return modifiedFlagName; + } + public void setModifiedFlagName(String modifiedFlagName) { this.modifiedFlagName = modifiedFlagName; } diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/naming/AuditColumnNameTest.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/naming/AuditColumnNameTest.java new file mode 100644 index 0000000000..dc57b7d47f --- /dev/null +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/naming/AuditColumnNameTest.java @@ -0,0 +1,44 @@ +package org.hibernate.envers.test.integration.naming; + +import java.util.List; +import javax.persistence.EntityManager; +import javax.persistence.Query; +import org.hibernate.envers.test.BaseEnversJPAFunctionalTestCase; +import org.hibernate.envers.test.Priority; +import org.junit.Assert; +import org.junit.Test; + +public class AuditColumnNameTest extends BaseEnversJPAFunctionalTestCase { + private Integer id; + + @Override + protected Class[] getAnnotatedClasses() { + return new Class[] {NamingTestEntity2.class}; + } + + @Test + @Priority(10) + public void initData() { + NamingTestEntity2 nte1 = new NamingTestEntity2("data1" ); + EntityManager em = getEntityManager(); + em.getTransaction().begin(); + em.persist( nte1 ); + em.getTransaction().commit(); + this.id = nte1.getId(); + } + + @Test + public void testColumnName() { + EntityManager em = getEntityManager(); + em.getTransaction().begin(); + Query query = em.createNativeQuery( + "select nte_data, data_MOD_different from naming_test_entity_2_versions where nte_id = :nteId"); + query.setParameter("nteId", this.id); + List resultList = query.getResultList(); + Assert.assertNotNull(resultList); + Assert.assertTrue(resultList.size() > 0); + Object[] result = resultList.get(0); + Assert.assertEquals(result.length, 2); + em.getTransaction().commit(); + } +} diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/naming/NamingTestEntity2.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/naming/NamingTestEntity2.java new file mode 100644 index 0000000000..25aec49b95 --- /dev/null +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/naming/NamingTestEntity2.java @@ -0,0 +1,79 @@ +package org.hibernate.envers.test.integration.naming; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.Id; +import javax.persistence.Table; +import org.hibernate.envers.AuditTable; +import org.hibernate.envers.Audited; + +@Entity +@Table(name = "naming_test_entity_2") +@AuditTable("naming_test_entity_2_versions") +public class NamingTestEntity2 { + @Id + @GeneratedValue + @Column(name = "nte_id") + @Audited(withModifiedFlag = true) + private Integer id; + + @Column(name = "nte_data") + @Audited(withModifiedFlag = true, modifiedColumnName = "data_MOD_different") + private String data; + + public NamingTestEntity2() { + } + + public NamingTestEntity2(String data) { + this.data = data; + } + + public NamingTestEntity2(Integer id, String data) { + this.id = id; + this.data = data; + } + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getData() { + return data; + } + + public void setData(String data) { + this.data = data; + } + + public boolean equals(Object o) { + if ( this == o ) { + return true; + } + if ( !(o instanceof NamingTestEntity2) ) { + return false; + } + + NamingTestEntity2 that = (NamingTestEntity2) o; + + if ( data != null ? !data.equals( that.data ) : that.data != null ) { + return false; + } + if ( id != null ? !id.equals( that.id ) : that.id != null ) { + return false; + } + + return true; + } + + public int hashCode() { + int result; + result = (id != null ? id.hashCode() : 0); + result = 31 * result + (data != null ? data.hashCode() : 0); + return result; + } +}