HHH-6210 Added config option to allow revend timestamp fields to be long data types
This commit is contained in:
parent
1abf044f2e
commit
205f0ce9bf
|
@ -257,6 +257,10 @@ This property is only evaluated if the `ValidityAuditStrategy` is used.
|
|||
Column name of the timestamp of the end revision until which the data was valid.
|
||||
Only used if the `ValidityAuditStrategy` is used, and `org.hibernate.envers.audit_strategy_validity_store_revend_timestamp` evaluates to true.
|
||||
|
||||
`*org.hibernate.envers.audit_strategy_validity_revend_timestamp_numeric*`(default: `false` )::
|
||||
Boolean flag that controls whether the revision end timestamp field is treated as a `Long` data type.
|
||||
Only used if the `ValidityAuditStrategy` is used, and `org.hibernate.envers.audit_strategy_validity_store_revend_timestamp` evaluates to true.
|
||||
|
||||
`*org.hibernate.envers.use_revision_entity_with_native_id*` (default: `true` )::
|
||||
Boolean flag that determines the strategy of revision number generation.
|
||||
Default implementation of revision entity uses native identifier generator.
|
||||
|
@ -320,6 +324,7 @@ The following configuration options have been added recently and should be regar
|
|||
. `org.hibernate.envers.modified_column_naming_strategy`
|
||||
. `org.hibernate.envers.original_id_prop_name`
|
||||
. `org.hibernate.envers.find_by_revision_exact_match`
|
||||
. `org.hibernate.envers.audit_strategy_validity_revend_timestamp_numeric`
|
||||
====
|
||||
|
||||
[[envers-additional-mappings]]
|
||||
|
@ -1489,6 +1494,8 @@ Optionally, you can also override the default values using following properties:
|
|||
|
||||
`org.hibernate.envers.audit_strategy_validity_revend_timestamp_field_name`
|
||||
|
||||
`org.hibernate.envers.audit_strategy_validity_revend_timestamp_numeric`
|
||||
|
||||
For more information, see <<envers-configuration>>.
|
||||
====
|
||||
|
||||
|
|
|
@ -90,6 +90,7 @@ public class Configuration {
|
|||
private final String revisionEndTimestampFieldName;
|
||||
private final String embeddableSetOrdinalPropertyName;
|
||||
private final boolean revisionEndTimestampEnabled;
|
||||
private final boolean revisionEndTimestampNumeric;
|
||||
|
||||
private final Map<String, String> customAuditTableNames = new HashMap<>();
|
||||
|
||||
|
@ -152,9 +153,14 @@ public class Configuration {
|
|||
EnversSettings.AUDIT_STRATEGY_VALIDITY_REVEND_TIMESTAMP_FIELD_NAME,
|
||||
DEFAULT_REV_TSTMP_FIELD
|
||||
);
|
||||
revisionEndTimestampNumeric = configProps.getBoolean(
|
||||
EnversSettings.AUDIT_STRATEGY_VALIDITY_REVEND_TIMESTAMP_NUMERIC,
|
||||
false
|
||||
);
|
||||
}
|
||||
else {
|
||||
revisionEndTimestampFieldName = null;
|
||||
revisionEndTimestampNumeric = false;
|
||||
}
|
||||
|
||||
embeddableSetOrdinalPropertyName = configProps.getString(
|
||||
|
@ -219,6 +225,10 @@ public class Configuration {
|
|||
return revisionEndTimestampEnabled;
|
||||
}
|
||||
|
||||
public boolean isRevisionEndTimestampNumeric() {
|
||||
return revisionEndTimestampNumeric;
|
||||
}
|
||||
|
||||
public String getDefaultCatalogName() {
|
||||
return defaultCatalogName;
|
||||
}
|
||||
|
|
|
@ -110,6 +110,14 @@ public interface EnversSettings {
|
|||
*/
|
||||
String AUDIT_STRATEGY_VALIDITY_REVEND_TIMESTAMP_FIELD_NAME = "org.hibernate.envers.audit_strategy_validity_revend_timestamp_field_name";
|
||||
|
||||
/**
|
||||
* Determines whether the timestamp of the end revision is stored as a numeric data type.
|
||||
* Defaults to {@literal false}.
|
||||
*
|
||||
* @since 6.0
|
||||
*/
|
||||
String AUDIT_STRATEGY_VALIDITY_REVEND_TIMESTAMP_NUMERIC = "org.hibernate.envers.audit_strategy_validity_revend_timestamp_numeric";
|
||||
|
||||
/**
|
||||
* Name of column used for storing ordinal of the change in sets of embeddable elements. Defaults to {@literal SETORDINAL}.
|
||||
*/
|
||||
|
|
|
@ -109,7 +109,13 @@ public class ValidityAuditStrategy implements AuditStrategy {
|
|||
|
||||
if ( mappingContext.getConfiguration().isRevisionEndTimestampEnabled() ) {
|
||||
// add a column for the timestamp of the end revision
|
||||
final String revisionInfoTimestampTypeName = StandardBasicTypes.TIMESTAMP.getName();
|
||||
final String revisionInfoTimestampTypeName;
|
||||
if ( mappingContext.getConfiguration().isRevisionEndTimestampNumeric() ) {
|
||||
revisionInfoTimestampTypeName = StandardBasicTypes.LONG.getName();
|
||||
}
|
||||
else {
|
||||
revisionInfoTimestampTypeName = StandardBasicTypes.TIMESTAMP.getName();
|
||||
}
|
||||
final BasicAttribute revEndTimestampMapping = new BasicAttribute(
|
||||
mappingContext.getConfiguration().getRevisionEndTimestampFieldName(),
|
||||
revisionInfoTimestampTypeName,
|
||||
|
@ -225,13 +231,11 @@ public class ValidityAuditStrategy implements AuditStrategy {
|
|||
// set [, REVEND_TSTMP = ?]
|
||||
if ( isRevisionEndTimestampEnabled ) {
|
||||
final Object revEndTimestampObj = revisionTimestampGetter.get( revision );
|
||||
final Date revisionEndTimestamp = convertRevEndTimestampToDate( revEndTimestampObj );
|
||||
final Object revEndValue = getRevEndTimestampValue( configuration, revEndTimestampObj );
|
||||
final Type revEndTsType = rootAuditedEntityQueryable.getPropertyType(
|
||||
configuration.getRevisionEndTimestampFieldName()
|
||||
);
|
||||
revEndTsType.nullSafeSet(
|
||||
preparedStatement, revisionEndTimestamp, index, sessionImplementor
|
||||
);
|
||||
revEndTsType.nullSafeSet( preparedStatement, revEndValue, index, sessionImplementor );
|
||||
index += revEndTsType.getColumnSpan( sessionImplementor.getFactory() );
|
||||
}
|
||||
|
||||
|
@ -445,6 +449,20 @@ public class ValidityAuditStrategy implements AuditStrategy {
|
|||
return new Date( (Long) revEndTimestampObj );
|
||||
}
|
||||
|
||||
private Long convertRevEndTimestampToLong(Object revEndTimstampObj) {
|
||||
if ( revEndTimstampObj instanceof Date ) {
|
||||
return ( (Date) revEndTimstampObj ).getTime();
|
||||
}
|
||||
return (Long) revEndTimstampObj;
|
||||
}
|
||||
|
||||
private Object getRevEndTimestampValue(Configuration configuration, Object value) {
|
||||
if ( configuration.isRevisionEndTimestampNumeric() ) {
|
||||
return convertRevEndTimestampToLong( value );
|
||||
}
|
||||
return convertRevEndTimestampToDate( value );
|
||||
}
|
||||
|
||||
private Queryable getQueryable(String entityName, SessionImplementor sessionImplementor) {
|
||||
return (Queryable) sessionImplementor.getFactory().getMetamodel().entityPersister( entityName );
|
||||
}
|
||||
|
|
|
@ -0,0 +1,61 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
*/
|
||||
package org.hibernate.orm.test.envers.integration.strategy;
|
||||
|
||||
import static org.hibernate.testing.junit4.ExtraAssertions.assertTyping;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.hibernate.envers.configuration.EnversSettings;
|
||||
|
||||
import org.hibernate.envers.strategy.internal.ValidityAuditStrategy;
|
||||
import org.hibernate.mapping.PersistentClass;
|
||||
import org.hibernate.mapping.Property;
|
||||
import org.hibernate.orm.test.envers.BaseEnversJPAFunctionalTestCase;
|
||||
import org.hibernate.orm.test.envers.entities.StrTestEntity;
|
||||
import org.hibernate.type.BasicType;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
import org.hibernate.testing.envers.RequiresAuditStrategy;
|
||||
|
||||
/**
|
||||
* Tests the {@code REVEND} functionality using a {@code LONG} data type.
|
||||
* This is only applicable with the ValidityAuditStrategy.
|
||||
*
|
||||
* @author Chris Cranford
|
||||
*/
|
||||
@TestForIssue( jiraKey = "HHH-6210" )
|
||||
@RequiresAuditStrategy( value = ValidityAuditStrategy.class, jiraKey = "HHH-6210" )
|
||||
public class RevisionEndNumericTypeTest extends BaseEnversJPAFunctionalTestCase {
|
||||
|
||||
@Override
|
||||
protected Class<?>[] getAnnotatedClasses() {
|
||||
return new Class[] { StrTestEntity.class };
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addConfigOptions(Map options) {
|
||||
super.addConfigOptions( options );
|
||||
options.put( EnversSettings.AUDIT_STRATEGY_VALIDITY_STORE_REVEND_TIMESTAMP, "true" );
|
||||
options.put( EnversSettings.AUDIT_STRATEGY_VALIDITY_REVEND_TIMESTAMP_NUMERIC, "true" );
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testRevisionEndTimestampIsTimestampType() {
|
||||
// get the entity and verify the revision end timestamp property exists
|
||||
final PersistentClass clazz = metadata().getEntityBinding( StrTestEntity.class.getName() + "_AUD" );
|
||||
assertTrue( clazz.hasProperty( "REVEND_TSTMP" ) );
|
||||
|
||||
final Property property = clazz.getProperty( "REVEND_TSTMP" );
|
||||
assertTyping( BasicType.class, clazz.getProperty( "REVEND_TSTMP" ).getType() );
|
||||
assertEquals( Long.class, ( (BasicType) property.getType() ).getJavaType() );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
|
||||
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
|
||||
*/
|
||||
package org.hibernate.orm.test.envers.integration.strategy;
|
||||
|
||||
import static org.hibernate.testing.junit4.ExtraAssertions.assertTyping;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.sql.Timestamp;
|
||||
import java.util.Map;
|
||||
|
||||
import org.hibernate.envers.configuration.EnversSettings;
|
||||
|
||||
import org.hibernate.envers.strategy.internal.ValidityAuditStrategy;
|
||||
import org.hibernate.mapping.PersistentClass;
|
||||
import org.hibernate.mapping.Property;
|
||||
import org.hibernate.orm.test.envers.BaseEnversJPAFunctionalTestCase;
|
||||
import org.hibernate.orm.test.envers.entities.StrTestEntity;
|
||||
import org.hibernate.type.BasicType;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.hibernate.testing.TestForIssue;
|
||||
import org.hibernate.testing.envers.RequiresAuditStrategy;
|
||||
|
||||
/**
|
||||
* Tests the {@code REVEND} functionality using a {@code LONG} data type.
|
||||
* This is only applicable with the ValidityAuditStrategy.
|
||||
*
|
||||
* @author Chris Cranford
|
||||
*/
|
||||
@TestForIssue( jiraKey = "HHH-6210" )
|
||||
@RequiresAuditStrategy( value = ValidityAuditStrategy.class, jiraKey = "HHH-6210" )
|
||||
public class RevisionEndTimestampTypeTest extends BaseEnversJPAFunctionalTestCase {
|
||||
|
||||
@Override
|
||||
protected Class<?>[] getAnnotatedClasses() {
|
||||
return new Class[] { StrTestEntity.class };
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addConfigOptions(Map options) {
|
||||
options.put( EnversSettings.AUDIT_STRATEGY_VALIDITY_STORE_REVEND_TIMESTAMP, "true" );
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRevisionEndTimestampIsLongType() {
|
||||
// get the entity and verify the revision end timestamp property exists
|
||||
final PersistentClass clazz = metadata().getEntityBinding( StrTestEntity.class.getName() + "_AUD" );
|
||||
|
||||
final Property property = clazz.getProperty( "REVEND_TSTMP" );
|
||||
assertTyping( BasicType.class, property.getType() );
|
||||
assertEquals( Timestamp.class, ( (BasicType) property.getType() ).getJavaType() );
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue