Save This Page
Home » Hibernate-3.3.2.GA » org.hibernate » cfg » [javadoc | source]
    1   /*
    2    * Hibernate, Relational Persistence for Idiomatic Java
    3    *
    4    * Copyright (c) 2008, Red Hat Middleware LLC or third-party contributors as
    5    * indicated by the @author tags or express copyright attribution
    6    * statements applied by the authors.  All third-party contributions are
    7    * distributed under license by Red Hat Middleware LLC.
    8    *
    9    * This copyrighted material is made available to anyone wishing to use, modify,
   10    * copy, or redistribute it subject to the terms and conditions of the GNU
   11    * Lesser General Public License, as published by the Free Software Foundation.
   12    *
   13    * This program is distributed in the hope that it will be useful,
   14    * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
   15    * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public License
   16    * for more details.
   17    *
   18    * You should have received a copy of the GNU Lesser General Public License
   19    * along with this distribution; if not, write to:
   20    * Free Software Foundation, Inc.
   21    * 51 Franklin Street, Fifth Floor
   22    * Boston, MA  02110-1301  USA
   23    *
   24    */
   25   package org.hibernate.cfg;
   26   
   27   import java.io.Serializable;
   28   import java.sql.Connection;
   29   import java.sql.DatabaseMetaData;
   30   import java.sql.ResultSet;
   31   import java.sql.SQLException;
   32   import java.util.Map;
   33   import java.util.Properties;
   34   
   35   import org.slf4j.Logger;
   36   import org.slf4j.LoggerFactory;
   37   
   38   import org.hibernate.ConnectionReleaseMode;
   39   import org.hibernate.EntityMode;
   40   import org.hibernate.HibernateException;
   41   import org.hibernate.bytecode.BytecodeProvider;
   42   import org.hibernate.cache.QueryCacheFactory;
   43   import org.hibernate.cache.RegionFactory;
   44   import org.hibernate.cache.impl.NoCachingRegionFactory;
   45   import org.hibernate.cache.impl.bridge.RegionFactoryCacheProviderBridge;
   46   import org.hibernate.connection.ConnectionProvider;
   47   import org.hibernate.connection.ConnectionProviderFactory;
   48   import org.hibernate.dialect.Dialect;
   49   import org.hibernate.dialect.resolver.DialectFactory;
   50   import org.hibernate.exception.SQLExceptionConverter;
   51   import org.hibernate.exception.SQLExceptionConverterFactory;
   52   import org.hibernate.hql.QueryTranslatorFactory;
   53   import org.hibernate.jdbc.BatcherFactory;
   54   import org.hibernate.jdbc.BatchingBatcherFactory;
   55   import org.hibernate.jdbc.NonBatchingBatcherFactory;
   56   import org.hibernate.jdbc.util.SQLStatementLogger;
   57   import org.hibernate.transaction.TransactionFactory;
   58   import org.hibernate.transaction.TransactionFactoryFactory;
   59   import org.hibernate.transaction.TransactionManagerLookup;
   60   import org.hibernate.transaction.TransactionManagerLookupFactory;
   61   import org.hibernate.util.PropertiesHelper;
   62   import org.hibernate.util.ReflectHelper;
   63   import org.hibernate.util.StringHelper;
   64   
   65   /**
   66    * Reads configuration properties and builds a {@link Settings} instance.
   67    *
   68    * @author Gavin King
   69    */
   70   public class SettingsFactory implements Serializable {
   71   	private static final Logger log = LoggerFactory.getLogger( SettingsFactory.class );
   72   	private static final long serialVersionUID = -1194386144994524825L;
   73   
   74   	public static final String DEF_CACHE_REG_FACTORY = NoCachingRegionFactory.class.getName();
   75   
   76   	protected SettingsFactory() {
   77   	}
   78   
   79   	public Settings buildSettings(Properties props) {
   80   		Settings settings = new Settings();
   81   
   82   		//SessionFactory name:
   83   
   84   		String sessionFactoryName = props.getProperty(Environment.SESSION_FACTORY_NAME);
   85   		settings.setSessionFactoryName(sessionFactoryName);
   86   
   87   		//JDBC and connection settings:
   88   
   89   		ConnectionProvider connections = createConnectionProvider(props);
   90   		settings.setConnectionProvider(connections);
   91   
   92   		//Interrogate JDBC metadata
   93   
   94   		boolean metaSupportsScrollable = false;
   95   		boolean metaSupportsGetGeneratedKeys = false;
   96   		boolean metaSupportsBatchUpdates = false;
   97   		boolean metaReportsDDLCausesTxnCommit = false;
   98   		boolean metaReportsDDLInTxnSupported = true;
   99   		Dialect dialect = null;
  100   
  101   		// 'hibernate.temp.use_jdbc_metadata_defaults' is a temporary magic value.
  102   		// The need for it is intended to be alleviated with future developement, thus it is
  103   		// not defined as an Environment constant...
  104   		//
  105   		// it is used to control whether we should consult the JDBC metadata to determine
  106   		// certain Settings default values; it is useful to *not* do this when the database
  107   		// may not be available (mainly in tools usage).
  108   		boolean useJdbcMetadata = PropertiesHelper.getBoolean( "hibernate.temp.use_jdbc_metadata_defaults", props, true );
  109   		if ( useJdbcMetadata ) {
  110   			try {
  111   				Connection conn = connections.getConnection();
  112   				try {
  113   					DatabaseMetaData meta = conn.getMetaData();
  114   					log.info( "RDBMS: " + meta.getDatabaseProductName() + ", version: " + meta.getDatabaseProductVersion() );
  115   					log.info( "JDBC driver: " + meta.getDriverName() + ", version: " + meta.getDriverVersion() );
  116   
  117   					dialect = DialectFactory.buildDialect( props, conn );
  118   
  119   					metaSupportsScrollable = meta.supportsResultSetType( ResultSet.TYPE_SCROLL_INSENSITIVE );
  120   					metaSupportsBatchUpdates = meta.supportsBatchUpdates();
  121   					metaReportsDDLCausesTxnCommit = meta.dataDefinitionCausesTransactionCommit();
  122   					metaReportsDDLInTxnSupported = !meta.dataDefinitionIgnoredInTransactions();
  123   					metaSupportsGetGeneratedKeys = meta.supportsGetGeneratedKeys();
  124   				}
  125   				catch ( SQLException sqle ) {
  126   					log.warn( "Could not obtain connection metadata", sqle );
  127   				}
  128   				finally {
  129   					connections.closeConnection( conn );
  130   				}
  131   			}
  132   			catch ( SQLException sqle ) {
  133   				log.warn( "Could not obtain connection to query metadata", sqle );
  134   				dialect = DialectFactory.buildDialect( props );
  135   			}
  136   			catch ( UnsupportedOperationException uoe ) {
  137   				// user supplied JDBC connections
  138   				dialect = DialectFactory.buildDialect( props );
  139   			}
  140   		}
  141   		else {
  142   			dialect = DialectFactory.buildDialect( props );
  143   		}
  144   
  145   		settings.setDataDefinitionImplicitCommit( metaReportsDDLCausesTxnCommit );
  146   		settings.setDataDefinitionInTransactionSupported( metaReportsDDLInTxnSupported );
  147   		settings.setDialect( dialect );
  148   
  149   		//use dialect default properties
  150   		final Properties properties = new Properties();
  151   		properties.putAll( dialect.getDefaultProperties() );
  152   		properties.putAll( props );
  153   
  154   		// Transaction settings:
  155   
  156   		TransactionFactory transactionFactory = createTransactionFactory(properties);
  157   		settings.setTransactionFactory(transactionFactory);
  158   		settings.setTransactionManagerLookup( createTransactionManagerLookup(properties) );
  159   
  160   		boolean flushBeforeCompletion = PropertiesHelper.getBoolean(Environment.FLUSH_BEFORE_COMPLETION, properties);
  161   		log.info("Automatic flush during beforeCompletion(): " + enabledDisabled(flushBeforeCompletion) );
  162   		settings.setFlushBeforeCompletionEnabled(flushBeforeCompletion);
  163   
  164   		boolean autoCloseSession = PropertiesHelper.getBoolean(Environment.AUTO_CLOSE_SESSION, properties);
  165   		log.info("Automatic session close at end of transaction: " + enabledDisabled(autoCloseSession) );
  166   		settings.setAutoCloseSessionEnabled(autoCloseSession);
  167   
  168   		//JDBC and connection settings:
  169   
  170   		int batchSize = PropertiesHelper.getInt(Environment.STATEMENT_BATCH_SIZE, properties, 0);
  171   		if ( !metaSupportsBatchUpdates ) batchSize = 0;
  172   		if (batchSize>0) log.info("JDBC batch size: " + batchSize);
  173   		settings.setJdbcBatchSize(batchSize);
  174   		boolean jdbcBatchVersionedData = PropertiesHelper.getBoolean(Environment.BATCH_VERSIONED_DATA, properties, false);
  175   		if (batchSize>0) log.info("JDBC batch updates for versioned data: " + enabledDisabled(jdbcBatchVersionedData) );
  176   		settings.setJdbcBatchVersionedData(jdbcBatchVersionedData);
  177   		settings.setBatcherFactory( createBatcherFactory(properties, batchSize) );
  178   
  179   		boolean useScrollableResultSets = PropertiesHelper.getBoolean(Environment.USE_SCROLLABLE_RESULTSET, properties, metaSupportsScrollable);
  180   		log.info("Scrollable result sets: " + enabledDisabled(useScrollableResultSets) );
  181   		settings.setScrollableResultSetsEnabled(useScrollableResultSets);
  182   
  183   		boolean wrapResultSets = PropertiesHelper.getBoolean(Environment.WRAP_RESULT_SETS, properties, false);
  184   		log.debug( "Wrap result sets: " + enabledDisabled(wrapResultSets) );
  185   		settings.setWrapResultSetsEnabled(wrapResultSets);
  186   
  187   		boolean useGetGeneratedKeys = PropertiesHelper.getBoolean(Environment.USE_GET_GENERATED_KEYS, properties, metaSupportsGetGeneratedKeys);
  188   		log.info("JDBC3 getGeneratedKeys(): " + enabledDisabled(useGetGeneratedKeys) );
  189   		settings.setGetGeneratedKeysEnabled(useGetGeneratedKeys);
  190   
  191   		Integer statementFetchSize = PropertiesHelper.getInteger(Environment.STATEMENT_FETCH_SIZE, properties);
  192   		if (statementFetchSize!=null) log.info("JDBC result set fetch size: " + statementFetchSize);
  193   		settings.setJdbcFetchSize(statementFetchSize);
  194   
  195   		String releaseModeName = PropertiesHelper.getString( Environment.RELEASE_CONNECTIONS, properties, "auto" );
  196   		log.info( "Connection release mode: " + releaseModeName );
  197   		ConnectionReleaseMode releaseMode;
  198   		if ( "auto".equals(releaseModeName) ) {
  199   			releaseMode = transactionFactory.getDefaultReleaseMode();
  200   		}
  201   		else {
  202   			releaseMode = ConnectionReleaseMode.parse( releaseModeName );
  203   			if ( releaseMode == ConnectionReleaseMode.AFTER_STATEMENT && !connections.supportsAggressiveRelease() ) {
  204   				log.warn( "Overriding release mode as connection provider does not support 'after_statement'" );
  205   				releaseMode = ConnectionReleaseMode.AFTER_TRANSACTION;
  206   			}
  207   		}
  208   		settings.setConnectionReleaseMode( releaseMode );
  209   
  210   		//SQL Generation settings:
  211   
  212   		String defaultSchema = properties.getProperty(Environment.DEFAULT_SCHEMA);
  213   		String defaultCatalog = properties.getProperty(Environment.DEFAULT_CATALOG);
  214   		if (defaultSchema!=null) log.info("Default schema: " + defaultSchema);
  215   		if (defaultCatalog!=null) log.info("Default catalog: " + defaultCatalog);
  216   		settings.setDefaultSchemaName(defaultSchema);
  217   		settings.setDefaultCatalogName(defaultCatalog);
  218   
  219   		Integer maxFetchDepth = PropertiesHelper.getInteger(Environment.MAX_FETCH_DEPTH, properties);
  220   		if (maxFetchDepth!=null) log.info("Maximum outer join fetch depth: " + maxFetchDepth);
  221   		settings.setMaximumFetchDepth(maxFetchDepth);
  222   		int batchFetchSize = PropertiesHelper.getInt(Environment.DEFAULT_BATCH_FETCH_SIZE, properties, 1);
  223   		log.info("Default batch fetch size: " + batchFetchSize);
  224   		settings.setDefaultBatchFetchSize(batchFetchSize);
  225   
  226   		boolean comments = PropertiesHelper.getBoolean(Environment.USE_SQL_COMMENTS, properties);
  227   		log.info( "Generate SQL with comments: " + enabledDisabled(comments) );
  228   		settings.setCommentsEnabled(comments);
  229   
  230   		boolean orderUpdates = PropertiesHelper.getBoolean(Environment.ORDER_UPDATES, properties);
  231   		log.info( "Order SQL updates by primary key: " + enabledDisabled(orderUpdates) );
  232   		settings.setOrderUpdatesEnabled(orderUpdates);
  233   
  234   		boolean orderInserts = PropertiesHelper.getBoolean(Environment.ORDER_INSERTS, properties);
  235   		log.info( "Order SQL inserts for batching: " + enabledDisabled( orderInserts ) );
  236   		settings.setOrderInsertsEnabled( orderInserts );
  237   
  238   		//Query parser settings:
  239   
  240   		settings.setQueryTranslatorFactory( createQueryTranslatorFactory(properties) );
  241   
  242   		Map querySubstitutions = PropertiesHelper.toMap(Environment.QUERY_SUBSTITUTIONS, " ,=;:\n\t\r\f", properties);
  243   		log.info("Query language substitutions: " + querySubstitutions);
  244   		settings.setQuerySubstitutions(querySubstitutions);
  245   
  246   		boolean jpaqlCompliance = PropertiesHelper.getBoolean( Environment.JPAQL_STRICT_COMPLIANCE, properties, false );
  247   		settings.setStrictJPAQLCompliance( jpaqlCompliance );
  248   		log.info( "JPA-QL strict compliance: " + enabledDisabled( jpaqlCompliance ) );
  249   
  250   		// Second-level / query cache:
  251   
  252   		boolean useSecondLevelCache = PropertiesHelper.getBoolean(Environment.USE_SECOND_LEVEL_CACHE, properties, true);
  253   		log.info( "Second-level cache: " + enabledDisabled(useSecondLevelCache) );
  254   		settings.setSecondLevelCacheEnabled(useSecondLevelCache);
  255   
  256   		boolean useQueryCache = PropertiesHelper.getBoolean(Environment.USE_QUERY_CACHE, properties);
  257   		log.info( "Query cache: " + enabledDisabled(useQueryCache) );
  258   		settings.setQueryCacheEnabled(useQueryCache);
  259   
  260   		// The cache provider is needed when we either have second-level cache enabled
  261   		// or query cache enabled.  Note that useSecondLevelCache is enabled by default
  262   		settings.setRegionFactory( createRegionFactory( properties, ( useSecondLevelCache || useQueryCache ) ) );
  263   
  264   		boolean useMinimalPuts = PropertiesHelper.getBoolean(
  265   				Environment.USE_MINIMAL_PUTS, properties, settings.getRegionFactory().isMinimalPutsEnabledByDefault()
  266   		);
  267   		log.info( "Optimize cache for minimal puts: " + enabledDisabled(useMinimalPuts) );
  268   		settings.setMinimalPutsEnabled(useMinimalPuts);
  269   
  270   		String prefix = properties.getProperty(Environment.CACHE_REGION_PREFIX);
  271   		if ( StringHelper.isEmpty(prefix) ) prefix=null;
  272   		if (prefix!=null) log.info("Cache region prefix: "+ prefix);
  273   		settings.setCacheRegionPrefix(prefix);
  274   
  275   		boolean useStructuredCacheEntries = PropertiesHelper.getBoolean(Environment.USE_STRUCTURED_CACHE, properties, false);
  276   		log.info( "Structured second-level cache entries: " + enabledDisabled(useStructuredCacheEntries) );
  277   		settings.setStructuredCacheEntriesEnabled(useStructuredCacheEntries);
  278   
  279   		if (useQueryCache) settings.setQueryCacheFactory( createQueryCacheFactory(properties) );
  280   
  281   		//SQL Exception converter:
  282   
  283   		SQLExceptionConverter sqlExceptionConverter;
  284   		try {
  285   			sqlExceptionConverter = SQLExceptionConverterFactory.buildSQLExceptionConverter( dialect, properties );
  286   		}
  287   		catch(HibernateException e) {
  288   			log.warn("Error building SQLExceptionConverter; using minimal converter");
  289   			sqlExceptionConverter = SQLExceptionConverterFactory.buildMinimalSQLExceptionConverter();
  290   		}
  291   		settings.setSQLExceptionConverter(sqlExceptionConverter);
  292   
  293   		//Statistics and logging:
  294   
  295   		boolean showSql = PropertiesHelper.getBoolean(Environment.SHOW_SQL, properties);
  296   		if (showSql) log.info("Echoing all SQL to stdout");
  297   //		settings.setShowSqlEnabled(showSql);
  298   
  299   		boolean formatSql = PropertiesHelper.getBoolean(Environment.FORMAT_SQL, properties);
  300   //		settings.setFormatSqlEnabled(formatSql);
  301   
  302   		settings.setSqlStatementLogger( new SQLStatementLogger( showSql, formatSql ) );
  303   
  304   		boolean useStatistics = PropertiesHelper.getBoolean(Environment.GENERATE_STATISTICS, properties);
  305   		log.info( "Statistics: " + enabledDisabled(useStatistics) );
  306   		settings.setStatisticsEnabled(useStatistics);
  307   
  308   		boolean useIdentifierRollback = PropertiesHelper.getBoolean(Environment.USE_IDENTIFIER_ROLLBACK, properties);
  309   		log.info( "Deleted entity synthetic identifier rollback: " + enabledDisabled(useIdentifierRollback) );
  310   		settings.setIdentifierRollbackEnabled(useIdentifierRollback);
  311   
  312   		//Schema export:
  313   
  314   		String autoSchemaExport = properties.getProperty(Environment.HBM2DDL_AUTO);
  315   		if ( "validate".equals(autoSchemaExport) ) settings.setAutoValidateSchema(true);
  316   		if ( "update".equals(autoSchemaExport) ) settings.setAutoUpdateSchema(true);
  317   		if ( "create".equals(autoSchemaExport) ) settings.setAutoCreateSchema(true);
  318   		if ( "create-drop".equals(autoSchemaExport) ) {
  319   			settings.setAutoCreateSchema(true);
  320   			settings.setAutoDropSchema(true);
  321   		}
  322   
  323   		EntityMode defaultEntityMode = EntityMode.parse( properties.getProperty( Environment.DEFAULT_ENTITY_MODE ) );
  324   		log.info( "Default entity-mode: " + defaultEntityMode );
  325   		settings.setDefaultEntityMode( defaultEntityMode );
  326   
  327   		boolean namedQueryChecking = PropertiesHelper.getBoolean( Environment.QUERY_STARTUP_CHECKING, properties, true );
  328   		log.info( "Named query checking : " + enabledDisabled( namedQueryChecking ) );
  329   		settings.setNamedQueryStartupCheckingEnabled( namedQueryChecking );
  330   
  331   //		String provider = properties.getProperty( Environment.BYTECODE_PROVIDER );
  332   //		log.info( "Bytecode provider name : " + provider );
  333   //		BytecodeProvider bytecodeProvider = buildBytecodeProvider( provider );
  334   //		settings.setBytecodeProvider( bytecodeProvider );
  335   
  336   		return settings;
  337   
  338   	}
  339   
  340   	protected BytecodeProvider buildBytecodeProvider(String providerName) {
  341   		if ( "javassist".equals( providerName ) ) {
  342   			return new org.hibernate.bytecode.javassist.BytecodeProviderImpl();
  343   		}
  344   		else if ( "cglib".equals( providerName ) ) {
  345   			return new org.hibernate.bytecode.cglib.BytecodeProviderImpl();
  346   		}
  347   		else {
  348   			log.debug( "using cglib as bytecode provider by default" );
  349   			return new org.hibernate.bytecode.cglib.BytecodeProviderImpl();
  350   		}
  351   	}
  352   
  353   	private static String enabledDisabled(boolean value) {
  354   		return value ? "enabled" : "disabled";
  355   	}
  356   
  357   	protected QueryCacheFactory createQueryCacheFactory(Properties properties) {
  358   		String queryCacheFactoryClassName = PropertiesHelper.getString(
  359   				Environment.QUERY_CACHE_FACTORY, properties, "org.hibernate.cache.StandardQueryCacheFactory"
  360   		);
  361   		log.info("Query cache factory: " + queryCacheFactoryClassName);
  362   		try {
  363   			return (QueryCacheFactory) ReflectHelper.classForName(queryCacheFactoryClassName).newInstance();
  364   		}
  365   		catch (Exception cnfe) {
  366   			throw new HibernateException("could not instantiate QueryCacheFactory: " + queryCacheFactoryClassName, cnfe);
  367   		}
  368   	}
  369   
  370   	protected RegionFactory createRegionFactory(Properties properties, boolean cachingEnabled) {
  371   		String regionFactoryClassName = PropertiesHelper.getString( Environment.CACHE_REGION_FACTORY, properties, null );
  372   		if ( regionFactoryClassName == null && cachingEnabled ) {
  373   			String providerClassName = PropertiesHelper.getString( Environment.CACHE_PROVIDER, properties, null );
  374   			if ( providerClassName != null ) {
  375   				// legacy behavior, apply the bridge...
  376   				regionFactoryClassName = RegionFactoryCacheProviderBridge.class.getName();
  377   			}
  378   		}
  379   		if ( regionFactoryClassName == null ) {
  380   			regionFactoryClassName = DEF_CACHE_REG_FACTORY;
  381   		}
  382   		log.info( "Cache region factory : " + regionFactoryClassName );
  383   		try {
  384   			return ( RegionFactory ) ReflectHelper.classForName( regionFactoryClassName )
  385   					.getConstructor( new Class[] { Properties.class } )
  386   					.newInstance( new Object[] { properties } );
  387   		}
  388   		catch ( Exception e ) {
  389   			throw new HibernateException( "could not instantiate RegionFactory [" + regionFactoryClassName + "]", e );
  390   		}
  391   	}
  392   
  393   	protected QueryTranslatorFactory createQueryTranslatorFactory(Properties properties) {
  394   		String className = PropertiesHelper.getString(
  395   				Environment.QUERY_TRANSLATOR, properties, "org.hibernate.hql.ast.ASTQueryTranslatorFactory"
  396   		);
  397   		log.info("Query translator: " + className);
  398   		try {
  399   			return (QueryTranslatorFactory) ReflectHelper.classForName(className).newInstance();
  400   		}
  401   		catch (Exception cnfe) {
  402   			throw new HibernateException("could not instantiate QueryTranslatorFactory: " + className, cnfe);
  403   		}
  404   	}
  405   
  406   	protected BatcherFactory createBatcherFactory(Properties properties, int batchSize) {
  407   		String batcherClass = properties.getProperty(Environment.BATCH_STRATEGY);
  408   		if (batcherClass==null) {
  409   			return batchSize==0 ?
  410   					(BatcherFactory) new NonBatchingBatcherFactory() :
  411   					(BatcherFactory) new BatchingBatcherFactory();
  412   		}
  413   		else {
  414   			log.info("Batcher factory: " + batcherClass);
  415   			try {
  416   				return (BatcherFactory) ReflectHelper.classForName(batcherClass).newInstance();
  417   			}
  418   			catch (Exception cnfe) {
  419   				throw new HibernateException("could not instantiate BatcherFactory: " + batcherClass, cnfe);
  420   			}
  421   		}
  422   	}
  423   
  424   	protected ConnectionProvider createConnectionProvider(Properties properties) {
  425   		return ConnectionProviderFactory.newConnectionProvider(properties);
  426   	}
  427   
  428   	protected TransactionFactory createTransactionFactory(Properties properties) {
  429   		return TransactionFactoryFactory.buildTransactionFactory(properties);
  430   	}
  431   
  432   	protected TransactionManagerLookup createTransactionManagerLookup(Properties properties) {
  433   		return TransactionManagerLookupFactory.getTransactionManagerLookup(properties);
  434   	}
  435   
  436   }

Save This Page
Home » Hibernate-3.3.2.GA » org.hibernate » cfg » [javadoc | source]