diff --git a/hibernate-envers/src/main/java/org/hibernate/envers/configuration/metadata/MetadataTools.java b/hibernate-envers/src/main/java/org/hibernate/envers/configuration/metadata/MetadataTools.java index a19ba5fcbf..6dcab46545 100644 --- a/hibernate-envers/src/main/java/org/hibernate/envers/configuration/metadata/MetadataTools.java +++ b/hibernate-envers/src/main/java/org/hibernate/envers/configuration/metadata/MetadataTools.java @@ -49,7 +49,7 @@ public class MetadataTools { if (useRevisionEntityWithNativeId) { generator_mapping.addAttribute("class", "native"); } else { - generator_mapping.addAttribute("class", "org.hibernate.id.enhanced.SequenceStyleGenerator"); + generator_mapping.addAttribute("class", "org.hibernate.envers.enhanced.OrderedSequenceGenerator"); generator_mapping.addElement("param").addAttribute("name", "sequence_name").setText("REVISION_GENERATOR"); generator_mapping.addElement("param").addAttribute("name", "table_name").setText("REVISION_GENERATOR"); generator_mapping.addElement("param").addAttribute("name", "initial_value").setText("1"); diff --git a/hibernate-envers/src/main/java/org/hibernate/envers/enhanced/OrderedSequenceGenerator.java b/hibernate-envers/src/main/java/org/hibernate/envers/enhanced/OrderedSequenceGenerator.java new file mode 100644 index 0000000000..9747280269 --- /dev/null +++ b/hibernate-envers/src/main/java/org/hibernate/envers/enhanced/OrderedSequenceGenerator.java @@ -0,0 +1,23 @@ +package org.hibernate.envers.enhanced; + +import org.hibernate.HibernateException; +import org.hibernate.dialect.Dialect; +import org.hibernate.dialect.Oracle8iDialect; +import org.hibernate.id.enhanced.SequenceStyleGenerator; +import org.hibernate.internal.util.StringHelper; + +/** + * Revision number generator has to produce values in ascending order (gaps may occur). + * @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com) + */ +public class OrderedSequenceGenerator extends SequenceStyleGenerator { + @Override + public String[] sqlCreateStrings(Dialect dialect) throws HibernateException { + String[] create = super.sqlCreateStrings( dialect ); + if ( dialect instanceof Oracle8iDialect ) { + // Make sure that sequence produces increasing values in Oracle RAC environment. + create = StringHelper.suffix( create, " order" ); + } + return create; + } +} diff --git a/hibernate-envers/src/main/java/org/hibernate/envers/enhanced/SequenceIdRevisionEntity.java b/hibernate-envers/src/main/java/org/hibernate/envers/enhanced/SequenceIdRevisionEntity.java index 6115723006..eb65728c88 100644 --- a/hibernate-envers/src/main/java/org/hibernate/envers/enhanced/SequenceIdRevisionEntity.java +++ b/hibernate-envers/src/main/java/org/hibernate/envers/enhanced/SequenceIdRevisionEntity.java @@ -47,7 +47,7 @@ public class SequenceIdRevisionEntity implements Serializable { @Id @GeneratedValue(generator = "RevisionNumberSequenceGenerator") @GenericGenerator(name = "RevisionNumberSequenceGenerator", - strategy = "org.hibernate.id.enhanced.SequenceStyleGenerator", + strategy = "org.hibernate.envers.enhanced.OrderedSequenceGenerator", parameters = {@Parameter(name = "table_name", value = "REVISION_GENERATOR"), @Parameter(name = "sequence_name", value = "REVISION_GENERATOR"), @Parameter(name = "initial_value", value = "1"), diff --git a/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/reventity/MonotonicRevisionNumberTest.java b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/reventity/MonotonicRevisionNumberTest.java new file mode 100644 index 0000000000..e42dbd66d0 --- /dev/null +++ b/hibernate-envers/src/test/java/org/hibernate/envers/test/integration/reventity/MonotonicRevisionNumberTest.java @@ -0,0 +1,38 @@ +package org.hibernate.envers.test.integration.reventity; + +import org.junit.Assert; +import org.junit.Test; + +import org.hibernate.dialect.Oracle8iDialect; +import org.hibernate.envers.enhanced.OrderedSequenceGenerator; +import org.hibernate.envers.enhanced.SequenceIdRevisionEntity; +import org.hibernate.envers.test.BaseEnversFunctionalTestCase; +import org.hibernate.envers.test.entities.StrIntTestEntity; +import org.hibernate.id.IdentifierGenerator; +import org.hibernate.persister.entity.EntityPersister; +import org.hibernate.testing.RequiresDialect; +import org.hibernate.testing.TestForIssue; + +/** + * @author Lukasz Antoniak (lukasz dot antoniak at gmail dot com) + */ +@TestForIssue(jiraKey = "HHH-7669") +@RequiresDialect(Oracle8iDialect.class) +public class MonotonicRevisionNumberTest extends BaseEnversFunctionalTestCase { + @Override + protected Class[] getAnnotatedClasses() { + return new Class[]{ StrIntTestEntity.class }; // Otherwise revision entity is not generated. + } + + @Test + public void testOracleSequenceOrder() { + EntityPersister persister = sessionFactory().getEntityPersister( SequenceIdRevisionEntity.class.getName() ); + IdentifierGenerator generator = persister.getIdentifierGenerator(); + Assert.assertTrue( OrderedSequenceGenerator.class.isInstance( generator ) ); + OrderedSequenceGenerator seqGenerator = (OrderedSequenceGenerator) generator; + Assert.assertTrue( + "Oracle sequence needs to be ordered in RAC environment.", + seqGenerator.sqlCreateStrings( getDialect() )[0].endsWith( " order" ) + ); + } +}