Added the ability to customize the modified field name for audited fields.
This commit is contained in:
Eric Haas 2015-01-16 14:22:46 -06:00 committed by Brett Meyer
parent 3cc8cb3113
commit 6f6b3264f3
8 changed files with 164 additions and 16 deletions

View File

@ -73,4 +73,10 @@ public @interface Audited {
* This can be used for example in queries. * This can be used for example in queries.
*/ */
boolean withModifiedFlag() default false; 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 "";
} }

View File

@ -141,7 +141,7 @@ public final class AuditMetadataGenerator {
revMapping.addAttribute( "name", verEntCfg.getRevisionFieldName() ); revMapping.addAttribute( "name", verEntCfg.getRevisionFieldName() );
if ( globalCfg.isCascadeDeleteRevision() ) { if ( globalCfg.isCascadeDeleteRevision() ) {
revMapping.addAttribute( "on-delete", "cascade" ); revMapping.addAttribute( "on-delete", "cascade" );
} }
MetadataTools.addOrModifyColumn( revMapping, verEntCfg.getRevisionFieldName() ); MetadataTools.addOrModifyColumn( revMapping, verEntCfg.getRevisionFieldName() );
@ -325,7 +325,8 @@ public final class AuditMetadataGenerator {
MetadataTools.addModifiedFlagProperty( MetadataTools.addModifiedFlagProperty(
parent, parent,
propertyAuditingData.getName(), propertyAuditingData.getName(),
globalCfg.getModifiedFlagSuffix() globalCfg.getModifiedFlagSuffix(),
propertyAuditingData.getModifiedFlagName()
); );
} }
} }

View File

@ -101,10 +101,10 @@ public final class MetadataTools {
return addProperty( parent, name, type, insertable, false, key ); 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( return addProperty(
parent, parent,
getModifiedFlagPropertyName( propertyName, suffix ), (modifiedFlagName != null) ? modifiedFlagName : getModifiedFlagPropertyName( propertyName, suffix ),
"boolean", "boolean",
true, true,
false, false,

View File

@ -518,19 +518,12 @@ public class AuditedPropertiesReader {
} }
} }
final String propertyName = propertyNamePrefix + property.getName();
if ( !this.checkAudited( property, propertyData, allClassAudited ) ) { if ( !this.checkAudited( property, propertyData,propertyName, allClassAudited, globalCfg.getModifiedFlagSuffix() ) ) {
return false; return false;
} }
final String propertyName = propertyNamePrefix + property.getName();
propertyData.setName( propertyName ); propertyData.setName( propertyName );
propertyData.setModifiedFlagName(
MetadataTools.getModifiedFlagPropertyName(
propertyName,
globalCfg.getModifiedFlagSuffix()
)
);
propertyData.setBeanName( property.getName() ); propertyData.setBeanName( property.getName() );
propertyData.setAccessType( accessType ); propertyData.setAccessType( accessType );
@ -550,7 +543,8 @@ public class AuditedPropertiesReader {
protected boolean checkAudited( protected boolean checkAudited(
XProperty property, 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. // Checking if this property is explicitly audited or if all properties are.
Audited aud = ( property.isAnnotationPresent( Audited.class ) ) Audited aud = ( property.isAnnotationPresent( Audited.class ) )
? property.getAnnotation( Audited.class ) ? property.getAnnotation( Audited.class )
@ -566,6 +560,13 @@ public class AuditedPropertiesReader {
propertyData.setStore( aud.modStore() ); propertyData.setStore( aud.modStore() );
propertyData.setRelationTargetAuditMode( aud.targetAuditMode() ); propertyData.setRelationTargetAuditMode( aud.targetAuditMode() );
propertyData.setUsingModifiedFlag( checkUsingModifiedFlag( aud ) ); propertyData.setUsingModifiedFlag( checkUsingModifiedFlag( aud ) );
if(aud.modifiedColumnName() != null && !"".equals(aud.modifiedColumnName())) {
propertyData.setModifiedFlagName(aud.modifiedColumnName());
} else {
propertyData.setModifiedFlagName(
MetadataTools.getModifiedFlagPropertyName(propertyName, modifiedFlagSuffix)
);
}
return true; return true;
} }
else { else {
@ -682,6 +683,11 @@ public class AuditedPropertiesReader {
return false; return false;
} }
@Override
public String modifiedColumnName() {
return "";
}
@Override @Override
public Class<? extends Annotation> annotationType() { public Class<? extends Annotation> annotationType() {
return this.getClass(); return this.getClass();

View File

@ -28,6 +28,7 @@ import org.hibernate.annotations.common.reflection.XProperty;
import org.hibernate.envers.Audited; import org.hibernate.envers.Audited;
import org.hibernate.envers.ModificationStore; import org.hibernate.envers.ModificationStore;
import org.hibernate.envers.configuration.internal.GlobalConfiguration; import org.hibernate.envers.configuration.internal.GlobalConfiguration;
import org.hibernate.envers.configuration.internal.metadata.MetadataTools;
/** /**
* Reads the audited properties for components. * Reads the audited properties for components.
@ -52,14 +53,21 @@ public class ComponentAuditedPropertiesReader extends AuditedPropertiesReader {
@Override @Override
protected boolean checkAudited( protected boolean checkAudited(
XProperty property, XProperty property,
PropertyAuditingData propertyData, PropertyAuditingData propertyData, String propertyName,
Audited allClassAudited) { Audited allClassAudited, String modifiedFlagSuffix) {
// Checking if this property is explicitly audited or if all properties are. // Checking if this property is explicitly audited or if all properties are.
final Audited aud = property.getAnnotation( Audited.class ); final Audited aud = property.getAnnotation( Audited.class );
if ( aud != null ) { if ( aud != null ) {
propertyData.setStore( aud.modStore() ); propertyData.setStore( aud.modStore() );
propertyData.setRelationTargetAuditMode( aud.targetAuditMode() ); propertyData.setRelationTargetAuditMode( aud.targetAuditMode() );
propertyData.setUsingModifiedFlag( checkUsingModifiedFlag( aud ) ); propertyData.setUsingModifiedFlag( checkUsingModifiedFlag( aud ) );
if(aud.modifiedColumnName() != null && !"".equals(aud.modifiedColumnName())) {
propertyData.setModifiedFlagName(aud.modifiedColumnName());
} else {
propertyData.setModifiedFlagName(
MetadataTools.getModifiedFlagPropertyName( propertyName, modifiedFlagSuffix )
);
}
} }
else { else {
propertyData.setStore( ModificationStore.FULL ); propertyData.setStore( ModificationStore.FULL );

View File

@ -170,6 +170,10 @@ public class PropertyAuditingData {
this.usingModifiedFlag = usingModifiedFlag; this.usingModifiedFlag = usingModifiedFlag;
} }
public String getModifiedFlagName() {
return modifiedFlagName;
}
public void setModifiedFlagName(String modifiedFlagName) { public void setModifiedFlagName(String modifiedFlagName) {
this.modifiedFlagName = modifiedFlagName; this.modifiedFlagName = modifiedFlagName;
} }

View File

@ -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<Object[]> resultList = query.getResultList();
Assert.assertNotNull(resultList);
Assert.assertTrue(resultList.size() > 0);
Object[] result = resultList.get(0);
Assert.assertEquals(result.length, 2);
em.getTransaction().commit();
}
}

View File

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