[hibernate-commits] Hibernate SVN: r19480 - in core/branches/Branch_3_5: core/src/main/java/org/hibernate/cfg and 3 other directories.

hibernate-commits at lists.jboss.org hibernate-commits at lists.jboss.org
Wed May 12 14:19:01 EDT 2010


Author: steve.ebersole at jboss.com
Date: 2010-05-12 14:19:00 -0400 (Wed, 12 May 2010)
New Revision: 19480

Modified:
   core/branches/Branch_3_5/annotations/src/main/java/org/hibernate/cfg/BinderHelper.java
   core/branches/Branch_3_5/core/src/main/java/org/hibernate/cfg/Environment.java
   core/branches/Branch_3_5/core/src/main/java/org/hibernate/cfg/HbmBinder.java
   core/branches/Branch_3_5/core/src/main/java/org/hibernate/id/enhanced/OptimizerFactory.java
   core/branches/Branch_3_5/core/src/main/java/org/hibernate/id/enhanced/SequenceStyleGenerator.java
   core/branches/Branch_3_5/core/src/main/java/org/hibernate/id/enhanced/TableGenerator.java
   core/branches/Branch_3_5/core/src/main/java/org/hibernate/mapping/SimpleValue.java
   core/branches/Branch_3_5/core/src/test/java/org/hibernate/id/enhanced/OptimizerUnitTest.java
   core/branches/Branch_3_5/core/src/test/java/org/hibernate/id/enhanced/SequenceStyleConfigUnitTest.java
Log:
HHH-5218 - Provide a new "pooled value" based optimizer which interprets the database value as the low boundary instead of upper boundary

Modified: core/branches/Branch_3_5/annotations/src/main/java/org/hibernate/cfg/BinderHelper.java
===================================================================
--- core/branches/Branch_3_5/annotations/src/main/java/org/hibernate/cfg/BinderHelper.java	2010-05-12 17:17:45 UTC (rev 19479)
+++ core/branches/Branch_3_5/annotations/src/main/java/org/hibernate/cfg/BinderHelper.java	2010-05-12 18:19:00 UTC (rev 19480)
@@ -434,9 +434,7 @@
 	 * Find the column owner (ie PersistentClass or Join) of columnName.
 	 * If columnName is null or empty, persistentClass is returned
 	 */
-	public static Object findColumnOwner(
-			PersistentClass persistentClass, String columnName, ExtendedMappings mappings
-	) {
+	public static Object findColumnOwner(PersistentClass persistentClass, String columnName, ExtendedMappings mappings) {
 		if ( StringHelper.isEmpty( columnName ) ) {
 			return persistentClass; //shortcut for implicit referenced column names
 		}
@@ -475,9 +473,11 @@
 	 * apply an id generator to a SimpleValue
 	 */
 	public static void makeIdGenerator(
-			SimpleValue id, String generatorType, String generatorName, ExtendedMappings mappings,
-			Map<String, IdGenerator> localGenerators
-	) {
+			SimpleValue id,
+			String generatorType,
+			String generatorName,
+			ExtendedMappings mappings,
+			Map<String, IdGenerator> localGenerators) {
 		Table table = id.getTable();
 		table.setIdentifierValue( id );
 		//generator settings
@@ -520,7 +520,16 @@
 				params.setProperty( (String) elt.getKey(), (String) elt.getValue() );
 			}
 		}
-		if ( "assigned".equals( generatorType ) ) id.setNullValue( "undefined" );
+
+		if ( "assigned".equals( generatorType ) ) {
+			id.setNullValue( "undefined" );
+		}
+
+		final String pooledOptPreference = mappings.getConfigurationProperties().getProperty( Environment.PREFER_POOLED_VALUES_LO );
+		if ( pooledOptPreference != null ) {
+			params.setProperty( Environment.PREFER_POOLED_VALUES_LO, pooledOptPreference );
+		}
+
 		id.setIdentifierGeneratorProperties( params );
 	}
 

Modified: core/branches/Branch_3_5/core/src/main/java/org/hibernate/cfg/Environment.java
===================================================================
--- core/branches/Branch_3_5/core/src/main/java/org/hibernate/cfg/Environment.java	2010-05-12 17:17:45 UTC (rev 19479)
+++ core/branches/Branch_3_5/core/src/main/java/org/hibernate/cfg/Environment.java	2010-05-12 18:19:00 UTC (rev 19480)
@@ -519,6 +519,12 @@
 
 	public static final String JPAQL_STRICT_COMPLIANCE= "hibernate.query.jpaql_strict_compliance";
 
+	/**
+	 * When using pooled {@link org.hibernate.id.enhanced.Optimizer optimizers}, prefer interpreting the
+	 * database value as the lower (lo) boundary.  The default is to interpret it as the high boundary.
+	 */
+	public static final String PREFER_POOLED_VALUES_LO = "hibernate.id.optimizer.pooled.prefer_lo";
+
 	private static final BytecodeProvider BYTECODE_PROVIDER_INSTANCE;
 	private static final boolean ENABLE_BINARY_STREAMS;
 	private static final boolean ENABLE_REFLECTION_OPTIMIZER;

Modified: core/branches/Branch_3_5/core/src/main/java/org/hibernate/cfg/HbmBinder.java
===================================================================
--- core/branches/Branch_3_5/core/src/main/java/org/hibernate/cfg/HbmBinder.java	2010-05-12 17:17:45 UTC (rev 19479)
+++ core/branches/Branch_3_5/core/src/main/java/org/hibernate/cfg/HbmBinder.java	2010-05-12 18:19:00 UTC (rev 19480)
@@ -2091,6 +2091,11 @@
 				params.setProperty( childNode.attributeValue( "name" ), childNode.getTextTrim() );
 			}
 
+			final String pooledOptPreference = mappings.getConfigurationProperties().getProperty( Environment.PREFER_POOLED_VALUES_LO );
+			if ( pooledOptPreference != null ) {
+				params.setProperty( Environment.PREFER_POOLED_VALUES_LO, pooledOptPreference );
+			}
+
 			model.setIdentifierGeneratorProperties( params );
 		}
 

Modified: core/branches/Branch_3_5/core/src/main/java/org/hibernate/id/enhanced/OptimizerFactory.java
===================================================================
--- core/branches/Branch_3_5/core/src/main/java/org/hibernate/id/enhanced/OptimizerFactory.java	2010-05-12 17:17:45 UTC (rev 19479)
+++ core/branches/Branch_3_5/core/src/main/java/org/hibernate/id/enhanced/OptimizerFactory.java	2010-05-12 18:19:00 UTC (rev 19480)
@@ -1,10 +1,10 @@
 /*
  * Hibernate, Relational Persistence for Idiomatic Java
  *
- * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * Copyright (c) 2010, Red Hat Inc. or third-party contributors as
  * indicated by the @author tags or express copyright attribution
  * statements applied by the authors.  All third-party contributions are
- * distributed under license by Red Hat Middleware LLC.
+ * distributed under license by Red Hat Inc.
  *
  * This copyrighted material is made available to anyone wishing to use, modify,
  * copy, or redistribute it subject to the terms and conditions of the GNU
@@ -20,7 +20,6 @@
  * Free Software Foundation, Inc.
  * 51 Franklin Street, Fifth Floor
  * Boston, MA  02110-1301  USA
- *
  */
 package org.hibernate.id.enhanced;
 
@@ -46,6 +45,7 @@
 	public static final String HILO = "hilo";
 	public static final String LEGACY_HILO = "legacy-hilo";
 	public static final String POOL = "pooled";
+	public static final String POOL_LO = "pooled-lo";
 
 	private static Class[] CTOR_SIG = new Class[] { Class.class, int.class };
 
@@ -92,6 +92,9 @@
 		else if ( POOL.equals( type ) ) {
 			optimizerClassName = PooledOptimizer.class.getName();
 		}
+		else if ( POOL_LO.equals( type ) ) {
+			optimizerClassName = PooledLoOptimizer.class.getName();
+		}
 		else {
 			optimizerClassName = type;
 		}
@@ -386,6 +389,9 @@
 	 * Note that this optimizer works essentially the same as the
 	 * {@link HiLoOptimizer} except that here the bucket ranges are actually
 	 * encoded into the database structures.
+	 * <p/>
+	 * Note if you prefer that the database value be interpreted as the bottom end of our current range,
+	 * then use the {@link PooledLoOptimizer} strategy
 	 */
 	public static class PooledOptimizer extends OptimizerSupport implements InitialValueAwareOptimizer {
 		private IntegralDataTypeHolder hiValue;
@@ -463,4 +469,39 @@
 			this.initialValue = initialValue;
 		}
 	}
+
+	public static class PooledLoOptimizer extends OptimizerSupport {
+		private IntegralDataTypeHolder lastSourceValue; // last value read from db source
+		private IntegralDataTypeHolder value; // the current generator value
+
+		public PooledLoOptimizer(Class returnClass, int incrementSize) {
+			super( returnClass, incrementSize );
+			if ( incrementSize < 1 ) {
+				throw new HibernateException( "increment size cannot be less than 1" );
+			}
+			if ( log.isTraceEnabled() ) {
+				log.trace( "creating pooled optimizer (lo) with [incrementSize=" + incrementSize + "; returnClass="  + returnClass.getName() + "]" );
+			}
+		}
+
+		public Serializable generate(AccessCallback callback) {
+			if ( lastSourceValue == null || ! value.lt( lastSourceValue.copy().add( incrementSize ) ) ) {
+				lastSourceValue = callback.getNextValue();
+				value = lastSourceValue.copy();
+				// handle cases where initial-value is less that one (hsqldb for instance).
+				while ( value.lt( 1 ) ) {
+					value.increment();
+				}
+			}
+			return value.makeValueThenIncrement();
+		}
+
+		public IntegralDataTypeHolder getLastSourceValue() {
+			return lastSourceValue;
+		}
+
+		public boolean applyIncrementSizeToSourceValues() {
+			return true;
+		}
+	}
 }

Modified: core/branches/Branch_3_5/core/src/main/java/org/hibernate/id/enhanced/SequenceStyleGenerator.java
===================================================================
--- core/branches/Branch_3_5/core/src/main/java/org/hibernate/id/enhanced/SequenceStyleGenerator.java	2010-05-12 17:17:45 UTC (rev 19479)
+++ core/branches/Branch_3_5/core/src/main/java/org/hibernate/id/enhanced/SequenceStyleGenerator.java	2010-05-12 18:19:00 UTC (rev 19480)
@@ -1,10 +1,10 @@
 /*
  * Hibernate, Relational Persistence for Idiomatic Java
  *
- * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * Copyright (c) 2010, Red Hat Inc. or third-party contributors as
  * indicated by the @author tags or express copyright attribution
  * statements applied by the authors.  All third-party contributions are
- * distributed under license by Red Hat Middleware LLC.
+ * distributed under license by Red Hat Inc.
  *
  * This copyrighted material is made available to anyone wishing to use, modify,
  * copy, or redistribute it subject to the terms and conditions of the GNU
@@ -20,7 +20,6 @@
  * Free Software Foundation, Inc.
  * 51 Franklin Street, Fifth Floor
  * Boston, MA  02110-1301  USA
- *
  */
 package org.hibernate.id.enhanced;
 
@@ -30,6 +29,7 @@
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import org.hibernate.cfg.Environment;
 import org.hibernate.id.PersistentIdentifierGenerator;
 import org.hibernate.id.Configurable;
 import org.hibernate.HibernateException;
@@ -280,8 +280,13 @@
 	 * @return The optimizer strategy (name)
 	 */
 	protected String determineOptimizationStrategy(Properties params, int incrementSize) {
-		String defOptStrategy = incrementSize <= 1 ? OptimizerFactory.NONE : OptimizerFactory.POOL;
-		return PropertiesHelper.getString( OPT_PARAM, params, defOptStrategy );
+		// if the increment size is greater than one, we prefer pooled optimization; but we
+		// need to see if the user prefers POOL or POOL_LO...
+		String defaultPooledOptimizerStrategy = PropertiesHelper.getBoolean( Environment.PREFER_POOLED_VALUES_LO, params, false )
+				? OptimizerFactory.POOL_LO
+				: OptimizerFactory.POOL;
+		String defaultOptimizerStrategy = incrementSize <= 1 ? OptimizerFactory.NONE : defaultPooledOptimizerStrategy;
+		return PropertiesHelper.getString( OPT_PARAM, params, defaultOptimizerStrategy );
 	}
 
 	/**

Modified: core/branches/Branch_3_5/core/src/main/java/org/hibernate/id/enhanced/TableGenerator.java
===================================================================
--- core/branches/Branch_3_5/core/src/main/java/org/hibernate/id/enhanced/TableGenerator.java	2010-05-12 17:17:45 UTC (rev 19479)
+++ core/branches/Branch_3_5/core/src/main/java/org/hibernate/id/enhanced/TableGenerator.java	2010-05-12 18:19:00 UTC (rev 19480)
@@ -1,10 +1,10 @@
 /*
  * Hibernate, Relational Persistence for Idiomatic Java
  *
- * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
+ * Copyright (c) 2010, Red Hat Inc. or third-party contributors as
  * indicated by the @author tags or express copyright attribution
  * statements applied by the authors.  All third-party contributions are
- * distributed under license by Red Hat Middleware LLC.
+ * distributed under license by Red Hat Inc.
  *
  * This copyrighted material is made available to anyone wishing to use, modify,
  * copy, or redistribute it subject to the terms and conditions of the GNU
@@ -20,7 +20,6 @@
  * Free Software Foundation, Inc.
  * 51 Franklin Street, Fifth Floor
  * Boston, MA  02110-1301  USA
- *
  */
 package org.hibernate.id.enhanced;
 
@@ -37,6 +36,7 @@
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
+import org.hibernate.cfg.Environment;
 import org.hibernate.engine.TransactionHelper;
 import org.hibernate.engine.SessionImplementor;
 import org.hibernate.id.IdentifierGeneratorHelper;
@@ -65,14 +65,14 @@
  * performing generation, which would mean that we would have a row in the generator
  * table for each entity name.  Or any configuration really; the setup is very flexible.
  * <p/>
- * In this respect it is very simliar to the legacy
+ * In this respect it is very similar to the legacy
  * {@link org.hibernate.id.MultipleHiLoPerTableGenerator} in terms of the
  * underlying storage structure (namely a single table capable of holding
  * multiple generator values).  The differentiator is, as with
  * {@link SequenceStyleGenerator} as well, the externalized notion
  * of an optimizer.
  * <p/>
- * <b>NOTE</b> that by default we use a single row for all genertators (based
+ * <b>NOTE</b> that by default we use a single row for all generators (based
  * on {@link #DEF_SEGMENT_VALUE}).  The configuration parameter
  * {@link #CONFIG_PREFER_SEGMENT_PER_ENTITY} can be used to change that to
  * instead default to using a row for each entity name.
@@ -303,8 +303,14 @@
 		this.updateQuery = buildUpdateQuery();
 		this.insertQuery = buildInsertQuery();
 
-		String defOptStrategy = incrementSize <= 1 ? OptimizerFactory.NONE : OptimizerFactory.POOL;
-		String optimizationStrategy = PropertiesHelper.getString( OPT_PARAM, params, defOptStrategy );
+
+		// if the increment size is greater than one, we prefer pooled optimization; but we
+		// need to see if the user prefers POOL or POOL_LO...
+		String defaultPooledOptimizerStrategy = PropertiesHelper.getBoolean( Environment.PREFER_POOLED_VALUES_LO, params, false )
+				? OptimizerFactory.POOL_LO
+				: OptimizerFactory.POOL;
+		final String defaultOptimizerStrategy = incrementSize <= 1 ? OptimizerFactory.NONE : defaultPooledOptimizerStrategy;
+		final String optimizationStrategy = PropertiesHelper.getString( OPT_PARAM, params, defaultOptimizerStrategy );
 		optimizer = OptimizerFactory.buildOptimizer(
 				optimizationStrategy,
 				identifierType.getReturnedClass(),

Modified: core/branches/Branch_3_5/core/src/main/java/org/hibernate/mapping/SimpleValue.java
===================================================================
--- core/branches/Branch_3_5/core/src/main/java/org/hibernate/mapping/SimpleValue.java	2010-05-12 17:17:45 UTC (rev 19479)
+++ core/branches/Branch_3_5/core/src/main/java/org/hibernate/mapping/SimpleValue.java	2010-05-12 18:19:00 UTC (rev 19480)
@@ -31,6 +31,7 @@
 
 import org.hibernate.FetchMode;
 import org.hibernate.MappingException;
+import org.hibernate.cfg.Environment;
 import org.hibernate.dialect.Dialect;
 import org.hibernate.engine.Mapping;
 import org.hibernate.id.IdentifierGenerator;

Modified: core/branches/Branch_3_5/core/src/test/java/org/hibernate/id/enhanced/OptimizerUnitTest.java
===================================================================
--- core/branches/Branch_3_5/core/src/test/java/org/hibernate/id/enhanced/OptimizerUnitTest.java	2010-05-12 17:17:45 UTC (rev 19479)
+++ core/branches/Branch_3_5/core/src/test/java/org/hibernate/id/enhanced/OptimizerUnitTest.java	2010-05-12 18:19:00 UTC (rev 19480)
@@ -1,3 +1,26 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2010, Red Hat Inc. or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ */
 package org.hibernate.id.enhanced;
 
 import junit.framework.Assert;
@@ -100,35 +123,136 @@
 	public void testSubsequentPooledOptimizerUsage() {
 		// test the pooled optimizer in situation where the sequence is already beyond its initial value on init.
 		//		cheat by telling the sequence to start with 1000
-		final SourceMock sequence = new SourceMock( 1000, 3, 5 );
+		final SourceMock sequence = new SourceMock( 1001, 3, 5 );
 		//		but tell the optimizer the start-with is 1
 		final Optimizer optimizer = OptimizerFactory.buildOptimizer( OptimizerFactory.POOL, Long.class, 3, 1 );
 
 		assertEquals( 5, sequence.getTimesCalled() );
-		assertEquals( 1000, sequence.getCurrentValue() );
+		assertEquals( 1001, sequence.getCurrentValue() );
 
 		Long next = (Long) optimizer.generate( sequence );
-		assertEquals( 1000, next.intValue() );
+		assertEquals( 1001, next.intValue() );
 		assertEquals( (5+1), sequence.getTimesCalled() );
-		assertEquals( (1000+3), sequence.getCurrentValue() );
+		assertEquals( (1001+3), sequence.getCurrentValue() );
 
 		next = (Long) optimizer.generate( sequence );
-		assertEquals( 1001, next.intValue() );
+		assertEquals( (1001+1), next.intValue() );
 		assertEquals( (5+1), sequence.getTimesCalled() );
-		assertEquals( (1000+3), sequence.getCurrentValue() );
+		assertEquals( (1001+3), sequence.getCurrentValue() );
 
 		next = (Long) optimizer.generate( sequence );
-		assertEquals( 1002, next.intValue() );
+		assertEquals( (1001+2), next.intValue() );
 		assertEquals( (5+1), sequence.getTimesCalled() );
-		assertEquals( (1000+3), sequence.getCurrentValue() );
+		assertEquals( (1001+3), sequence.getCurrentValue() );
 
 		// force a "clock over"
 		next = (Long) optimizer.generate( sequence );
-		assertEquals( 1003, next.intValue() );
+		assertEquals( (1001+3), next.intValue() );
 		assertEquals( (5+2), sequence.getTimesCalled() );
-		assertEquals( (1000+6), sequence.getCurrentValue() );
+		assertEquals( (1001+6), sequence.getCurrentValue() );
 	}
 
+	public void testBasicPooledLoOptimizerUsage() {
+		final SourceMock sequence = new SourceMock( 1, 3 );
+		final Optimizer optimizer = OptimizerFactory.buildOptimizer( OptimizerFactory.POOL_LO, Long.class, 3 );
+
+		assertEquals( 0, sequence.getTimesCalled() );
+		assertEquals( -1, sequence.getCurrentValue() );
+
+		Long next = ( Long ) optimizer.generate( sequence );
+		assertEquals( 1, next.intValue() );
+		assertEquals( 1, sequence.getTimesCalled() );
+		assertEquals( 1, sequence.getCurrentValue() );
+
+		next = ( Long ) optimizer.generate( sequence );
+		assertEquals( 2, next.intValue() );
+		assertEquals( 1, sequence.getTimesCalled() );
+		assertEquals( 1, sequence.getCurrentValue() );
+
+		next = ( Long ) optimizer.generate( sequence );
+		assertEquals( 3, next.intValue() );
+		assertEquals( 1, sequence.getTimesCalled() );
+		assertEquals( 1, sequence.getCurrentValue() );
+
+//		// force a "clock over"
+		next = ( Long ) optimizer.generate( sequence );
+		assertEquals( 4, next.intValue() );
+		assertEquals( 2, sequence.getTimesCalled() );
+		assertEquals( (1+3), sequence.getCurrentValue() );
+	}
+
+	public void testSubsequentPooledLoOptimizerUsage() {
+		// test the pooled optimizer in situation where the sequence is already beyond its initial value on init.
+		//		cheat by telling the sequence to start with 1000
+		final SourceMock sequence = new SourceMock( 1001, 3, 5 );
+		//		but tell the optimizer the start-with is 1
+		final Optimizer optimizer = OptimizerFactory.buildOptimizer( OptimizerFactory.POOL, Long.class, 3, 1 );
+
+		assertEquals( 5, sequence.getTimesCalled() );
+		assertEquals( 1001, sequence.getCurrentValue() );
+
+		Long next = ( Long ) optimizer.generate( sequence );
+		assertEquals( (1001), next.intValue() );
+		assertEquals( (5+1), sequence.getTimesCalled() );
+		assertEquals( (1001+3), sequence.getCurrentValue() );
+
+		next = ( Long ) optimizer.generate( sequence );
+		assertEquals( (1001+1), next.intValue() );
+		assertEquals( (5+1), sequence.getTimesCalled() );
+		assertEquals( (1001+3), sequence.getCurrentValue() );
+
+		next = ( Long ) optimizer.generate( sequence );
+		assertEquals( (1001+2), next.intValue() );
+		assertEquals( (5+1), sequence.getTimesCalled() );
+		assertEquals( (1001+3), sequence.getCurrentValue() );
+
+//		// force a "clock over"
+		next = ( Long ) optimizer.generate( sequence );
+		assertEquals( (1001+3), next.intValue() );
+		assertEquals( (5+2), sequence.getTimesCalled() );
+		assertEquals( (1001+6), sequence.getCurrentValue() );
+	}
+
+	public void testRecoveredPooledOptimizerUsage() {
+		final SourceMock sequence = new SourceMock( 1, 3 );
+		final Optimizer optimizer = OptimizerFactory.buildOptimizer( OptimizerFactory.POOL, Long.class, 3, 1 );
+
+		assertEquals( 0, sequence.getTimesCalled() );
+		assertEquals( -1, sequence.getCurrentValue() );
+
+		Long next = ( Long ) optimizer.generate( sequence );
+		assertEquals( 1, next.intValue() );
+		assertEquals( 2, sequence.getTimesCalled() );
+		assertEquals( 4, sequence.getCurrentValue() );
+
+		// app ends, and starts back up (we should "lose" only 2 and 3 as id values)
+		final Optimizer optimizer2 = OptimizerFactory.buildOptimizer( OptimizerFactory.POOL, Long.class, 3, 1 );
+		next = ( Long ) optimizer2.generate( sequence );
+		assertEquals( 4, next.intValue() );
+		assertEquals( 3, sequence.getTimesCalled() );
+		assertEquals( 7, sequence.getCurrentValue() );
+	}
+
+	public void testRecoveredPooledLoOptimizerUsage() {
+		final SourceMock sequence = new SourceMock( 1, 3 );
+		final Optimizer optimizer = OptimizerFactory.buildOptimizer( OptimizerFactory.POOL_LO, Long.class, 3, 1 );
+
+		assertEquals( 0, sequence.getTimesCalled() );
+		assertEquals( -1, sequence.getCurrentValue() );
+
+		Long next = ( Long ) optimizer.generate( sequence );
+		assertEquals( 1, next.intValue() );
+		assertEquals( 1, sequence.getTimesCalled() );
+		assertEquals( 1, sequence.getCurrentValue() );
+
+		// app ends, and starts back up (we should "lose" only 2 and 3 as id values)
+		final Optimizer optimizer2 = OptimizerFactory.buildOptimizer( OptimizerFactory.POOL_LO, Long.class, 3, 1 );
+		next = ( Long ) optimizer2.generate( sequence );
+		assertEquals( 4, next.intValue() );
+		assertEquals( 2, sequence.getTimesCalled() );
+		assertEquals( 4, sequence.getCurrentValue() );
+	}
+
 	private static class SourceMock implements AccessCallback {
 		private IdentifierGeneratorHelper.BasicHolder value = new IdentifierGeneratorHelper.BasicHolder( Long.class );
 		private long initialValue;
@@ -151,6 +275,7 @@
 				this.initialValue = 1;
 			}
 			else {
+				this.value.initialize( -1 );
 				this.initialValue = initialValue;
 			}
 		}
@@ -182,5 +307,4 @@
 			return value == null ? -1 : value.getActualLongValue();
 		}
 	}
-
 }

Modified: core/branches/Branch_3_5/core/src/test/java/org/hibernate/id/enhanced/SequenceStyleConfigUnitTest.java
===================================================================
--- core/branches/Branch_3_5/core/src/test/java/org/hibernate/id/enhanced/SequenceStyleConfigUnitTest.java	2010-05-12 17:17:45 UTC (rev 19479)
+++ core/branches/Branch_3_5/core/src/test/java/org/hibernate/id/enhanced/SequenceStyleConfigUnitTest.java	2010-05-12 18:19:00 UTC (rev 19480)
@@ -1,3 +1,26 @@
+/*
+ * Hibernate, Relational Persistence for Idiomatic Java
+ *
+ * Copyright (c) 2010, Red Hat Inc. or third-party contributors as
+ * indicated by the @author tags or express copyright attribution
+ * statements applied by the authors.  All third-party contributions are
+ * distributed under license by Red Hat Inc.
+ *
+ * This copyrighted material is made available to anyone wishing to use, modify,
+ * copy, or redistribute it subject to the terms and conditions of the GNU
+ * Lesser General Public License, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
+ * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
+ * for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this distribution; if not, write to:
+ * Free Software Foundation, Inc.
+ * 51 Franklin Street, Fifth Floor
+ * Boston, MA  02110-1301  USA
+ */
 package org.hibernate.id.enhanced;
 
 import java.util.Properties;
@@ -9,6 +32,7 @@
 
 import org.hibernate.Hibernate;
 import org.hibernate.MappingException;
+import org.hibernate.cfg.Environment;
 import org.hibernate.cfg.NamingStrategy;
 import org.hibernate.cfg.ObjectNameNormalizer;
 import org.hibernate.dialect.Dialect;
@@ -179,7 +203,23 @@
 		assertClassAssignability( OptimizerFactory.PooledOptimizer.class, generator.getOptimizer().getClass() );
 		Assert.assertEquals( 20, generator.getOptimizer().getIncrementSize() );
 		Assert.assertEquals( 20, generator.getDatabaseStructure().getIncrementSize() );
+	}
 
+	public void testPreferPooledLoSettingHonored() {
+		final Dialect dialect = new PooledSequenceDialect();
+
+		Properties props = buildGeneratorPropertiesBase();
+		props.setProperty( SequenceStyleGenerator.INCREMENT_PARAM, "20" );
+		SequenceStyleGenerator generator = new SequenceStyleGenerator();
+		generator.configure( Hibernate.LONG, props, dialect );
+		assertClassAssignability( SequenceStructure.class, generator.getDatabaseStructure().getClass() );
+		assertClassAssignability( OptimizerFactory.PooledOptimizer.class, generator.getOptimizer().getClass() );
+
+		props.setProperty( Environment.PREFER_POOLED_VALUES_LO, "true" );
+		generator = new SequenceStyleGenerator();
+		generator.configure( Hibernate.LONG, props, dialect );
+		assertClassAssignability( SequenceStructure.class, generator.getDatabaseStructure().getClass() );
+		assertClassAssignability( OptimizerFactory.PooledLoOptimizer.class, generator.getOptimizer().getClass() );
 	}
 
 	private static class TableDialect extends Dialect {



More information about the hibernate-commits mailing list