KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > hibernate > cfg > SettingsFactory


1 //$Id: SettingsFactory.java,v 1.33 2005/05/25 04:57:11 oneovthafew Exp $
2
package org.hibernate.cfg;
3
4 import java.io.Serializable JavaDoc;
5 import java.lang.reflect.Method JavaDoc;
6 import java.sql.Connection JavaDoc;
7 import java.sql.DatabaseMetaData JavaDoc;
8 import java.sql.ResultSet JavaDoc;
9 import java.sql.SQLException JavaDoc;
10 import java.util.Map JavaDoc;
11 import java.util.Properties JavaDoc;
12
13 import org.apache.commons.logging.Log;
14 import org.apache.commons.logging.LogFactory;
15 import org.hibernate.ConnectionReleaseMode;
16 import org.hibernate.EntityMode;
17 import org.hibernate.HibernateException;
18 import org.hibernate.cache.CacheProvider;
19 import org.hibernate.cache.NoCacheProvider;
20 import org.hibernate.cache.QueryCacheFactory;
21 import org.hibernate.connection.ConnectionProvider;
22 import org.hibernate.connection.ConnectionProviderFactory;
23 import org.hibernate.dialect.Dialect;
24 import org.hibernate.dialect.DialectFactory;
25 import org.hibernate.exception.SQLExceptionConverter;
26 import org.hibernate.exception.SQLExceptionConverterFactory;
27 import org.hibernate.hql.QueryTranslatorFactory;
28 import org.hibernate.jdbc.BatcherFactory;
29 import org.hibernate.jdbc.BatchingBatcherFactory;
30 import org.hibernate.jdbc.NonBatchingBatcherFactory;
31 import org.hibernate.transaction.TransactionFactory;
32 import org.hibernate.transaction.TransactionFactoryFactory;
33 import org.hibernate.transaction.TransactionManagerLookup;
34 import org.hibernate.transaction.TransactionManagerLookupFactory;
35 import org.hibernate.util.PropertiesHelper;
36 import org.hibernate.util.ReflectHelper;
37 import org.hibernate.util.StringHelper;
38
39 /**
40  * Reads configuration properties and configures a <tt>Settings</tt> instance.
41  *
42  * @author Gavin King
43  */

44 public class SettingsFactory implements Serializable JavaDoc {
45     
46     private static final Log log = LogFactory.getLog(SettingsFactory.class);
47
48     protected SettingsFactory() throws HibernateException {}
49     
50     public Settings buildSettings(Properties JavaDoc props) {
51         Settings settings = new Settings();
52         
53         //SessionFactory name:
54

55         String JavaDoc sessionFactoryName = props.getProperty(Environment.SESSION_FACTORY_NAME);
56         settings.setSessionFactoryName(sessionFactoryName);
57
58         //JDBC and connection settings:
59

60         ConnectionProvider connections = createConnectionProvider(props);
61         settings.setConnectionProvider(connections);
62
63         //Interrogate JDBC metadata
64

65         boolean metaSupportsScrollable = false;
66         boolean metaSupportsGetGeneratedKeys = false;
67         boolean metaSupportsBatchUpdates = false;
68         String JavaDoc databaseName = null;
69         int databaseMajorVersion = 0;
70
71         try {
72             Connection JavaDoc conn = connections.getConnection();
73             try {
74                 DatabaseMetaData JavaDoc meta = conn.getMetaData();
75                 databaseName = meta.getDatabaseProductName();
76                 databaseMajorVersion = getDatabaseMajorVersion(meta);
77                 log.info("RDBMS: " + databaseName + ", version: " + meta.getDatabaseProductVersion() );
78                 log.info("JDBC driver: " + meta.getDriverName() + ", version: " + meta.getDriverVersion() );
79                 
80                 metaSupportsScrollable = meta.supportsResultSetType(ResultSet.TYPE_SCROLL_INSENSITIVE);
81                 metaSupportsBatchUpdates = meta.supportsBatchUpdates();
82                 
83                 if ( Environment.jvmSupportsGetGeneratedKeys() ) {
84                     try {
85                         Boolean JavaDoc result = (Boolean JavaDoc) DatabaseMetaData JavaDoc.class.getMethod("supportsGetGeneratedKeys", null)
86                             .invoke(meta, null);
87                         metaSupportsGetGeneratedKeys = result.booleanValue();
88                     }
89                     catch (AbstractMethodError JavaDoc ame) {
90                         metaSupportsGetGeneratedKeys = false;
91                     }
92                     catch (Exception JavaDoc e) {
93                         metaSupportsGetGeneratedKeys = false;
94                     }
95                 }
96                 
97             }
98             finally {
99                 connections.closeConnection(conn);
100             }
101         }
102         catch (SQLException JavaDoc sqle) {
103             log.warn("Could not obtain connection metadata", sqle);
104         }
105         catch (UnsupportedOperationException JavaDoc uoe) {
106             // user supplied JDBC connections
107
}
108         
109         //SQL Dialect:
110
Dialect dialect = determineDialect( props, databaseName, databaseMajorVersion );
111         settings.setDialect(dialect);
112         
113         //use dialect default properties
114
final Properties JavaDoc properties = new Properties JavaDoc();
115         properties.putAll( dialect.getDefaultProperties() );
116         properties.putAll(props);
117         
118         // Transaction settings:
119

120         TransactionFactory transactionFactory = createTransactionFactory(properties);
121         settings.setTransactionFactory(transactionFactory);
122         settings.setTransactionManagerLookup( createTransactionManagerLookup(properties) );
123
124         boolean flushBeforeCompletion = PropertiesHelper.getBoolean(Environment.FLUSH_BEFORE_COMPLETION, properties);
125         log.info("Automatic flush during beforeCompletion(): " + enabledDisabled(flushBeforeCompletion) );
126         settings.setFlushBeforeCompletionEnabled(flushBeforeCompletion);
127
128         boolean autoCloseSession = PropertiesHelper.getBoolean(Environment.AUTO_CLOSE_SESSION, properties);
129         log.info("Automatic session close at end of transaction: " + enabledDisabled(autoCloseSession) );
130         settings.setAutoCloseSessionEnabled(autoCloseSession);
131
132         //JDBC and connection settings:
133

134         int batchSize = PropertiesHelper.getInt(Environment.STATEMENT_BATCH_SIZE, properties, 0);
135         if ( !metaSupportsBatchUpdates ) batchSize = 0;
136         if (batchSize>0) log.info("JDBC batch size: " + batchSize);
137         settings.setJdbcBatchSize(batchSize);
138         boolean jdbcBatchVersionedData = PropertiesHelper.getBoolean(Environment.BATCH_VERSIONED_DATA, properties, false);
139         if (batchSize>0) log.info("JDBC batch updates for versioned data: " + enabledDisabled(jdbcBatchVersionedData) );
140         settings.setJdbcBatchVersionedData(jdbcBatchVersionedData);
141         settings.setBatcherFactory( createBatcherFactory(properties, batchSize) );
142         
143         boolean useScrollableResultSets = PropertiesHelper.getBoolean(Environment.USE_SCROLLABLE_RESULTSET, properties, metaSupportsScrollable);
144         log.info("Scrollable result sets: " + enabledDisabled(useScrollableResultSets) );
145         settings.setScrollableResultSetsEnabled(useScrollableResultSets);
146
147         boolean wrapResultSets = PropertiesHelper.getBoolean(Environment.WRAP_RESULT_SETS, properties, false);
148         log.debug( "Wrap result sets: " + enabledDisabled(wrapResultSets) );
149         settings.setWrapResultSetsEnabled(wrapResultSets);
150
151         boolean useGetGeneratedKeys = PropertiesHelper.getBoolean(Environment.USE_GET_GENERATED_KEYS, properties, metaSupportsGetGeneratedKeys);
152         log.info("JDBC3 getGeneratedKeys(): " + enabledDisabled(useGetGeneratedKeys) );
153         settings.setGetGeneratedKeysEnabled(useGetGeneratedKeys);
154
155         Integer JavaDoc statementFetchSize = PropertiesHelper.getInteger(Environment.STATEMENT_FETCH_SIZE, properties);
156         if (statementFetchSize!=null) log.info("JDBC result set fetch size: " + statementFetchSize);
157         settings.setJdbcFetchSize(statementFetchSize);
158
159         String JavaDoc releaseModeName = properties.getProperty( Environment.RELEASE_CONNECTIONS );
160         log.info( "Connection release mode: " + releaseModeName );
161         ConnectionReleaseMode releaseMode;
162         if ( "auto".equals(releaseModeName) ) {
163             releaseMode = transactionFactory.getDefaultReleaseMode();
164         }
165         else {
166             releaseMode = ConnectionReleaseMode.parse( releaseModeName );
167             if ( releaseMode == ConnectionReleaseMode.AFTER_STATEMENT && !connections.supportsAggressiveRelease() ) {
168                 log.warn( "Overriding release mode as connection provider does not support 'after_statement'" );
169                 releaseMode = ConnectionReleaseMode.AFTER_TRANSACTION;
170             }
171         }
172         settings.setConnectionReleaseMode( releaseMode );
173
174         //SQL Generation settings:
175

176         String JavaDoc defaultSchema = properties.getProperty(Environment.DEFAULT_SCHEMA);
177         String JavaDoc defaultCatalog = properties.getProperty(Environment.DEFAULT_CATALOG);
178         if (defaultSchema!=null) log.info("Default schema: " + defaultSchema);
179         if (defaultCatalog!=null) log.info("Default catalog: " + defaultCatalog);
180         settings.setDefaultSchemaName(defaultSchema);
181         settings.setDefaultCatalogName(defaultCatalog);
182
183         Integer JavaDoc maxFetchDepth = PropertiesHelper.getInteger(Environment.MAX_FETCH_DEPTH, properties);
184         if (maxFetchDepth!=null) log.info("Maximum outer join fetch depth: " + maxFetchDepth);
185         settings.setMaximumFetchDepth(maxFetchDepth);
186         int batchFetchSize = PropertiesHelper.getInt(Environment.DEFAULT_BATCH_FETCH_SIZE, properties, 1);
187         log.info("Default batch fetch size: " + batchFetchSize);
188         settings.setDefaultBatchFetchSize(batchFetchSize);
189
190         boolean comments = PropertiesHelper.getBoolean(Environment.USE_SQL_COMMENTS, properties);
191         log.info( "Generate SQL with comments: " + enabledDisabled(comments) );
192         settings.setCommentsEnabled(comments);
193         
194         boolean orderUpdates = PropertiesHelper.getBoolean(Environment.ORDER_UPDATES, properties);
195         log.info( "Order SQL updates by primary key: " + enabledDisabled(orderUpdates) );
196         settings.setOrderUpdatesEnabled(orderUpdates);
197         
198         //Query parser settings:
199

200         settings.setQueryTranslatorFactory( createQueryTranslatorFactory(properties) );
201
202         Map JavaDoc querySubstitutions = PropertiesHelper.toMap(Environment.QUERY_SUBSTITUTIONS, " ,=;:\n\t\r\f", properties);
203         log.info("Query language substitutions: " + querySubstitutions);
204         settings.setQuerySubstitutions(querySubstitutions);
205         
206         // Second-level / query cache:
207

208         boolean useSecondLevelCache = PropertiesHelper.getBoolean(Environment.USE_SECOND_LEVEL_CACHE, properties, true);
209         log.info( "Second-level cache: " + enabledDisabled(useSecondLevelCache) );
210         settings.setSecondLevelCacheEnabled(useSecondLevelCache);
211
212         boolean useQueryCache = PropertiesHelper.getBoolean(Environment.USE_QUERY_CACHE, properties);
213         log.info( "Query cache: " + enabledDisabled(useQueryCache) );
214         settings.setQueryCacheEnabled(useQueryCache);
215
216         if ( useSecondLevelCache || useQueryCache ) {
217             // The cache provider is needed when we either have second-level cache enabled
218
// or query cache enabled. Note that useSecondLevelCache is enabled by default
219
settings.setCacheProvider( createCacheProvider( properties ) );
220         }
221         else {
222             settings.setCacheProvider( new NoCacheProvider() );
223         }
224
225         boolean useMinimalPuts = PropertiesHelper.getBoolean(
226                 Environment.USE_MINIMAL_PUTS, properties, settings.getCacheProvider().isMinimalPutsEnabledByDefault()
227         );
228         log.info( "Optimize cache for minimal puts: " + enabledDisabled(useMinimalPuts) );
229         settings.setMinimalPutsEnabled(useMinimalPuts);
230
231         String JavaDoc prefix = properties.getProperty(Environment.CACHE_REGION_PREFIX);
232         if ( StringHelper.isEmpty(prefix) ) prefix=null;
233         if (prefix!=null) log.info("Cache region prefix: "+ prefix);
234         settings.setCacheRegionPrefix(prefix);
235
236         boolean useStructuredCacheEntries = PropertiesHelper.getBoolean(Environment.USE_STRUCTURED_CACHE, properties, false);
237         log.info( "Structured second-level cache entries: " + enabledDisabled(useStructuredCacheEntries) );
238         settings.setStructuredCacheEntriesEnabled(useStructuredCacheEntries);
239
240         if (useQueryCache) settings.setQueryCacheFactory( createQueryCacheFactory(properties) );
241         
242         //SQL Exception converter:
243

244         SQLExceptionConverter sqlExceptionConverter;
245         try {
246             sqlExceptionConverter = SQLExceptionConverterFactory.buildSQLExceptionConverter( dialect, properties );
247         }
248         catch(HibernateException e) {
249             log.warn("Error building SQLExceptionConverter; using minimal converter");
250             sqlExceptionConverter = SQLExceptionConverterFactory.buildMinimalSQLExceptionConverter();
251         }
252         settings.setSQLExceptionConverter(sqlExceptionConverter);
253
254         //Statistics and logging:
255

256         boolean showSql = PropertiesHelper.getBoolean(Environment.SHOW_SQL, properties);
257         if (showSql) log.info("Echoing all SQL to stdout");
258         settings.setShowSqlEnabled(showSql);
259
260         boolean useStatistics = PropertiesHelper.getBoolean(Environment.GENERATE_STATISTICS, properties);
261         log.info( "Statistics: " + enabledDisabled(useStatistics) );
262         settings.setStatisticsEnabled(useStatistics);
263         
264         boolean useIdentifierRollback = PropertiesHelper.getBoolean(Environment.USE_IDENTIFIER_ROLLBACK, properties);
265         log.info( "Deleted entity synthetic identifier rollback: " + enabledDisabled(useIdentifierRollback) );
266         settings.setIdentifierRollbackEnabled(useIdentifierRollback);
267         
268         //Schema export:
269

270         String JavaDoc autoSchemaExport = properties.getProperty(Environment.HBM2DDL_AUTO);
271         if ( "update".equals(autoSchemaExport) ) settings.setAutoUpdateSchema(true);
272         if ( "create".equals(autoSchemaExport) ) settings.setAutoCreateSchema(true);
273         if ( "create-drop".equals(autoSchemaExport) ) {
274             settings.setAutoCreateSchema(true);
275             settings.setAutoDropSchema(true);
276         }
277
278         EntityMode defaultEntityMode = EntityMode.parse( properties.getProperty( Environment.DEFAULT_ENTITY_MODE ) );
279         log.info( "Default entity-mode: " + defaultEntityMode );
280         settings.setDefaultEntityMode( defaultEntityMode );
281
282         return settings;
283
284     }
285
286     private int getDatabaseMajorVersion(DatabaseMetaData JavaDoc meta) {
287         try {
288             Method JavaDoc gdbmvMethod = DatabaseMetaData JavaDoc.class.getMethod("getDatabaseMajorVersion", null);
289             return ( (Integer JavaDoc) gdbmvMethod.invoke(meta, null) ).intValue();
290         }
291         catch (NoSuchMethodException JavaDoc nsme) {
292             return 0;
293         }
294         catch (Throwable JavaDoc t) {
295             log.debug("could not get database version from JDBC metadata");
296             return 0;
297         }
298     }
299
300     private static final String JavaDoc enabledDisabled(boolean value) {
301         return value ? "enabled" : "disabled";
302     }
303     
304     protected QueryCacheFactory createQueryCacheFactory(Properties JavaDoc properties) {
305         String JavaDoc queryCacheFactoryClassName = PropertiesHelper.getString(
306                 Environment.QUERY_CACHE_FACTORY, properties, "org.hibernate.cache.StandardQueryCacheFactory"
307         );
308         log.info("Query cache factory: " + queryCacheFactoryClassName);
309         try {
310             return (QueryCacheFactory) ReflectHelper.classForName(queryCacheFactoryClassName).newInstance();
311         }
312         catch (Exception JavaDoc cnfe) {
313             throw new HibernateException("could not instantiate QueryCacheFactory: " + queryCacheFactoryClassName, cnfe);
314         }
315     }
316     
317     protected CacheProvider createCacheProvider(Properties JavaDoc properties) {
318         String JavaDoc cacheClassName = PropertiesHelper.getString(
319                 Environment.CACHE_PROVIDER, properties, "org.hibernate.cache.EhCacheProvider"
320         );
321         log.info("Cache provider: " + cacheClassName);
322         try {
323             return (CacheProvider) ReflectHelper.classForName(cacheClassName).newInstance();
324         }
325         catch (Exception JavaDoc cnfe) {
326             throw new HibernateException("could not instantiate CacheProvider: " + cacheClassName, cnfe);
327         }
328     }
329     
330     protected QueryTranslatorFactory createQueryTranslatorFactory(Properties JavaDoc properties) {
331         String JavaDoc className = PropertiesHelper.getString(
332                 Environment.QUERY_TRANSLATOR, properties, "org.hibernate.hql.ast.ASTQueryTranslatorFactory"
333         );
334         log.info("Query translator: " + className);
335         try {
336             return (QueryTranslatorFactory) ReflectHelper.classForName(className).newInstance();
337         }
338         catch (Exception JavaDoc cnfe) {
339             throw new HibernateException("could not instantiate QueryTranslatorFactory: " + className, cnfe);
340         }
341     }
342     
343     protected BatcherFactory createBatcherFactory(Properties JavaDoc properties, int batchSize) {
344         String JavaDoc batcherClass = properties.getProperty(Environment.BATCH_STRATEGY);
345         if (batcherClass==null) {
346             return batchSize==0 ?
347                     (BatcherFactory) new NonBatchingBatcherFactory() :
348                     (BatcherFactory) new BatchingBatcherFactory();
349         }
350         else {
351             log.info("Batcher factory: " + batcherClass);
352             try {
353                 return (BatcherFactory) ReflectHelper.classForName(batcherClass).newInstance();
354             }
355             catch (Exception JavaDoc cnfe) {
356                 throw new HibernateException("could not instantiate BatcherFactory: " + batcherClass, cnfe);
357             }
358         }
359     }
360     
361     protected ConnectionProvider createConnectionProvider(Properties JavaDoc properties) {
362         return ConnectionProviderFactory.newConnectionProvider(properties);
363     }
364     
365     protected TransactionFactory createTransactionFactory(Properties JavaDoc properties) {
366         return TransactionFactoryFactory.buildTransactionFactory(properties);
367     }
368     
369     protected TransactionManagerLookup createTransactionManagerLookup(Properties JavaDoc properties) {
370         return TransactionManagerLookupFactory.getTransactionManagerLookup(properties);
371     }
372
373     private Dialect determineDialect(Properties JavaDoc props, String JavaDoc databaseName, int databaseMajorVersion) {
374         return DialectFactory.buildDialect( props, databaseName, databaseMajorVersion );
375     }
376     
377     private static final Properties JavaDoc DIALECTS = new Properties JavaDoc();
378     static {
379         DIALECTS.put( "HSQL Database Engine", "org.hibernate.dialect.HSQLDialect" );
380         DIALECTS.put( "DB2/NT", "org.hibernate.dialect.DB2Dialect" );
381         DIALECTS.put( "MySQL", "org.hibernate.dialect.MySQLDialect" );
382         DIALECTS.put( "Oracle", "org.hibernate.dialect.Oracle9Dialect" );
383         DIALECTS.put( "PostgreSQL", "org.hibernate.dialect.PostgreSQLDialect" );
384         DIALECTS.put( "Microsoft SQL Server Database", "org.hibernate.dialect.SQLServerDialect" );
385         DIALECTS.put( "Sybase SQL Server", "org.hibernate.dialect.SybaseDialect" );
386         //TODO: etc...
387
}
388     
389 }
390
Popular Tags