All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.hibernate.id.enhanced.SequenceStyleGenerator Maven / Gradle / Ivy

There is a newer version: 7.0.0.Alpha1
Show newest version
/*
 * Hibernate, Relational Persistence for Idiomatic Java
 *
 * Copyright (c) 2008, Red Hat Middleware LLC 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.
 *
 * 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;
import java.io.Serializable;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.hibernate.id.PersistentIdentifierGenerator;
import org.hibernate.id.Configurable;
import org.hibernate.HibernateException;
import org.hibernate.MappingException;
import org.hibernate.engine.SessionImplementor;
import org.hibernate.mapping.Table;
import org.hibernate.util.PropertiesHelper;
import org.hibernate.type.Type;
import org.hibernate.dialect.Dialect;

/**
 * Generates identifier values based on an sequence-style database structure.
 * Variations range from actually using a sequence to using a table to mimic
 * a sequence.  These variations are encapsulated by the {@link DatabaseStructure}
 * interface internally.
 * 

* General configuration parameters: *

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
NAMEDEFAULTDESCRIPTION
{@link #SEQUENCE_PARAM}{@link #DEF_SEQUENCE_NAME}The name of the sequence/table to use to store/retrieve values
{@link #INITIAL_PARAM}{@link #DEFAULT_INITIAL_VALUE}The initial value to be stored for the given segment; the effect in terms of storage varies based on {@link Optimizer} and {@link DatabaseStructure}
{@link #INCREMENT_PARAM}{@link #DEFAULT_INCREMENT_SIZE}The increment size for the underlying segment; the effect in terms of storage varies based on {@link Optimizer} and {@link DatabaseStructure}
{@link #OPT_PARAM}depends on defined increment sizeAllows explicit definition of which optimization strategy to use
{@link #FORCE_TBL_PARAM}falseAllows explicit definition of which optimization strategy to use
*

* Configuration parameters used specifically when the underlying structure is a table: *

* * * * * * * * * * *
NAMEDEFAULTDESCRIPTION
{@link #VALUE_COLUMN_PARAM}{@link #DEF_VALUE_COLUMN}The name of column which holds the sequence value for the given segment
* * @author Steve Ebersole */ public class SequenceStyleGenerator implements PersistentIdentifierGenerator, Configurable { private static final Logger log = LoggerFactory.getLogger( SequenceStyleGenerator.class ); // general purpose parameters ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ public static final String SEQUENCE_PARAM = "sequence_name"; public static final String DEF_SEQUENCE_NAME = "hibernate_sequence"; public static final String INITIAL_PARAM = "initial_value"; public static final int DEFAULT_INITIAL_VALUE = 1; public static final String INCREMENT_PARAM = "increment_size"; public static final int DEFAULT_INCREMENT_SIZE = 1; public static final String OPT_PARAM = "optimizer"; public static final String FORCE_TBL_PARAM = "force_table_use"; // table-specific parameters ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ public static final String VALUE_COLUMN_PARAM = "value_column"; public static final String DEF_VALUE_COLUMN = "next_val"; // state ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ private DatabaseStructure databaseStructure; private Optimizer optimizer; private Type identifierType; public DatabaseStructure getDatabaseStructure() { return databaseStructure; } public Optimizer getOptimizer() { return optimizer; } public Type getIdentifierType() { return identifierType; } // Configurable implementation ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ public void configure(Type type, Properties params, Dialect dialect) throws MappingException { identifierType = type; boolean forceTableUse = PropertiesHelper.getBoolean( FORCE_TBL_PARAM, params, false ); 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 ); String valueColumnName = PropertiesHelper.getString( VALUE_COLUMN_PARAM, params, DEF_VALUE_COLUMN ); String defOptStrategy = incrementSize <= 1 ? OptimizerFactory.NONE : OptimizerFactory.POOL; String optimizationStrategy = PropertiesHelper.getString( OPT_PARAM, params, defOptStrategy ); 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 ); } else { databaseStructure = new TableStructure( dialect, sequenceName, valueColumnName, initialValue, incrementSize ); } optimizer = OptimizerFactory.buildOptimizer( optimizationStrategy, identifierType.getReturnedClass(), incrementSize ); databaseStructure.prepare( optimizer ); } // IdentifierGenerator implementation ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ public Serializable generate(SessionImplementor session, Object object) throws HibernateException { return optimizer.generate( databaseStructure.buildCallback( session ) ); } // PersistentIdentifierGenerator implementation ~~~~~~~~~~~~~~~~~~~~~~~~~~~ public Object generatorKey() { return databaseStructure.getName(); } public String[] sqlCreateStrings(Dialect dialect) throws HibernateException { return databaseStructure.sqlCreateStrings( dialect ); } public String[] sqlDropStrings(Dialect dialect) throws HibernateException { return databaseStructure.sqlDropStrings( dialect ); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy