[hibernate-commits] Hibernate SVN: r15151 - core/trunk/core/src/main/java/org/hibernate/id/enhanced.

hibernate-commits at lists.jboss.org hibernate-commits at lists.jboss.org
Fri Aug 29 14:42:57 EDT 2008


Author: steve.ebersole at jboss.com
Date: 2008-08-29 14:42:57 -0400 (Fri, 29 Aug 2008)
New Revision: 15151

Modified:
   core/trunk/core/src/main/java/org/hibernate/id/enhanced/OptimizerFactory.java
   core/trunk/core/src/main/java/org/hibernate/id/enhanced/SequenceStructure.java
   core/trunk/core/src/main/java/org/hibernate/id/enhanced/SequenceStyleGenerator.java
   core/trunk/core/src/main/java/org/hibernate/id/enhanced/TableStructure.java
Log:
HHH-3456 : enhanced.SequenceStyleGenerator extensibility

Modified: core/trunk/core/src/main/java/org/hibernate/id/enhanced/OptimizerFactory.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/id/enhanced/OptimizerFactory.java	2008-08-29 18:42:30 UTC (rev 15150)
+++ core/trunk/core/src/main/java/org/hibernate/id/enhanced/OptimizerFactory.java	2008-08-29 18:42:57 UTC (rev 15151)
@@ -76,10 +76,19 @@
 		return new NoopOptimizer( returnClass, incrementSize );
 	}
 
+	/**
+	 * Common support for optimizer implementations.
+	 */
 	public static abstract class OptimizerSupport implements Optimizer {
 		protected final Class returnClass;
 		protected final int incrementSize;
 
+		/**
+		 * Construct an optimizer
+		 *
+		 * @param returnClass The expected id class.
+		 * @param incrementSize The increment size
+		 */
 		protected OptimizerSupport(Class returnClass, int incrementSize) {
 			if ( returnClass == null ) {
 				throw new HibernateException( "return class is required" );
@@ -88,19 +97,39 @@
 			this.incrementSize = incrementSize;
 		}
 
-		protected Serializable make(long value) {
+		/**
+		 * Take the primitive long value and "make" (or wrap) it into the
+		 * {@link #getReturnClass id type}.
+		 *
+		 * @param value The primitive value to make/wrap.
+		 * @return The wrapped value.
+		 */
+		protected final Serializable make(long value) {
 			return IdentifierGeneratorFactory.createNumber( value, returnClass );
 		}
 
-		public Class getReturnClass() {
+		/**
+		 * Getter for property 'returnClass'.  This is the Java
+		 * class which is used to represent the id (e.g. {@link java.lang.Long}).
+		 *
+		 * @return Value for property 'returnClass'.
+		 */
+		public final Class getReturnClass() {
 			return returnClass;
 		}
 
-		public int getIncrementSize() {
+		/**
+		 * {@inheritDoc}
+		 */
+		public final int getIncrementSize() {
 			return incrementSize;
 		}
 	}
 
+	/**
+	 * An optimizer that performs no optimization.  The database is hit for
+	 * every request.
+	 */
 	public static class NoopOptimizer extends OptimizerSupport {
 		private long lastSourceValue = -1;
 
@@ -108,6 +137,9 @@
 			super( returnClass, incrementSize );
 		}
 
+		/**
+		 * {@inheritDoc}
+		 */
 		public Serializable generate(AccessCallback callback) {
 			if ( lastSourceValue == -1 ) {
 				while( lastSourceValue <= 0 ) {
@@ -120,15 +152,25 @@
 			return make( lastSourceValue );
 		}
 
+		/**
+		 * {@inheritDoc}
+		 */
 		public long getLastSourceValue() {
 			return lastSourceValue;
 		}
 
+		/**
+		 * {@inheritDoc}
+		 */
 		public boolean applyIncrementSizeToSourceValues() {
 			return false;
 		}
 	}
 
+	/**
+	 * Optimizer which applies a 'hilo' algorithm in memory to achieve
+	 * optimization.
+	 */
 	public static class HiLoOptimizer extends OptimizerSupport {
 		private long lastSourceValue = -1;
 		private long value;
@@ -144,6 +186,9 @@
 			}
 		}
 
+		/**
+		 * {@inheritDoc}
+		 */
 		public synchronized Serializable generate(AccessCallback callback) {
 			if ( lastSourceValue < 0 ) {
 				lastSourceValue = callback.getNextValue();
@@ -161,23 +206,43 @@
 		}
 
 
+		/**
+		 * {@inheritDoc}
+		 */
 		public long getLastSourceValue() {
 			return lastSourceValue;
 		}
 
+		/**
+		 * {@inheritDoc}
+		 */
 		public boolean applyIncrementSizeToSourceValues() {
 			return false;
 		}
 
+		/**
+		 * Getter for property 'lastValue'.
+		 *
+		 * @return Value for property 'lastValue'.
+		 */
 		public long getLastValue() {
 			return value - 1;
 		}
 
+		/**
+		 * Getter for property 'hiValue'.
+		 *
+		 * @return Value for property 'hiValue'.
+		 */
 		public long getHiValue() {
 			return hiValue;
 		}
 	}
 
+	/**
+	 * Optimizer which uses a pool of values, storing the next low value of the
+	 * range in the database.
+	 */
 	public static class PooledOptimizer extends OptimizerSupport {
 		private long value;
 		private long hiValue = -1;
@@ -192,6 +257,9 @@
 			}
 		}
 
+		/**
+		 * {@inheritDoc}
+		 */
 		public synchronized Serializable generate(AccessCallback callback) {
 			if ( hiValue < 0 ) {
 				value = callback.getNextValue();
@@ -211,14 +279,25 @@
 			return make( value++ );
 		}
 
+		/**
+		 * {@inheritDoc}
+		 */
 		public long getLastSourceValue() {
 			return hiValue;
 		}
 
+		/**
+		 * {@inheritDoc}
+		 */
 		public boolean applyIncrementSizeToSourceValues() {
 			return true;
 		}
 
+		/**
+		 * Getter for property 'lastValue'.
+		 *
+		 * @return Value for property 'lastValue'.
+		 */
 		public long getLastValue() {
 			return value - 1;
 		}

Modified: core/trunk/core/src/main/java/org/hibernate/id/enhanced/SequenceStructure.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/id/enhanced/SequenceStructure.java	2008-08-29 18:42:30 UTC (rev 15150)
+++ core/trunk/core/src/main/java/org/hibernate/id/enhanced/SequenceStructure.java	2008-08-29 18:42:57 UTC (rev 15151)
@@ -58,18 +58,30 @@
 		sql = dialect.getSequenceNextValString( sequenceName );
 	}
 
+	/**
+	 * {@inheritDoc}
+	 */
 	public String getName() {
 		return sequenceName;
 	}
 
+	/**
+	 * {@inheritDoc}
+	 */
 	public int getIncrementSize() {
 		return incrementSize;
 	}
 
+	/**
+	 * {@inheritDoc}
+	 */
 	public int getTimesAccessed() {
 		return accessCounter;
 	}
 
+	/**
+	 * {@inheritDoc}
+	 */
 	public AccessCallback buildCallback(final SessionImplementor session) {
 		return new AccessCallback() {
 			public long getNextValue() {
@@ -112,15 +124,24 @@
 		};
 	}
 
+	/**
+	 * {@inheritDoc}
+	 */
 	public void prepare(Optimizer optimizer) {
 		applyIncrementSizeToSourceValues = optimizer.applyIncrementSizeToSourceValues();
 	}
 
+	/**
+	 * {@inheritDoc}
+	 */
 	public String[] sqlCreateStrings(Dialect dialect) throws HibernateException {
 		int sourceIncrementSize = applyIncrementSizeToSourceValues ? incrementSize : 1;
 		return dialect.getCreateSequenceStrings( sequenceName, initialValue, sourceIncrementSize );
 	}
 
+	/**
+	 * {@inheritDoc}
+	 */
 	public String[] sqlDropStrings(Dialect dialect) throws HibernateException {
 		return dialect.getDropSequenceStrings( sequenceName );
 	}

Modified: core/trunk/core/src/main/java/org/hibernate/id/enhanced/SequenceStyleGenerator.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/id/enhanced/SequenceStyleGenerator.java	2008-08-29 18:42:30 UTC (rev 15150)
+++ core/trunk/core/src/main/java/org/hibernate/id/enhanced/SequenceStyleGenerator.java	2008-08-29 18:42:57 UTC (rev 15151)
@@ -123,14 +123,29 @@
 	private Optimizer optimizer;
 	private Type identifierType;
 
+	/**
+	 * Getter for property 'databaseStructure'.
+	 *
+	 * @return Value for property 'databaseStructure'.
+	 */
 	public DatabaseStructure getDatabaseStructure() {
 		return databaseStructure;
 	}
 
+	/**
+	 * Getter for property 'optimizer'.
+	 *
+	 * @return Value for property 'optimizer'.
+	 */
 	public Optimizer getOptimizer() {
 		return optimizer;
 	}
 
+	/**
+	 * Getter for property 'identifierType'.
+	 *
+	 * @return Value for property 'identifierType'.
+	 */
 	public Type getIdentifierType() {
 		return identifierType;
 	}
@@ -138,45 +153,160 @@
 
 	// Configurable implementation ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
+	/**
+	 * {@inheritDoc}
+	 */
 	public void configure(Type type, Properties params, Dialect dialect) throws MappingException {
-		identifierType = type;
+		this.identifierType = type;
 		boolean forceTableUse = PropertiesHelper.getBoolean( FORCE_TBL_PARAM, params, false );
 
+		final String sequenceName = determineSequenceName( params );
+
+		final int initialValue = determineInitialValue( params );
+		int incrementSize = determineIncrementSize( params );
+
+		final String optimizationStrategy = determineOptimizationStrategy( params, incrementSize );
+		incrementSize = determineAdjustedIncrementSize( optimizationStrategy, incrementSize );
+
+		if ( dialect.supportsSequences() && !forceTableUse ) {
+			if ( OptimizerFactory.POOL.equals( optimizationStrategy ) && !dialect.supportsPooledSequences() ) {
+				forceTableUse = true;
+				log.info(
+						"Forcing table use for sequence-style generator due to pooled optimizer selection where db does not support pooled sequences"
+				);
+			}
+		}
+
+		this.databaseStructure = buildDatabaseStructure( params, dialect, forceTableUse, sequenceName, initialValue, incrementSize );
+
+		this.optimizer = OptimizerFactory.buildOptimizer( optimizationStrategy, identifierType.getReturnedClass(), incrementSize );
+		this.databaseStructure.prepare( optimizer );
+	}
+
+	/**
+	 * Determine the name of the sequence (or table if this resolves to a physical table)
+	 * to use.
+	 * <p/>
+	 * Called during {@link #configure configuration}.
+	 *
+	 * @param params The params supplied in the generator config (plus some standard useful extras).
+	 * @return The sequence name
+	 */
+	protected String determineSequenceName(Properties params) {
 		String sequenceName = PropertiesHelper.getString( SEQUENCE_PARAM, params, DEF_SEQUENCE_NAME );
 		if ( sequenceName.indexOf( '.' ) < 0 ) {
 			String schemaName = params.getProperty( SCHEMA );
 			String catalogName = params.getProperty( CATALOG );
 			sequenceName = Table.qualify( catalogName, schemaName, sequenceName );
 		}
-		int initialValue = PropertiesHelper.getInt( INITIAL_PARAM, params, DEFAULT_INITIAL_VALUE );
-		int incrementSize = PropertiesHelper.getInt( INCREMENT_PARAM, params, DEFAULT_INCREMENT_SIZE );
+		return sequenceName;
+	}
 
-		String valueColumnName = PropertiesHelper.getString( VALUE_COLUMN_PARAM, params, DEF_VALUE_COLUMN );
+	/**
+	 * Determine the name of the column used to store the generator value in
+	 * the db.
+	 * <p/>
+	 * Called during {@link #configure configuration} <b>when resolving to a
+	 * physical table</b>.
+	 *
+	 * @param params The params supplied in the generator config (plus some standard useful extras).
+	 * @return The value column name
+	 */
+	protected String determineValueColumnName(Properties params) {
+		return PropertiesHelper.getString( VALUE_COLUMN_PARAM, params, DEF_VALUE_COLUMN );
+	}
 
+	/**
+	 * Determine the initial sequence value to use.  This value is used when
+	 * initializing the {@link #getDatabaseStructure() database structure}
+	 * (i.e. sequence/table).
+	 * <p/>
+	 * Called during {@link #configure configuration}.
+	 *
+	 * @param params The params supplied in the generator config (plus some standard useful extras).
+	 * @return The initial value
+	 */
+	protected int determineInitialValue(Properties params) {
+		return PropertiesHelper.getInt( INITIAL_PARAM, params, DEFAULT_INITIAL_VALUE );
+	}
+
+	/**
+	 * Determine the increment size to be applied.  The exact implications of
+	 * this value depends on the {@link #getOptimizer() optimizer} being used.
+	 * <p/>
+	 * Called during {@link #configure configuration}.
+	 *
+	 * @param params The params supplied in the generator config (plus some standard useful extras).
+	 * @return The increment size
+	 */
+	protected int determineIncrementSize(Properties params) {
+		return PropertiesHelper.getInt( INCREMENT_PARAM, params, DEFAULT_INCREMENT_SIZE );
+	}
+
+	/**
+	 * Determine the optimizer to use.
+	 * <p/>
+	 * Called during {@link #configure configuration}.
+	 *
+	 * @param params The params supplied in the generator config (plus some standard useful extras).
+	 * @param incrementSize The {@link #determineIncrementSize determined increment size}
+	 * @return The optimizer strategy (name)
+	 */
+	protected String determineOptimizationStrategy(Properties params, int incrementSize) {
 		String defOptStrategy = incrementSize <= 1 ? OptimizerFactory.NONE : OptimizerFactory.POOL;
-		String optimizationStrategy = PropertiesHelper.getString( OPT_PARAM, params, defOptStrategy );
+		return PropertiesHelper.getString( OPT_PARAM, params, defOptStrategy );
+	}
+
+	/**
+	 * In certain cases we need to adjust the increment size based on the
+	 * selected optimizer.  This is the hook to achieve that.
+	 *
+	 * @param optimizationStrategy The optimizer strategy (name)
+	 * @param incrementSize The {@link #determineIncrementSize determined increment size}
+	 * @return The adjusted increment size.
+	 */
+	protected int determineAdjustedIncrementSize(String optimizationStrategy, int incrementSize) {
 		if ( OptimizerFactory.NONE.equals( optimizationStrategy ) && incrementSize > 1 ) {
 			log.warn( "config specified explicit optimizer of [" + OptimizerFactory.NONE + "], but [" + INCREMENT_PARAM + "=" + incrementSize + "; honoring optimizer setting" );
 			incrementSize = 1;
 		}
-		if ( dialect.supportsSequences() && !forceTableUse ) {
-			if ( OptimizerFactory.POOL.equals( optimizationStrategy ) && !dialect.supportsPooledSequences() ) {
-				// TODO : may even be better to fall back to a pooled table strategy here so that the db stored values remain consistent... 
-				optimizationStrategy = OptimizerFactory.HILO;
-			}
-			databaseStructure = new SequenceStructure( dialect, sequenceName, initialValue, incrementSize );
+		return incrementSize;
+	}
+
+	/**
+	 * Build the database structure.
+	 *
+	 * @param params The params supplied in the generator config (plus some standard useful extras).
+	 * @param dialect The dialect being used.
+	 * @param forceTableUse Should a table be used even if the dialect supports sequences?
+	 * @param sequenceName The name to use for the sequence or table.
+	 * @param initialValue The initial value.
+	 * @param incrementSize the increment size to use (after any adjustments).
+	 * @return The db structure representation
+	 */
+	protected DatabaseStructure buildDatabaseStructure(
+			Properties params,
+			Dialect dialect,
+			boolean forceTableUse,
+			String sequenceName,
+			int initialValue,
+			int incrementSize) {
+		boolean useSequence = dialect.supportsSequences() && !forceTableUse;
+		if ( useSequence ) {
+			return new SequenceStructure( dialect, sequenceName, initialValue, incrementSize );
 		}
 		else {
-			databaseStructure = new TableStructure( dialect, sequenceName, valueColumnName, initialValue, incrementSize );
+			String valueColumnName = determineValueColumnName( params );
+			return new TableStructure( dialect, sequenceName, valueColumnName, initialValue, incrementSize );
 		}
-
-		optimizer = OptimizerFactory.buildOptimizer( optimizationStrategy, identifierType.getReturnedClass(), incrementSize );
-		databaseStructure.prepare( optimizer );
 	}
 
 
 	// IdentifierGenerator implementation ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
+	/**
+	 * {@inheritDoc}
+	 */
 	public Serializable generate(SessionImplementor session, Object object) throws HibernateException {
 		return optimizer.generate( databaseStructure.buildCallback( session ) );
 	}
@@ -184,16 +314,24 @@
 
 	// PersistentIdentifierGenerator implementation ~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
+	/**
+	 * {@inheritDoc}
+	 */
 	public Object generatorKey() {
 		return databaseStructure.getName();
 	}
 
+	/**
+	 * {@inheritDoc}
+	 */
 	public String[] sqlCreateStrings(Dialect dialect) throws HibernateException {
 		return databaseStructure.sqlCreateStrings( dialect );
 	}
 
+	/**
+	 * {@inheritDoc}
+	 */
 	public String[] sqlDropStrings(Dialect dialect) throws HibernateException {
 		return databaseStructure.sqlDropStrings( dialect );
 	}
-
 }

Modified: core/trunk/core/src/main/java/org/hibernate/id/enhanced/TableStructure.java
===================================================================
--- core/trunk/core/src/main/java/org/hibernate/id/enhanced/TableStructure.java	2008-08-29 18:42:30 UTC (rev 15150)
+++ core/trunk/core/src/main/java/org/hibernate/id/enhanced/TableStructure.java	2008-08-29 18:42:57 UTC (rev 15151)
@@ -56,8 +56,9 @@
 	private final String valueColumnName;
 	private final int initialValue;
 	private final int incrementSize;
-	private final String select;
-	private final String update;
+	private final String selectQuery;
+	private final String updateQuery;
+
 	private boolean applyIncrementSizeToSourceValues;
 	private int accessCounter;
 
@@ -67,31 +68,46 @@
 		this.incrementSize = incrementSize;
 		this.valueColumnName = valueColumnName;
 
-		select = "select " + valueColumnName + " id_val" +
+		selectQuery = "select " + valueColumnName + " id_val" +
 				" from " + dialect.appendLockHint( LockMode.UPGRADE, tableName ) +
 				dialect.getForUpdateString();
 
-		update = "update " + tableName +
+		updateQuery = "update " + tableName +
 				" set " + valueColumnName + "= ?" +
 				" where " + valueColumnName + "=?";
 	}
 
+	/**
+	 * {@inheritDoc}
+	 */
 	public String getName() {
 		return tableName;
 	}
 
+	/**
+	 * {@inheritDoc}
+	 */
 	public int getIncrementSize() {
 		return incrementSize;
 	}
 
+	/**
+	 * {@inheritDoc}
+	 */
 	public int getTimesAccessed() {
 		return accessCounter;
 	}
 
+	/**
+	 * {@inheritDoc}
+	 */
 	public void prepare(Optimizer optimizer) {
 		applyIncrementSizeToSourceValues = optimizer.applyIncrementSizeToSourceValues();
 	}
 
+	/**
+	 * {@inheritDoc}
+	 */
 	public AccessCallback buildCallback(final SessionImplementor session) {
 		return new AccessCallback() {
 			public long getNextValue() {
@@ -100,6 +116,9 @@
 		};
 	}
 
+	/**
+	 * {@inheritDoc}
+	 */
 	public String[] sqlCreateStrings(Dialect dialect) throws HibernateException {
 		return new String[] {
 				dialect.getCreateTableString() + " " + tableName + " ( " + valueColumnName + " " + dialect.getTypeName( Types.BIGINT ) + " )",
@@ -107,6 +126,9 @@
 		};
 	}
 
+	/**
+	 * {@inheritDoc}
+	 */
 	public String[] sqlDropStrings(Dialect dialect) throws HibernateException {
 		StringBuffer sqlDropString = new StringBuffer().append( "drop table " );
 		if ( dialect.supportsIfExistsBeforeTableName() ) {
@@ -119,46 +141,47 @@
 		return new String[] { sqlDropString.toString() };
 	}
 
+	/**
+	 * {@inheritDoc}
+	 */
 	protected Serializable doWorkInCurrentTransaction(Connection conn, String sql) throws SQLException {
 		long result;
 		int rows;
 		do {
-			sql = select;
-			SQL_STATEMENT_LOGGER.logStatement( sql, FormatStyle.BASIC );
-			PreparedStatement qps = conn.prepareStatement( select );
+			SQL_STATEMENT_LOGGER.logStatement( selectQuery, FormatStyle.BASIC );
+			PreparedStatement selectPS = conn.prepareStatement( selectQuery );
 			try {
-				ResultSet rs = qps.executeQuery();
-				if ( !rs.next() ) {
+				ResultSet selectRS = selectPS.executeQuery();
+				if ( !selectRS.next() ) {
 					String err = "could not read a hi value - you need to populate the table: " + tableName;
 					log.error( err );
 					throw new IdentifierGenerationException( err );
 				}
-				result = rs.getLong( 1 );
-				rs.close();
+				result = selectRS.getLong( 1 );
+				selectRS.close();
 			}
 			catch ( SQLException sqle ) {
 				log.error( "could not read a hi value", sqle );
 				throw sqle;
 			}
 			finally {
-				qps.close();
+				selectPS.close();
 			}
 
-			sql = update;
-			SQL_STATEMENT_LOGGER.logStatement( sql, FormatStyle.BASIC );
-			PreparedStatement ups = conn.prepareStatement( update );
+			SQL_STATEMENT_LOGGER.logStatement( updateQuery, FormatStyle.BASIC );
+			PreparedStatement updatePS = conn.prepareStatement( updateQuery );
 			try {
 				int increment = applyIncrementSizeToSourceValues ? incrementSize : 1;
-				ups.setLong( 1, result + increment );
-				ups.setLong( 2, result );
-				rows = ups.executeUpdate();
+				updatePS.setLong( 1, result + increment );
+				updatePS.setLong( 2, result );
+				rows = updatePS.executeUpdate();
 			}
 			catch ( SQLException sqle ) {
-				log.error( "could not update hi value in: " + tableName, sqle );
+				log.error( "could not updateQuery hi value in: " + tableName, sqle );
 				throw sqle;
 			}
 			finally {
-				ups.close();
+				updatePS.close();
 			}
 		} while ( rows == 0 );
 




More information about the hibernate-commits mailing list