diff --git a/org.springframework.integration-tests/integration-tests.iml b/org.springframework.integration-tests/integration-tests.iml index c575fd5536..374bd67fbd 100644 --- a/org.springframework.integration-tests/integration-tests.iml +++ b/org.springframework.integration-tests/integration-tests.iml @@ -33,7 +33,6 @@ - diff --git a/org.springframework.integration-tests/ivy.xml b/org.springframework.integration-tests/ivy.xml index f4d035168e..29e307330f 100644 --- a/org.springframework.integration-tests/ivy.xml +++ b/org.springframework.integration-tests/ivy.xml @@ -74,9 +74,7 @@ - - diff --git a/org.springframework.integration-tests/src/test/java/org/springframework/orm/hibernate3/HibernateSessionFactoryConfigurationTests.java b/org.springframework.integration-tests/src/test/java/org/springframework/orm/hibernate3/HibernateSessionFactoryConfigurationTests.java deleted file mode 100644 index 94a4be325d..0000000000 --- a/org.springframework.integration-tests/src/test/java/org/springframework/orm/hibernate3/HibernateSessionFactoryConfigurationTests.java +++ /dev/null @@ -1,340 +0,0 @@ -/* - * Copyright 2002-2011 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.orm.hibernate3; - -import static org.hamcrest.CoreMatchers.instanceOf; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.CoreMatchers.notNullValue; -import static org.junit.Assert.assertThat; - -import java.io.File; -import java.util.List; - -import javax.inject.Inject; -import javax.sql.DataSource; - -import org.hibernate.SessionFactory; -import org.hibernate.Transaction; -import org.hibernate.cfg.AnnotationConfiguration; -import org.hibernate.classic.Session; -import org.junit.Ignore; -import org.junit.Test; -import org.springframework.beans.factory.BeanCreationException; -import org.springframework.context.annotation.AnnotationConfigApplicationContext; -import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.ImportResource; -import org.springframework.dao.DataAccessException; -import org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor; -import org.springframework.dao.support.PersistenceExceptionTranslator; -import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; -import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType; -import org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBuilder; -import org.springframework.orm.hibernate3.scannable.Foo; -import org.springframework.stereotype.Repository; -import org.springframework.transaction.PlatformTransactionManager; -import org.springframework.transaction.annotation.EnableTransactionManagement; -import org.springframework.transaction.annotation.Transactional; - -/** - * Integration tests for configuring Hibernate SessionFactory types - * without using a FactoryBean, e.g., within a {@link Configuration} class. - * - * @author Chris Beams - * @since 3.1 - */ -public class HibernateSessionFactoryConfigurationTests { - - @Test - public void usingLocalSessionFactoryBean() { - saveAndRetriveEntity(LocalSessionFactoryBeanXmlConfig.class); - } - - @Test - public void usingAnnotationSessionFactoryBean() { - saveAndRetriveEntity(AnnotationSessionFactoryBeanXmlConfig.class); - } - - @Ignore @Test - public void usingNativeHibernateConfiguration() { - saveAndRetriveEntity(NativeHibernateConfig.class); - } - - @Test - public void usingSessionFactoryBuilder_withConfigurationCallback() { - saveAndRetriveEntity(SessionFactoryConfig_withConfigurationCallback.class); - } - - @Test - public void usingAnnotationSessionFactoryBuilder() { - saveAndRetriveEntity(AnnotationSessionFactoryConfig.class); - } - - @Test - public void usingAnnotationSessionFactoryBuilder_withConfigurationCallback() { - saveAndRetriveEntity(AnnotationSessionFactoryConfig_withConfigurationCallback.class); - } - - @Test - public void usingAnnotationSessionFactoryBuilder_withPackagesToScan() { - saveAndRetriveEntity(AnnotationSessionFactoryConfig_withPackagesToScan.class); - } - - @Test - public void usingAnnotationSessionFactoryBuilder_withAnnotatedClasses() { - saveAndRetriveEntity(AnnotationSessionFactoryConfig_withAnnotatedClasses.class); - } - - - @Test(expected=DataAccessException.class) - public void exceptionTranslation_withLocalSessionFactoryBean() { - causeException(LocalSessionFactoryBeanXmlConfig.class, RepositoryConfig.class); - } - - @Test(expected=DataAccessException.class) - public void exceptionTranslation_withSessionFactoryBuilder() { - causeException(SessionFactoryConfig_withConfigurationCallback.class, - RepositoryConfig.class); - } - - @Test - public void usingSessionFactoryBuilder_withCustomConfigurationClass() { - saveAndRetriveEntity(SessionFactoryConfig_withCustomConfigurationClass.class); - } - - @Test(expected=IllegalStateException.class) - public void usingSessionFactoryBuilder_withLateCustomConfigurationClass() throws Throwable { - try { - saveAndRetriveEntity(SessionFactoryConfig_withLateCustomConfigurationClass.class); - } catch (BeanCreationException ex) { - Throwable cause = ex.getRootCause(); - assertThat(cause.getMessage().startsWith("setConfigurationClass() must be called before"), is(true)); - throw cause; - } - } - - - private void saveAndRetriveEntity(Class configClass) { - SessionFactory sessionFactory = new AnnotationConfigApplicationContext(configClass).getBean(SessionFactory.class); - Session session = sessionFactory.openSession(); - Transaction tx = session.beginTransaction(); - Foo foo = new Foo(); - foo.setName("f1"); - session.save(foo); - - Foo f1 = (Foo) session.createQuery("from Foo where name = 'f1'").uniqueResult(); - assertThat("No foo with name='f1' found!", f1, notNullValue()); - assertThat(f1.getName(), is("f1")); - - tx.rollback(); - } - - private void causeException(Class... configClasses) { - FooRepository fooRepository = new AnnotationConfigApplicationContext(configClasses).getBean(FooRepository.class); - fooRepository.findAll(); // will throw - } - - - @Configuration - static class DataConfig { - @Bean - DataSource dataSource() { - return new EmbeddedDatabaseBuilder() - .setType(EmbeddedDatabaseType.HSQL) - .build(); - } - } - - - @Configuration - @ImportResource("org/springframework/orm/hibernate3/LocalSessionFactoryBeanXmlConfig-context.xml") - static class LocalSessionFactoryBeanXmlConfig extends DataConfig { - } - - - interface FooRepository { - List findAll(); - } - - @Repository - public static class HibernateFooRepository implements FooRepository { - private final SessionFactory sessionFactory; - public HibernateFooRepository(SessionFactory sessionFactory) { - this.sessionFactory = sessionFactory; - } - @Transactional - @SuppressWarnings("unchecked") - public List findAll() { - return sessionFactory.getCurrentSession().createQuery("from Bogus").list(); - } - } - - - @Configuration - @EnableTransactionManagement - static class RepositoryConfig { - @Inject SessionFactory sessionFactory; - - @Bean - FooRepository fooRepository() { - return new HibernateFooRepository(sessionFactory); - } - - @Bean - PlatformTransactionManager txManager() { - return new HibernateTransactionManager(sessionFactory); - } - - @Bean - PersistenceExceptionTranslationPostProcessor exceptionTranslationPostProcessor() { - return new PersistenceExceptionTranslationPostProcessor(); - } - - @Bean - PersistenceExceptionTranslator exceptionTranslator() { - return new HibernateExceptionTranslator(); - } - } - - - @Configuration - @ImportResource("org/springframework/orm/hibernate3/AnnotationSessionFactoryBeanXmlConfig-context.xml") - static class AnnotationSessionFactoryBeanXmlConfig extends DataConfig { - } - - - @Configuration - static class NativeHibernateConfig { - @Bean - SessionFactory sessionFactory() { - org.hibernate.cfg.Configuration cfg = new AnnotationConfiguration(); - return cfg.buildSessionFactory(); - } - } - - - @Configuration - static class AnnotationSessionFactoryConfig extends DataConfig { - @Bean - SessionFactory sessionFactory() throws Exception { - return new AnnotationSessionFactoryBuilder(dataSource()) - .setSchemaUpdate(true) - .doWithConfiguration(new HibernateConfigurationCallback() { - public void configure(AnnotationConfiguration configuration) { - configuration.addAnnotatedClass(Foo.class); - } - }) - .buildSessionFactory(); - } - } - - - @Configuration - static class AnnotationSessionFactoryConfig_withPackagesToScan extends DataConfig { - @Bean - SessionFactory sessionFactory() throws Exception { - return new AnnotationSessionFactoryBuilder(dataSource()) - .setSchemaUpdate(true) - .setPackagesToScan(Foo.class.getPackage().getName()) - .buildSessionFactory(); - } - } - - @Configuration - static class AnnotationSessionFactoryConfig_withAnnotatedClasses extends DataConfig { - @Bean - SessionFactory sessionFactory() throws Exception { - return new AnnotationSessionFactoryBuilder(dataSource()) - .setSchemaUpdate(true) - .setAnnotatedClasses(Foo.class, Foo.class) - .buildSessionFactory(); - } - } - - - @Configuration - static class AnnotationSessionFactoryConfig_withConfigurationCallback extends DataConfig { - @Bean - SessionFactory sessionFactory() throws Exception { - return new AnnotationSessionFactoryBuilder(dataSource()) - .setSchemaUpdate(true) - .doWithConfiguration(new HibernateConfigurationCallback() { - public void configure(AnnotationConfiguration configuration) throws Exception { - configuration.addAnnotatedClass(Foo.class); - } - }) - .buildSessionFactory(); - } - } - - - @Configuration - static class SessionFactoryConfig_withConfigurationCallback extends DataConfig { - @Bean - SessionFactory sessionFactory() throws Exception { - return new SessionFactoryBuilder(dataSource()) - .setSchemaUpdate(true) - .doWithConfiguration(new HibernateConfigurationCallback() { - public void configure(org.hibernate.cfg.Configuration configuration) throws Exception { - configuration.addFile(new File(this.getClass().getClassLoader().getResource("org/springframework/orm/hibernate3/scannable/FooMapping.hbm.xml").toURI())); - } - }) - .buildSessionFactory(); - } - } - - - @Configuration - static class SessionFactoryConfig_withCustomConfigurationClass extends DataConfig { - @Bean - SessionFactory sessionFactory() throws Exception { - SessionFactoryBuilder sfb = new SessionFactoryBuilder(dataSource()) - .setSchemaUpdate(true) - .setConfigurationClass(CustomHibernateConfiguration.class) - .doWithConfiguration(new HibernateConfigurationCallback() { - public void configure(org.hibernate.cfg.Configuration configuration) throws Exception { - configuration.addFile(new File(this.getClass().getClassLoader().getResource("org/springframework/orm/hibernate3/scannable/FooMapping.hbm.xml").toURI())); - } - }); - assertThat(sfb.getConfiguration(), instanceOf(CustomHibernateConfiguration.class)); - return sfb.buildSessionFactory(); - } - } - - - @Configuration - static class SessionFactoryConfig_withLateCustomConfigurationClass extends DataConfig { - @Bean - SessionFactory sessionFactory() throws Exception { - return new SessionFactoryBuilder(dataSource()) - .setSchemaUpdate(true) - .doWithConfiguration(new HibernateConfigurationCallback() { - public void configure(org.hibernate.cfg.Configuration configuration) throws Exception { - configuration.addFile(new File(this.getClass().getClassLoader().getResource("org/springframework/orm/hibernate3/scannable/FooMapping.hbm.xml").toURI())); - } - }) - .setConfigurationClass(CustomHibernateConfiguration.class) - .buildSessionFactory(); - } - } - - - @SuppressWarnings("serial") - static class CustomHibernateConfiguration extends org.hibernate.cfg.Configuration { - } - -} diff --git a/org.springframework.integration-tests/src/test/java/org/springframework/orm/hibernate3/scannable/Foo.java b/org.springframework.integration-tests/src/test/java/org/springframework/orm/hibernate3/scannable/Foo.java deleted file mode 100644 index 0728499b09..0000000000 --- a/org.springframework.integration-tests/src/test/java/org/springframework/orm/hibernate3/scannable/Foo.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2002-2011 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.orm.hibernate3.scannable; - -import javax.persistence.Entity; -import javax.persistence.Id; - -@Entity -public class Foo { - @SuppressWarnings("unused") - @Id private int id; - - private String name; - - public void setName(String name) { - this.name = name; - } - - public String getName() { - return this.name; - } -} \ No newline at end of file diff --git a/org.springframework.integration-tests/src/test/resources/org/springframework/orm/hibernate3/AnnotationSessionFactoryBeanXmlConfig-context.xml b/org.springframework.integration-tests/src/test/resources/org/springframework/orm/hibernate3/AnnotationSessionFactoryBeanXmlConfig-context.xml deleted file mode 100644 index dd5ec1d94c..0000000000 --- a/org.springframework.integration-tests/src/test/resources/org/springframework/orm/hibernate3/AnnotationSessionFactoryBeanXmlConfig-context.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - diff --git a/org.springframework.integration-tests/src/test/resources/org/springframework/orm/hibernate3/LocalSessionFactoryBeanXmlConfig-context.xml b/org.springframework.integration-tests/src/test/resources/org/springframework/orm/hibernate3/LocalSessionFactoryBeanXmlConfig-context.xml deleted file mode 100644 index c3a2f30b31..0000000000 --- a/org.springframework.integration-tests/src/test/resources/org/springframework/orm/hibernate3/LocalSessionFactoryBeanXmlConfig-context.xml +++ /dev/null @@ -1,18 +0,0 @@ - - - - - - - - - - - hibernate.dialect=org.hibernate.dialect.HSQLDialect - - - - - \ No newline at end of file diff --git a/org.springframework.integration-tests/src/test/resources/org/springframework/orm/hibernate3/scannable/FooMapping.hbm.xml b/org.springframework.integration-tests/src/test/resources/org/springframework/orm/hibernate3/scannable/FooMapping.hbm.xml deleted file mode 100644 index 187f145218..0000000000 --- a/org.springframework.integration-tests/src/test/resources/org/springframework/orm/hibernate3/scannable/FooMapping.hbm.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - diff --git a/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/AbstractSessionFactoryBean.java b/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/AbstractSessionFactoryBean.java new file mode 100644 index 0000000000..135538e795 --- /dev/null +++ b/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/AbstractSessionFactoryBean.java @@ -0,0 +1,336 @@ +/* + * Copyright 2002-2010 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.orm.hibernate3; + +import javax.sql.DataSource; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.hibernate.HibernateException; +import org.hibernate.JDBCException; +import org.hibernate.SessionFactory; + +import org.springframework.beans.factory.DisposableBean; +import org.springframework.beans.factory.FactoryBean; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.dao.DataAccessException; +import org.springframework.dao.support.PersistenceExceptionTranslator; +import org.springframework.jdbc.support.SQLExceptionTranslator; + +/** + * Abstract {@link org.springframework.beans.factory.FactoryBean} that creates + * a Hibernate {@link org.hibernate.SessionFactory} within a Spring application + * context, providing general infrastructure not related to Hibernate's + * specific configuration API. + * + *

This class implements the + * {@link org.springframework.dao.support.PersistenceExceptionTranslator} + * interface, as autodetected by Spring's + * {@link org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor}, + * for AOP-based translation of native exceptions to Spring DataAccessExceptions. + * Hence, the presence of e.g. LocalSessionFactoryBean automatically enables + * a PersistenceExceptionTranslationPostProcessor to translate Hibernate exceptions. + * + *

This class mainly serves as common base class for {@link LocalSessionFactoryBean}. + * For details on typical SessionFactory setup, see the LocalSessionFactoryBean javadoc. + * + * @author Juergen Hoeller + * @since 2.0 + * @see #setExposeTransactionAwareSessionFactory + * @see org.hibernate.SessionFactory#getCurrentSession() + * @see org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor + */ +public abstract class AbstractSessionFactoryBean + implements FactoryBean, InitializingBean, DisposableBean, PersistenceExceptionTranslator { + + /** Logger available to subclasses */ + protected final Log logger = LogFactory.getLog(getClass()); + + private DataSource dataSource; + + private boolean useTransactionAwareDataSource = false; + + private boolean exposeTransactionAwareSessionFactory = true; + + private SQLExceptionTranslator jdbcExceptionTranslator; + + private SessionFactory sessionFactory; + + + /** + * Set the DataSource to be used by the SessionFactory. + * If set, this will override corresponding settings in Hibernate properties. + *

If this is set, the Hibernate settings should not define + * a connection provider to avoid meaningless double configuration. + *

If using HibernateTransactionManager as transaction strategy, consider + * proxying your target DataSource with a LazyConnectionDataSourceProxy. + * This defers fetching of an actual JDBC Connection until the first JDBC + * Statement gets executed, even within JDBC transactions (as performed by + * HibernateTransactionManager). Such lazy fetching is particularly beneficial + * for read-only operations, in particular if the chances of resolving the + * result in the second-level cache are high. + *

As JTA and transactional JNDI DataSources already provide lazy enlistment + * of JDBC Connections, LazyConnectionDataSourceProxy does not add value with + * JTA (i.e. Spring's JtaTransactionManager) as transaction strategy. + * @see #setUseTransactionAwareDataSource + * @see HibernateTransactionManager + * @see org.springframework.transaction.jta.JtaTransactionManager + * @see org.springframework.jdbc.datasource.LazyConnectionDataSourceProxy + */ + public void setDataSource(DataSource dataSource) { + this.dataSource = dataSource; + } + + /** + * Return the DataSource to be used by the SessionFactory. + */ + public DataSource getDataSource() { + return this.dataSource; + } + + /** + * Set whether to use a transaction-aware DataSource for the SessionFactory, + * i.e. whether to automatically wrap the passed-in DataSource with Spring's + * TransactionAwareDataSourceProxy. + *

Default is "false": LocalSessionFactoryBean is usually used with Spring's + * HibernateTransactionManager or JtaTransactionManager, both of which work nicely + * on a plain JDBC DataSource. Hibernate Sessions and their JDBC Connections are + * fully managed by the Hibernate/JTA transaction infrastructure in such a scenario. + *

If you switch this flag to "true", Spring's Hibernate access will be able to + * participate in JDBC-based transactions managed outside of Hibernate + * (for example, by Spring's DataSourceTransactionManager). This can be convenient + * if you need a different local transaction strategy for another O/R mapping tool, + * for example, but still want Hibernate access to join into those transactions. + *

A further benefit of this option is that plain Sessions opened directly + * via the SessionFactory, outside of Spring's Hibernate support, will still + * participate in active Spring-managed transactions. However, consider using + * Hibernate's getCurrentSession() method instead (see javadoc of + * "exposeTransactionAwareSessionFactory" property). + *

WARNING: When using a transaction-aware JDBC DataSource in combination + * with OpenSessionInViewFilter/Interceptor, whether participating in JTA or + * external JDBC-based transactions, it is strongly recommended to set Hibernate's + * Connection release mode to "after_transaction" or "after_statement", which + * guarantees proper Connection handling in such a scenario. In contrast to that, + * HibernateTransactionManager generally requires release mode "on_close". + *

Note: If you want to use Hibernate's Connection release mode "after_statement" + * with a DataSource specified on this LocalSessionFactoryBean (for example, a + * JTA-aware DataSource fetched from JNDI), switch this setting to "true". + * Otherwise, the ConnectionProvider used underneath will vote against aggressive + * release and thus silently switch to release mode "after_transaction". + * @see #setDataSource + * @see #setExposeTransactionAwareSessionFactory + * @see org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy + * @see org.springframework.jdbc.datasource.DataSourceTransactionManager + * @see org.springframework.orm.hibernate3.support.OpenSessionInViewFilter + * @see org.springframework.orm.hibernate3.support.OpenSessionInViewInterceptor + * @see HibernateTransactionManager + * @see org.springframework.transaction.jta.JtaTransactionManager + */ + public void setUseTransactionAwareDataSource(boolean useTransactionAwareDataSource) { + this.useTransactionAwareDataSource = useTransactionAwareDataSource; + } + + /** + * Return whether to use a transaction-aware DataSource for the SessionFactory. + */ + protected boolean isUseTransactionAwareDataSource() { + return this.useTransactionAwareDataSource; + } + + /** + * Set whether to expose a transaction-aware current Session from the + * SessionFactory's getCurrentSession() method, returning the + * Session that's associated with the current Spring-managed transaction, if any. + *

Default is "true", letting data access code work with the plain + * Hibernate SessionFactory and its getCurrentSession() method, + * while still being able to participate in current Spring-managed transactions: + * with any transaction management strategy, either local or JTA / EJB CMT, + * and any transaction synchronization mechanism, either Spring or JTA. + * Furthermore, getCurrentSession() will also seamlessly work with + * a request-scoped Session managed by OpenSessionInViewFilter/Interceptor. + *

Turn this flag off to expose the plain Hibernate SessionFactory with + * Hibernate's default getCurrentSession() behavior, supporting + * plain JTA synchronization only. Alternatively, simply override the + * corresponding Hibernate property "hibernate.current_session_context_class". + * @see SpringSessionContext + * @see org.hibernate.SessionFactory#getCurrentSession() + * @see org.springframework.transaction.jta.JtaTransactionManager + * @see HibernateTransactionManager + * @see org.springframework.orm.hibernate3.support.OpenSessionInViewFilter + * @see org.springframework.orm.hibernate3.support.OpenSessionInViewInterceptor + */ + public void setExposeTransactionAwareSessionFactory(boolean exposeTransactionAwareSessionFactory) { + this.exposeTransactionAwareSessionFactory = exposeTransactionAwareSessionFactory; + } + + /** + * Return whether to expose a transaction-aware proxy for the SessionFactory. + */ + protected boolean isExposeTransactionAwareSessionFactory() { + return this.exposeTransactionAwareSessionFactory; + } + + /** + * Set the JDBC exception translator for the SessionFactory, + * exposed via the PersistenceExceptionTranslator interface. + *

Applied to any SQLException root cause of a Hibernate JDBCException, + * overriding Hibernate's default SQLException translation (which is + * based on Hibernate's Dialect for a specific target database). + * @param jdbcExceptionTranslator the exception translator + * @see java.sql.SQLException + * @see org.hibernate.JDBCException + * @see org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator + * @see org.springframework.jdbc.support.SQLStateSQLExceptionTranslator + * @see org.springframework.dao.support.PersistenceExceptionTranslator + */ + public void setJdbcExceptionTranslator(SQLExceptionTranslator jdbcExceptionTranslator) { + this.jdbcExceptionTranslator = jdbcExceptionTranslator; + } + + + /** + * Build and expose the SessionFactory. + * @see #buildSessionFactory() + * @see #wrapSessionFactoryIfNecessary + */ + public void afterPropertiesSet() throws Exception { + SessionFactory rawSf = buildSessionFactory(); + this.sessionFactory = wrapSessionFactoryIfNecessary(rawSf); + afterSessionFactoryCreation(); + } + + /** + * Wrap the given SessionFactory with a proxy, if demanded. + *

The default implementation simply returns the given SessionFactory as-is. + * Subclasses may override this to implement transaction awareness through + * a SessionFactory proxy, for example. + * @param rawSf the raw SessionFactory as built by {@link #buildSessionFactory()} + * @return the SessionFactory reference to expose + * @see #buildSessionFactory() + */ + protected SessionFactory wrapSessionFactoryIfNecessary(SessionFactory rawSf) { + return rawSf; + } + + /** + * Return the exposed SessionFactory. + * Will throw an exception if not initialized yet. + * @return the SessionFactory (never null) + * @throws IllegalStateException if the SessionFactory has not been initialized yet + */ + protected final SessionFactory getSessionFactory() { + if (this.sessionFactory == null) { + throw new IllegalStateException("SessionFactory not initialized yet"); + } + return this.sessionFactory; + } + + /** + * Close the SessionFactory on bean factory shutdown. + */ + public void destroy() throws HibernateException { + logger.info("Closing Hibernate SessionFactory"); + try { + beforeSessionFactoryDestruction(); + } + finally { + this.sessionFactory.close(); + } + } + + + /** + * Return the singleton SessionFactory. + */ + public SessionFactory getObject() { + return this.sessionFactory; + } + + public Class getObjectType() { + return (this.sessionFactory != null ? this.sessionFactory.getClass() : SessionFactory.class); + } + + public boolean isSingleton() { + return true; + } + + + /** + * Implementation of the PersistenceExceptionTranslator interface, + * as autodetected by Spring's PersistenceExceptionTranslationPostProcessor. + *

Converts the exception if it is a HibernateException; + * else returns null to indicate an unknown exception. + * @see org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor + * @see #convertHibernateAccessException + */ + public DataAccessException translateExceptionIfPossible(RuntimeException ex) { + if (ex instanceof HibernateException) { + return convertHibernateAccessException((HibernateException) ex); + } + return null; + } + + /** + * Convert the given HibernateException to an appropriate exception from the + * org.springframework.dao hierarchy. + *

Will automatically apply a specified SQLExceptionTranslator to a + * Hibernate JDBCException, else rely on Hibernate's default translation. + * @param ex HibernateException that occured + * @return a corresponding DataAccessException + * @see SessionFactoryUtils#convertHibernateAccessException + * @see #setJdbcExceptionTranslator + */ + protected DataAccessException convertHibernateAccessException(HibernateException ex) { + if (this.jdbcExceptionTranslator != null && ex instanceof JDBCException) { + JDBCException jdbcEx = (JDBCException) ex; + return this.jdbcExceptionTranslator.translate( + "Hibernate operation: " + jdbcEx.getMessage(), jdbcEx.getSQL(), jdbcEx.getSQLException()); + } + return SessionFactoryUtils.convertHibernateAccessException(ex); + } + + + /** + * Build the underlying Hibernate SessionFactory. + * @return the raw SessionFactory (potentially to be wrapped with a + * transaction-aware proxy before it is exposed to the application) + * @throws Exception in case of initialization failure + */ + protected abstract SessionFactory buildSessionFactory() throws Exception; + + /** + * Hook that allows post-processing after the SessionFactory has been + * successfully created. The SessionFactory is already available through + * getSessionFactory() at this point. + *

This implementation is empty. + * @throws Exception in case of initialization failure + * @see #getSessionFactory() + */ + protected void afterSessionFactoryCreation() throws Exception { + } + + /** + * Hook that allows shutdown processing before the SessionFactory + * will be closed. The SessionFactory is still available through + * getSessionFactory() at this point. + *

This implementation is empty. + * @see #getSessionFactory() + */ + protected void beforeSessionFactoryDestruction() { + } + +} diff --git a/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/FilterDefinitionFactoryBean.java b/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/FilterDefinitionFactoryBean.java index 3f84727aa0..04b7789d3b 100644 --- a/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/FilterDefinitionFactoryBean.java +++ b/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/FilterDefinitionFactoryBean.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2011 the original author or authors. + * Copyright 2002-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -37,25 +37,24 @@ import org.springframework.util.ReflectionUtils; * definition, as the list element for the "filterDefinitions" bean property. * For example: * - *

- * {@code
- * 
+ * 
+ * <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
  *   ...
- *   
- *     
- *       
- *         
- *         
- *           
- *             
- *             
- *           
- *         
- *       
- *     
- *   
+ *   <property name="filterDefinitions">
+ *     <list>
+ *       <bean class="org.springframework.orm.hibernate3.FilterDefinitionFactoryBean">
+ *         <property name="filterName" value="myFilter"/>
+ *         <property name="parameterTypes">
+ *           <map>
+ *             <entry key="myParam" value="string"/>
+ *             <entry key="myOtherParam" value="long"/>
+ *           </map>
+ *         </property>
+ *       </bean>
+ *     </list>
+ *   </property>
  *   ...
- * }
+ * </bean>
* * Alternatively, specify a bean id (or name) attribute for the inner bean, * instead of the "filterName" property. @@ -74,7 +73,7 @@ public class FilterDefinitionFactoryBean implements FactoryBean trClass = FilterDefinitionFactoryBean.class.getClassLoader().loadClass( + Class trClass = FilterDefinitionFactoryBean.class.getClassLoader().loadClass( "org.hibernate.type.TypeResolver"); heuristicTypeMethod = trClass.getMethod("heuristicType", String.class); typeResolver = trClass.newInstance(); diff --git a/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/HibernateAccessor.java b/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/HibernateAccessor.java index 7b3b4e05a3..7fe337d659 100644 --- a/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/HibernateAccessor.java +++ b/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/HibernateAccessor.java @@ -181,13 +181,12 @@ public abstract class HibernateAccessor implements InitializingBean, BeanFactory * property values before writing to and reading from the database. * Will get applied to any new Session created by this object. *

Such an interceptor can either be set at the SessionFactory level, - * i.e. on SessionFactoryBuilder/LocalSessionFactoryBean, or at the Session - * level, i.e. on HibernateTemplate, HibernateInterceptor, and - * HibernateTransactionManager. It's preferable to set it on - * SessionFactoryBuilder or HibernateTransactionManager to avoid repeated - * configuration and guarantee consistent behavior in transactions. + * i.e. on LocalSessionFactoryBean, or at the Session level, i.e. on + * HibernateTemplate, HibernateInterceptor, and HibernateTransactionManager. + * It's preferable to set it on LocalSessionFactoryBean or HibernateTransactionManager + * to avoid repeated configuration and guarantee consistent behavior in transactions. * @see #setEntityInterceptorBeanName - * @see SessionFactoryBuilder#setEntityInterceptor + * @see LocalSessionFactoryBean#setEntityInterceptor * @see HibernateTransactionManager#setEntityInterceptor */ public void setEntityInterceptor(Interceptor entityInterceptor) { @@ -209,7 +208,7 @@ public abstract class HibernateAccessor implements InitializingBean, BeanFactory if (this.beanFactory == null) { throw new IllegalStateException("Cannot get entity interceptor via bean name if no bean factory set"); } - return this.beanFactory.getBean((String) this.entityInterceptor, Interceptor.class); + return (Interceptor) this.beanFactory.getBean((String) this.entityInterceptor, Interceptor.class); } return (Interceptor) this.entityInterceptor; } @@ -273,7 +272,7 @@ public abstract class HibernateAccessor implements InitializingBean, BeanFactory * Sessions (for example, within a transaction). * @see #enableFilters(org.hibernate.Session) * @see org.hibernate.Session#enableFilter(String) - * @see SessionFactoryBuilder#setFilterDefinitions + * @see LocalSessionFactoryBean#setFilterDefinitions */ public void setFilterName(String filter) { this.filterNames = new String[] {filter}; @@ -288,7 +287,7 @@ public abstract class HibernateAccessor implements InitializingBean, BeanFactory * Sessions (for example, within a transaction). * @see #enableFilters(org.hibernate.Session) * @see org.hibernate.Session#enableFilter(String) - * @see SessionFactoryBuilder#setFilterDefinitions + * @see LocalSessionFactoryBean#setFilterDefinitions */ public void setFilterNames(String[] filterNames) { this.filterNames = filterNames; diff --git a/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/HibernateConfigurationCallback.java b/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/HibernateConfigurationCallback.java deleted file mode 100644 index 1099d1894d..0000000000 --- a/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/HibernateConfigurationCallback.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2002-2011 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.orm.hibernate3; - -import org.hibernate.cfg.Configuration; - -/** - * Callback for use in conjunction with {@link SessionFactoryBuilderSupport#doWithConfiguration}. - * - * @author Chris Beams - * @since 3.1 - * @see SessionFactoryBuilderSupport#doWithConfiguration - * @see SessionFactoryBuilder - * @see org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBuilder - */ -public interface HibernateConfigurationCallback { - - /** - * Configure the given Hibernate {@code Configuration type}. Note that methods - * only setter methods should be called, and methods such as - * {@link Configuration#buildSessionFactory()} should be avoided. - * @throws Exception to propagate any exception thrown by - * {@code Configuration} methods - */ - void configure(C configuration) throws Exception; - -} diff --git a/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/HibernateTemplate.java b/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/HibernateTemplate.java index d8d0a54204..72962e4087 100644 --- a/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/HibernateTemplate.java +++ b/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/HibernateTemplate.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2011 the original author or authors. + * Copyright 2002-2009 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -40,6 +40,7 @@ import org.hibernate.criterion.DetachedCriteria; import org.hibernate.criterion.Example; import org.hibernate.engine.SessionImplementor; import org.hibernate.event.EventSource; + import org.springframework.dao.DataAccessException; import org.springframework.dao.DataAccessResourceFailureException; import org.springframework.dao.InvalidDataAccessApiUsageException; @@ -76,10 +77,10 @@ import org.springframework.util.Assert; * management, not participating in a custom Hibernate CurrentSessionContext * unless you explicitly switch {@link #setAllowCreate "allowCreate"} to "false". * - *

Using a {@link SessionFactoryBuilder} is the preferred way of obtaining a - * reference to a specific Hibernate SessionFactory, at least in a non-EJB - * environment. The Spring application context will manage its lifecycle, - * initializing and shutting down the factory as part of the application. + *

{@link LocalSessionFactoryBean} is the preferred way of obtaining a reference + * to a specific Hibernate SessionFactory, at least in a non-EJB environment. + * The Spring application context will manage its lifecycle, initializing and + * shutting down the factory as part of the application. * *

Note that operations that return an Iterator (i.e. iterate) * are supposed to be used within Spring-driven or JTA-driven transactions @@ -98,7 +99,7 @@ import org.springframework.util.Assert; * @see #setSessionFactory * @see HibernateCallback * @see org.hibernate.Session - * @see SessionFactoryBuilder + * @see LocalSessionFactoryBean * @see HibernateTransactionManager * @see org.springframework.transaction.jta.JtaTransactionManager * @see org.springframework.orm.hibernate3.support.OpenSessionInViewFilter diff --git a/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/HibernateTransactionManager.java b/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/HibernateTransactionManager.java index d0910264d9..ae5f3853b3 100644 --- a/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/HibernateTransactionManager.java +++ b/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/HibernateTransactionManager.java @@ -80,9 +80,8 @@ import org.springframework.transaction.support.TransactionSynchronizationManager * this instance needs to be aware of the DataSource ({@link #setDataSource}). * The given DataSource should obviously match the one used by the given * SessionFactory. To achieve this, configure both to the same JNDI DataSource, - * or preferably create the SessionFactory with {@link SessionFactoryBuilder} / - * {@link LocalSessionFactoryBean} and a local DataSource (which will be - * autodetected by this transaction manager). + * or preferably create the SessionFactory with {@link LocalSessionFactoryBean} and + * a local DataSource (which will be autodetected by this transaction manager). * *

JTA (usually through {@link org.springframework.transaction.jta.JtaTransactionManager}) * is necessary for accessing multiple transactional resources within the same @@ -117,7 +116,6 @@ import org.springframework.transaction.support.TransactionSynchronizationManager * @since 1.2 * @see #setSessionFactory * @see #setDataSource - * @see SessionFactoryBuilder * @see LocalSessionFactoryBean * @see SessionFactoryUtils#getSession * @see SessionFactoryUtils#applyTransactionTimeout @@ -131,7 +129,6 @@ import org.springframework.transaction.support.TransactionSynchronizationManager * @see org.springframework.jdbc.datasource.DataSourceTransactionManager * @see org.springframework.transaction.jta.JtaTransactionManager */ -@SuppressWarnings("serial") public class HibernateTransactionManager extends AbstractPlatformTransactionManager implements ResourceTransactionManager, BeanFactoryAware, InitializingBean { @@ -197,7 +194,7 @@ public class HibernateTransactionManager extends AbstractPlatformTransactionMana * The DataSource should match the one used by the Hibernate SessionFactory: * for example, you could specify the same JNDI DataSource for both. *

If the SessionFactory was configured with LocalDataSourceConnectionProvider, - * i.e. by Spring's SessionFactoryBuilder with a specified "dataSource", + * i.e. by Spring's LocalSessionFactoryBean with a specified "dataSource", * the DataSource will be auto-detected: You can still explictly specify the * DataSource, but you don't need to in this case. *

A transactional JDBC Connection for this DataSource will be provided to @@ -211,7 +208,7 @@ public class HibernateTransactionManager extends AbstractPlatformTransactionMana * unwrapped to extract its target DataSource. * @see #setAutodetectDataSource * @see LocalDataSourceConnectionProvider - * @see SessionFactoryBuilder#setDataSource + * @see LocalSessionFactoryBean#setDataSource * @see org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy * @see org.springframework.jdbc.datasource.DataSourceUtils * @see org.springframework.jdbc.core.JdbcTemplate @@ -237,11 +234,11 @@ public class HibernateTransactionManager extends AbstractPlatformTransactionMana /** * Set whether to autodetect a JDBC DataSource used by the Hibernate SessionFactory, - * if set via SessionFactoryBuilder's setDataSource. Default is "true". + * if set via LocalSessionFactoryBean's setDataSource. Default is "true". *

Can be turned off to deliberately ignore an available DataSource, in order * to not expose Hibernate transactions as JDBC transactions for that DataSource. * @see #setDataSource - * @see SessionFactoryBuilder#setDataSource + * @see LocalSessionFactoryBean#setDataSource */ public void setAutodetectDataSource(boolean autodetectDataSource) { this.autodetectDataSource = autodetectDataSource; @@ -332,11 +329,11 @@ public class HibernateTransactionManager extends AbstractPlatformTransactionMana * property values before writing to and reading from the database. * Will get applied to any new Session created by this transaction manager. *

Such an interceptor can either be set at the SessionFactory level, - * i.e. on SessionFactoryBuilder, or at the Session level, i.e. on + * i.e. on LocalSessionFactoryBean, or at the Session level, i.e. on * HibernateTemplate, HibernateInterceptor, and HibernateTransactionManager. - * It's preferable to set it on SessionFactoryBuilder or HibernateTransactionManager + * It's preferable to set it on LocalSessionFactoryBean or HibernateTransactionManager * to avoid repeated configuration and guarantee consistent behavior in transactions. - * @see SessionFactoryBuilder#setEntityInterceptor + * @see LocalSessionFactoryBean#setEntityInterceptor * @see HibernateTemplate#setEntityInterceptor * @see HibernateInterceptor#setEntityInterceptor */ @@ -507,7 +504,6 @@ public class HibernateTransactionManager extends AbstractPlatformTransactionMana logger.debug( "Preparing JDBC Connection of Hibernate Session [" + SessionFactoryUtils.toString(session) + "]"); } - @SuppressWarnings("deprecation") Connection con = session.connection(); Integer previousIsolationLevel = DataSourceUtils.prepareConnectionForTransaction(con, definition); txObject.setPreviousIsolationLevel(previousIsolationLevel); @@ -520,7 +516,7 @@ public class HibernateTransactionManager extends AbstractPlatformTransactionMana "HibernateTransactionManager is not allowed to support custom isolation levels: " + "make sure that its 'prepareConnection' flag is on (the default) and that the " + "Hibernate connection release mode is set to 'on_close' (SpringTransactionFactory's default). " + - "Make sure that your SessionFactoryBuilder actually uses SpringTransactionFactory: Your " + + "Make sure that your LocalSessionFactoryBean actually uses SpringTransactionFactory: Your " + "Hibernate properties should *not* include a 'hibernate.transaction.factory_class' property!"); } if (logger.isDebugEnabled()) { @@ -564,7 +560,6 @@ public class HibernateTransactionManager extends AbstractPlatformTransactionMana // Register the Hibernate Session's JDBC Connection for the DataSource, if set. if (getDataSource() != null) { - @SuppressWarnings("deprecation") Connection con = session.connection(); ConnectionHolder conHolder = new ConnectionHolder(con); if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) { @@ -726,7 +721,6 @@ public class HibernateTransactionManager extends AbstractPlatformTransactionMana // the isolation level and/or read-only flag of the JDBC Connection here. // Else, we need to rely on the connection pool to perform proper cleanup. try { - @SuppressWarnings("deprecation") Connection con = session.connection(); DataSourceUtils.resetConnectionAfterTransaction(con, txObject.getPreviousIsolationLevel()); } diff --git a/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/LocalCacheProviderProxy.java b/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/LocalCacheProviderProxy.java index bc9c6a906c..e240800e0f 100644 --- a/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/LocalCacheProviderProxy.java +++ b/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/LocalCacheProviderProxy.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2011 the original author or authors. + * Copyright 2002-2008 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -28,23 +28,16 @@ import org.hibernate.cache.CacheProvider; * "cacheProvider" property. * * @author Juergen Hoeller - * @author Chris Beams * @since 2.5.1 * @see LocalSessionFactoryBean#setCacheProvider - * @see LocalRegionFactoryProxy - * @deprecated as of Spring 3.1 to reflect the deprecation of the - * CacheProvider SPI in Hibernate 3.3. Favor the new - * {@link org.hibernate.cache.RegionFactory} SPI and Spring's - * {@link LocalRegionFactoryProxy} support. */ -@Deprecated public class LocalCacheProviderProxy implements CacheProvider { private final CacheProvider cacheProvider; public LocalCacheProviderProxy() { - CacheProvider cp = SessionFactoryBeanDelegate.getConfigTimeCacheProvider(); + CacheProvider cp = LocalSessionFactoryBean.getConfigTimeCacheProvider(); // absolutely needs thread-bound CacheProvider to initialize if (cp == null) { throw new IllegalStateException("No Hibernate CacheProvider found - " + diff --git a/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/LocalDataSourceConnectionProvider.java b/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/LocalDataSourceConnectionProvider.java index 0af65601b1..29a711b333 100644 --- a/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/LocalDataSourceConnectionProvider.java +++ b/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/LocalDataSourceConnectionProvider.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2011 the original author or authors. + * Copyright 2002-2009 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -19,7 +19,6 @@ package org.springframework.orm.hibernate3; import java.sql.Connection; import java.sql.SQLException; import java.util.Properties; - import javax.sql.DataSource; import org.hibernate.HibernateException; @@ -29,12 +28,12 @@ import org.hibernate.util.JDBCExceptionReporter; /** * Hibernate connection provider for local DataSource instances * in an application context. This provider will be used if - * SessionFactoryBuilder's "dataSource" property is set + * LocalSessionFactoryBean's "dataSource" property is set * without a Hibernate TransactionManagerLookup. * * @author Juergen Hoeller * @since 1.2 - * @see SessionFactoryBuilder#setDataSource + * @see LocalSessionFactoryBean#setDataSource */ public class LocalDataSourceConnectionProvider implements ConnectionProvider { @@ -44,11 +43,11 @@ public class LocalDataSourceConnectionProvider implements ConnectionProvider { public void configure(Properties props) throws HibernateException { - this.dataSource = SessionFactoryBuilderSupport.getConfigTimeDataSource(); + this.dataSource = LocalSessionFactoryBean.getConfigTimeDataSource(); // absolutely needs thread-bound DataSource to initialize if (this.dataSource == null) { throw new HibernateException("No local DataSource found for configuration - " + - "'dataSource' property must be set on SessionFactoryBuilder"); + "'dataSource' property must be set on LocalSessionFactoryBean"); } this.dataSourceToUse = getDataSourceToUse(this.dataSource); } @@ -57,10 +56,10 @@ public class LocalDataSourceConnectionProvider implements ConnectionProvider { * Return the DataSource to use for retrieving Connections. *

This implementation returns the passed-in DataSource as-is. * @param originalDataSource the DataSource as configured by the user - * on SessionFactoryBuilder + * on LocalSessionFactoryBean * @return the DataSource to actually retrieve Connections from * (potentially wrapped) - * @see SessionFactoryBuilder#setDataSource + * @see LocalSessionFactoryBean#setDataSource */ protected DataSource getDataSourceToUse(DataSource originalDataSource) { return originalDataSource; diff --git a/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/LocalJtaDataSourceConnectionProvider.java b/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/LocalJtaDataSourceConnectionProvider.java index c4f204d0aa..b2da29349e 100644 --- a/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/LocalJtaDataSourceConnectionProvider.java +++ b/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/LocalJtaDataSourceConnectionProvider.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2011 the original author or authors. + * Copyright 2002-2007 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,7 +18,7 @@ package org.springframework.orm.hibernate3; /** * Subclass of LocalDataSourceConnectionProvider that will be used - * if SessionFactoryBean's "dataSource" property is set + * if LocalSessionFactoryBean's "dataSource" property is set * in combination with a Hibernate TransactionManagerLookup. * * @author Juergen Hoeller diff --git a/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/LocalRegionFactoryProxy.java b/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/LocalRegionFactoryProxy.java index 6e3c1d5b71..d43196ce3f 100644 --- a/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/LocalRegionFactoryProxy.java +++ b/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/LocalRegionFactoryProxy.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2011 the original author or authors. + * Copyright 2002-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -33,7 +33,7 @@ import org.springframework.util.ReflectionUtils; /** * Proxy for a Hibernate RegionFactory, delegating to a Spring-managed - * RegionFactory instance, determined by SessionFactoryBuilder's + * RegionFactory instance, determined by LocalSessionFactoryBean's * "cacheRegionFactory" property. * *

Compatible with Hibernate 3.3 as well as Hibernate 3.5's version @@ -41,7 +41,7 @@ import org.springframework.util.ReflectionUtils; * * @author Juergen Hoeller * @since 3.0 - * @see SessionFactoryBuilder#setCacheRegionFactory + * @see LocalSessionFactoryBean#setCacheRegionFactory */ public class LocalRegionFactoryProxy implements RegionFactory { @@ -52,11 +52,11 @@ public class LocalRegionFactoryProxy implements RegionFactory { * Standard constructor. */ public LocalRegionFactoryProxy() { - RegionFactory rf = (RegionFactory) SessionFactoryBuilderSupport.getConfigTimeRegionFactory(); + RegionFactory rf = (RegionFactory) LocalSessionFactoryBean.getConfigTimeRegionFactory(); // absolutely needs thread-bound RegionFactory to initialize if (rf == null) { throw new IllegalStateException("No Hibernate RegionFactory found - " + - "'cacheRegionFactory' property must be set on SessionFactoryBuilder"); + "'cacheRegionFactory' property must be set on LocalSessionFactoryBean"); } this.regionFactory = rf; } diff --git a/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/LocalSessionFactoryBean.java b/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/LocalSessionFactoryBean.java index 40786470ab..0cb0d7335f 100644 --- a/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/LocalSessionFactoryBean.java +++ b/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/LocalSessionFactoryBean.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2011 the original author or authors. + * Copyright 2002-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,125 +16,1109 @@ package org.springframework.orm.hibernate3; -import org.hibernate.HibernateException; +import java.io.File; +import java.lang.reflect.Array; +import java.lang.reflect.Method; +import java.sql.Connection; +import java.sql.SQLException; +import java.sql.Statement; +import java.util.Collection; +import java.util.Enumeration; +import java.util.Map; +import java.util.Properties; +import javax.sql.DataSource; +import javax.transaction.TransactionManager; +import org.hibernate.HibernateException; +import org.hibernate.Interceptor; +import org.hibernate.Session; import org.hibernate.SessionFactory; +import org.hibernate.cache.CacheProvider; +import org.hibernate.cfg.Configuration; +import org.hibernate.cfg.Environment; +import org.hibernate.cfg.NamingStrategy; +import org.hibernate.dialect.Dialect; +import org.hibernate.engine.FilterDefinition; +import org.hibernate.event.EventListeners; +import org.hibernate.tool.hbm2ddl.DatabaseMetadata; +import org.hibernate.transaction.JTATransactionFactory; + +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.BeanClassLoaderAware; +import org.springframework.core.io.ClassPathResource; +import org.springframework.core.io.Resource; import org.springframework.dao.DataAccessException; -import org.springframework.jdbc.support.SQLExceptionTranslator; +import org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy; +import org.springframework.jdbc.support.JdbcUtils; +import org.springframework.jdbc.support.lob.LobHandler; +import org.springframework.util.ClassUtils; +import org.springframework.util.ReflectionUtils; +import org.springframework.util.StringUtils; /** - * Subclass of {@link SessionFactoryBuilder} adhering to Spring's - * {@link org.springframework.beans.factory.FactoryBean FactoryBean} contract, - * making it suitable for use in XML configuration. + * {@link org.springframework.beans.factory.FactoryBean} that creates a + * Hibernate {@link org.hibernate.SessionFactory}. This is the usual way to + * set up a shared Hibernate SessionFactory in a Spring application context; + * the SessionFactory can then be passed to Hibernate-based DAOs via + * dependency injection. * - *

A typical {@code LocalSessionFactoryBean} bean definition: + *

Configuration settings can either be read from a Hibernate XML file, + * specified as "configLocation", or completely via this class. A typical + * local configuration consists of one or more "mappingResources", various + * "hibernateProperties" (not strictly necessary), and a "dataSource" that the + * SessionFactory should use. The latter can also be specified via Hibernate + * properties, but "dataSource" supports any Spring-configured DataSource, + * instead of relying on Hibernate's own connection providers. * - *

- * {@code
- * 
- *   
- *   
- * }
+ *

This SessionFactory handling strategy is appropriate for most types of + * applications, from Hibernate-only single database apps to ones that need + * distributed transactions. Either {@link HibernateTransactionManager} or + * {@link org.springframework.transaction.jta.JtaTransactionManager} can be + * used for transaction demarcation, with the latter only necessary for + * transactions which span multiple databases. * - *

Implements the - * {@link org.springframework.dao.support.PersistenceExceptionTranslator - * PersistenceExceptionTranslator} interface, as autodetected by Spring's {@link - * org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor - * PersistenceExceptionTranslationPostProcessor}, for AOP-based translation of - * native Hibernate exceptions to Spring's {@link DataAccessException} hierarchy. - * Hence, the presence of an {@code LocalSessionFactoryBean} automatically - * enables a {@code PersistenceExceptionTranslationPostProcessor} to translate - * Hibernate exceptions. + *

This factory bean will by default expose a transaction-aware SessionFactory + * proxy, letting data access code work with the plain Hibernate SessionFactory + * and its getCurrentSession() method, while still being able to + * participate in current Spring-managed transactions: with any transaction + * management strategy, either local or JTA / EJB CMT, and any transaction + * synchronization mechanism, either Spring or JTA. Furthermore, + * getCurrentSession() will also seamlessly work with + * a request-scoped Session managed by + * {@link org.springframework.orm.hibernate3.support.OpenSessionInViewFilter} / + * {@link org.springframework.orm.hibernate3.support.OpenSessionInViewInterceptor}. + * + *

Requires Hibernate 3.2 or later; tested with 3.3, 3.5 and 3.6. + * Note that this factory will use "on_close" as default Hibernate connection + * release mode, unless in the case of a "jtaTransactionManager" specified, + * for the reason that this is appropriate for most Spring-based applications + * (in particular when using Spring's HibernateTransactionManager). * * @author Juergen Hoeller - * @author Chris Beams * @since 1.2 - * @see SessionFactoryBuilderSupport - * @see SessionFactoryBeanOperations - * @see org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean + * @see HibernateTemplate#setSessionFactory + * @see HibernateTransactionManager#setSessionFactory + * @see #setExposeTransactionAwareSessionFactory + * @see #setJtaTransactionManager + * @see org.hibernate.SessionFactory#getCurrentSession() + * @see HibernateTransactionManager */ -public class LocalSessionFactoryBean extends SessionFactoryBuilder implements SessionFactoryBeanOperations { +public class LocalSessionFactoryBean extends AbstractSessionFactoryBean implements BeanClassLoaderAware { - private final SessionFactoryBeanDelegate delegate = new SessionFactoryBeanDelegate(this); + private static final ThreadLocal configTimeDataSourceHolder = + new ThreadLocal(); + private static final ThreadLocal configTimeTransactionManagerHolder = + new ThreadLocal(); + + private static final ThreadLocal configTimeRegionFactoryHolder = + new ThreadLocal(); + + private static final ThreadLocal configTimeCacheProviderHolder = + new ThreadLocal(); + + private static final ThreadLocal configTimeLobHandlerHolder = + new ThreadLocal(); + + /** + * Return the DataSource for the currently configured Hibernate SessionFactory, + * to be used by LocalDataSourceConnectionProvoder. + *

This instance will be set before initialization of the corresponding + * SessionFactory, and reset immediately afterwards. It is thus only available + * during configuration. + * @see #setDataSource + * @see LocalDataSourceConnectionProvider + */ + public static DataSource getConfigTimeDataSource() { + return configTimeDataSourceHolder.get(); + } + + /** + * Return the JTA TransactionManager for the currently configured Hibernate + * SessionFactory, to be used by LocalTransactionManagerLookup. + *

This instance will be set before initialization of the corresponding + * SessionFactory, and reset immediately afterwards. It is thus only available + * during configuration. + * @see #setJtaTransactionManager + * @see LocalTransactionManagerLookup + */ + public static TransactionManager getConfigTimeTransactionManager() { + return configTimeTransactionManagerHolder.get(); + } + + /** + * Return the RegionFactory for the currently configured Hibernate SessionFactory, + * to be used by LocalRegionFactoryProxy. + *

This instance will be set before initialization of the corresponding + * SessionFactory, and reset immediately afterwards. It is thus only available + * during configuration. + * @see #setCacheRegionFactory + */ + static Object getConfigTimeRegionFactory() { + return configTimeRegionFactoryHolder.get(); + } + + /** + * Return the CacheProvider for the currently configured Hibernate SessionFactory, + * to be used by LocalCacheProviderProxy. + *

This instance will be set before initialization of the corresponding + * SessionFactory, and reset immediately afterwards. It is thus only available + * during configuration. + * @see #setCacheProvider + */ + public static CacheProvider getConfigTimeCacheProvider() { + return configTimeCacheProviderHolder.get(); + } + + /** + * Return the LobHandler for the currently configured Hibernate SessionFactory, + * to be used by UserType implementations like ClobStringType. + *

This instance will be set before initialization of the corresponding + * SessionFactory, and reset immediately afterwards. It is thus only available + * during configuration. + * @see #setLobHandler + * @see org.springframework.orm.hibernate3.support.ClobStringType + * @see org.springframework.orm.hibernate3.support.BlobByteArrayType + * @see org.springframework.orm.hibernate3.support.BlobSerializableType + */ + public static LobHandler getConfigTimeLobHandler() { + return configTimeLobHandlerHolder.get(); + } + + + private Class configurationClass = Configuration.class; + + private Resource[] configLocations; + + private String[] mappingResources; + + private Resource[] mappingLocations; + + private Resource[] cacheableMappingLocations; + + private Resource[] mappingJarLocations; + + private Resource[] mappingDirectoryLocations; + + private Properties hibernateProperties; + + private TransactionManager jtaTransactionManager; + + private Object cacheRegionFactory; + + private CacheProvider cacheProvider; + + private LobHandler lobHandler; + + private Interceptor entityInterceptor; + + private NamingStrategy namingStrategy; + + private TypeDefinitionBean[] typeDefinitions; + + private FilterDefinition[] filterDefinitions; + + private Properties entityCacheStrategies; + + private Properties collectionCacheStrategies; + + private Map eventListeners; + + private boolean schemaUpdate = false; + + private ClassLoader beanClassLoader = ClassUtils.getDefaultClassLoader(); + + private Configuration configuration; + + + /** + * Specify the Hibernate Configuration class to use. + * Default is "org.hibernate.cfg.Configuration"; any subclass of + * this default Hibernate Configuration class can be specified. + *

Can be set to "org.hibernate.cfg.AnnotationConfiguration" for + * using Hibernate3 annotation support (initially only available as + * alpha download separate from the main Hibernate3 distribution). + *

Annotated packages and annotated classes can be specified via the + * corresponding tags in "hibernate.cfg.xml" then, so this will usually + * be combined with a "configLocation" property that points at such a + * standard Hibernate configuration file. + * @see #setConfigLocation + * @see org.hibernate.cfg.Configuration + * @see org.hibernate.cfg.AnnotationConfiguration + */ + @SuppressWarnings("unchecked") + public void setConfigurationClass(Class configurationClass) { + if (configurationClass == null || !Configuration.class.isAssignableFrom(configurationClass)) { + throw new IllegalArgumentException( + "'configurationClass' must be assignable to [org.hibernate.cfg.Configuration]"); + } + this.configurationClass = (Class) configurationClass; + } + + /** + * Set the location of a single Hibernate XML config file, for example as + * classpath resource "classpath:hibernate.cfg.xml". + *

Note: Can be omitted when all necessary properties and mapping + * resources are specified locally via this bean. + * @see org.hibernate.cfg.Configuration#configure(java.net.URL) + */ + public void setConfigLocation(Resource configLocation) { + this.configLocations = new Resource[] {configLocation}; + } + + /** + * Set the locations of multiple Hibernate XML config files, for example as + * classpath resources "classpath:hibernate.cfg.xml,classpath:extension.cfg.xml". + *

Note: Can be omitted when all necessary properties and mapping + * resources are specified locally via this bean. + * @see org.hibernate.cfg.Configuration#configure(java.net.URL) + */ + public void setConfigLocations(Resource[] configLocations) { + this.configLocations = configLocations; + } + + /** + * Set Hibernate mapping resources to be found in the class path, + * like "example.hbm.xml" or "mypackage/example.hbm.xml". + * Analogous to mapping entries in a Hibernate XML config file. + * Alternative to the more generic setMappingLocations method. + *

Can be used to add to mappings from a Hibernate XML config file, + * or to specify all mappings locally. + * @see #setMappingLocations + * @see org.hibernate.cfg.Configuration#addResource + */ + public void setMappingResources(String[] mappingResources) { + this.mappingResources = mappingResources; + } + + /** + * Set locations of Hibernate mapping files, for example as classpath + * resource "classpath:example.hbm.xml". Supports any resource location + * via Spring's resource abstraction, for example relative paths like + * "WEB-INF/mappings/example.hbm.xml" when running in an application context. + *

Can be used to add to mappings from a Hibernate XML config file, + * or to specify all mappings locally. + * @see org.hibernate.cfg.Configuration#addInputStream + */ + public void setMappingLocations(Resource[] mappingLocations) { + this.mappingLocations = mappingLocations; + } + + /** + * Set locations of cacheable Hibernate mapping files, for example as web app + * resource "/WEB-INF/mapping/example.hbm.xml". Supports any resource location + * via Spring's resource abstraction, as long as the resource can be resolved + * in the file system. + *

Can be used to add to mappings from a Hibernate XML config file, + * or to specify all mappings locally. + * @see org.hibernate.cfg.Configuration#addCacheableFile(java.io.File) + */ + public void setCacheableMappingLocations(Resource[] cacheableMappingLocations) { + this.cacheableMappingLocations = cacheableMappingLocations; + } + + /** + * Set locations of jar files that contain Hibernate mapping resources, + * like "WEB-INF/lib/example.hbm.jar". + *

Can be used to add to mappings from a Hibernate XML config file, + * or to specify all mappings locally. + * @see org.hibernate.cfg.Configuration#addJar(java.io.File) + */ + public void setMappingJarLocations(Resource[] mappingJarLocations) { + this.mappingJarLocations = mappingJarLocations; + } + + /** + * Set locations of directories that contain Hibernate mapping resources, + * like "WEB-INF/mappings". + *

Can be used to add to mappings from a Hibernate XML config file, + * or to specify all mappings locally. + * @see org.hibernate.cfg.Configuration#addDirectory(java.io.File) + */ + public void setMappingDirectoryLocations(Resource[] mappingDirectoryLocations) { + this.mappingDirectoryLocations = mappingDirectoryLocations; + } + + /** + * Set Hibernate properties, such as "hibernate.dialect". + *

Can be used to override values in a Hibernate XML config file, + * or to specify all necessary properties locally. + *

Note: Do not specify a transaction provider here when using + * Spring-driven transactions. It is also advisable to omit connection + * provider settings and use a Spring-set DataSource instead. + * @see #setDataSource + */ + public void setHibernateProperties(Properties hibernateProperties) { + this.hibernateProperties = hibernateProperties; + } + + /** + * Return the Hibernate properties, if any. Mainly available for + * configuration through property paths that specify individual keys. + */ + public Properties getHibernateProperties() { + if (this.hibernateProperties == null) { + this.hibernateProperties = new Properties(); + } + return this.hibernateProperties; + } + + /** + * Set the JTA TransactionManager to be used for Hibernate's + * TransactionManagerLookup. Allows for using a Spring-managed + * JTA TransactionManager for Hibernate's cache synchronization. + *

Note: If this is set, the Hibernate settings should not define a + * transaction manager lookup to avoid meaningless double configuration. + * @see LocalTransactionManagerLookup + */ + public void setJtaTransactionManager(TransactionManager jtaTransactionManager) { + this.jtaTransactionManager = jtaTransactionManager; + } + + /** + * Set the Hibernate RegionFactory to use for the SessionFactory. + * Allows for using a Spring-managed RegionFactory instance. + *

As of Hibernate 3.3, this is the preferred mechanism for configuring + * caches, superseding the {@link #setCacheProvider CacheProvider SPI}. + * For Hibernate 3.2 compatibility purposes, the accepted reference is of type + * Object: the actual type is org.hibernate.cache.RegionFactory. + *

Note: If this is set, the Hibernate settings should not define a + * cache provider to avoid meaningless double configuration. + * @see org.hibernate.cache.RegionFactory + */ + public void setCacheRegionFactory(Object cacheRegionFactory) { + this.cacheRegionFactory = cacheRegionFactory; + } + + /** + * Set the Hibernate CacheProvider to use for the SessionFactory. + * Allows for using a Spring-managed CacheProvider instance. + *

Note: If this is set, the Hibernate settings should not define a + * cache provider to avoid meaningless double configuration. + * @deprecated as of Spring 3.0, following Hibernate 3.3's deprecation + * of the CacheProvider SPI + * @see #setCacheRegionFactory + */ @Deprecated - public void setCacheProvider(org.hibernate.cache.CacheProvider cacheProvider) { - delegate.setCacheProvider(cacheProvider); + public void setCacheProvider(CacheProvider cacheProvider) { + this.cacheProvider = cacheProvider; } + /** + * Set the LobHandler to be used by the SessionFactory. + * Will be exposed at config time for UserType implementations. + * @see #getConfigTimeLobHandler + * @see org.hibernate.usertype.UserType + * @see org.springframework.orm.hibernate3.support.ClobStringType + * @see org.springframework.orm.hibernate3.support.BlobByteArrayType + * @see org.springframework.orm.hibernate3.support.BlobSerializableType + */ + public void setLobHandler(LobHandler lobHandler) { + this.lobHandler = lobHandler; + } + + /** + * Set a Hibernate entity interceptor that allows to inspect and change + * property values before writing to and reading from the database. + * Will get applied to any new Session created by this factory. + *

Such an interceptor can either be set at the SessionFactory level, i.e. on + * LocalSessionFactoryBean, or at the Session level, i.e. on HibernateTemplate, + * HibernateInterceptor, and HibernateTransactionManager. It's preferable to set + * it on LocalSessionFactoryBean or HibernateTransactionManager to avoid repeated + * configuration and guarantee consistent behavior in transactions. + * @see HibernateTemplate#setEntityInterceptor + * @see HibernateInterceptor#setEntityInterceptor + * @see HibernateTransactionManager#setEntityInterceptor + * @see org.hibernate.cfg.Configuration#setInterceptor + */ + public void setEntityInterceptor(Interceptor entityInterceptor) { + this.entityInterceptor = entityInterceptor; + } + + /** + * Set a Hibernate NamingStrategy for the SessionFactory, determining the + * physical column and table names given the info in the mapping document. + * @see org.hibernate.cfg.Configuration#setNamingStrategy + */ + public void setNamingStrategy(NamingStrategy namingStrategy) { + this.namingStrategy = namingStrategy; + } + + /** + * Specify the Hibernate type definitions to register with the SessionFactory, + * as Spring TypeDefinitionBean instances. This is an alternative to specifying + * <<typedef> elements in Hibernate mapping files. + *

Unfortunately, Hibernate itself does not define a complete object that + * represents a type definition, hence the need for Spring's TypeDefinitionBean. + * @see TypeDefinitionBean + * @see org.hibernate.cfg.Mappings#addTypeDef(String, String, java.util.Properties) + */ + public void setTypeDefinitions(TypeDefinitionBean[] typeDefinitions) { + this.typeDefinitions = typeDefinitions; + } + + /** + * Specify the Hibernate FilterDefinitions to register with the SessionFactory. + * This is an alternative to specifying <<filter-def> elements in + * Hibernate mapping files. + *

Typically, the passed-in FilterDefinition objects will have been defined + * as Spring FilterDefinitionFactoryBeans, probably as inner beans within the + * LocalSessionFactoryBean definition. + * @see FilterDefinitionFactoryBean + * @see org.hibernate.cfg.Configuration#addFilterDefinition + */ + public void setFilterDefinitions(FilterDefinition[] filterDefinitions) { + this.filterDefinitions = filterDefinitions; + } + + /** + * Specify the cache strategies for entities (persistent classes or named entities). + * This configuration setting corresponds to the <class-cache> entry + * in the "hibernate.cfg.xml" configuration format. + *

For example: + *

+	 * <property name="entityCacheStrategies">
+	 *   <props>
+	 *     <prop key="com.mycompany.Customer">read-write</prop>
+	 *     <prop key="com.mycompany.Product">read-only,myRegion</prop>
+	 *   </props>
+	 * </property>
+ * @param entityCacheStrategies properties that define entity cache strategies, + * with class names as keys and cache concurrency strategies as values + * @see org.hibernate.cfg.Configuration#setCacheConcurrencyStrategy(String, String) + */ + public void setEntityCacheStrategies(Properties entityCacheStrategies) { + this.entityCacheStrategies = entityCacheStrategies; + } + + /** + * Specify the cache strategies for persistent collections (with specific roles). + * This configuration setting corresponds to the <collection-cache> entry + * in the "hibernate.cfg.xml" configuration format. + *

For example: + *

+	 * <property name="collectionCacheStrategies">
+	 *   <props>
+	 *     <prop key="com.mycompany.Order.items">read-write</prop>
+	 *     <prop key="com.mycompany.Product.categories">read-only,myRegion</prop>
+	 *   </props>
+	 * </property>
+ * @param collectionCacheStrategies properties that define collection cache strategies, + * with collection roles as keys and cache concurrency strategies as values + * @see org.hibernate.cfg.Configuration#setCollectionCacheConcurrencyStrategy(String, String) + */ + public void setCollectionCacheStrategies(Properties collectionCacheStrategies) { + this.collectionCacheStrategies = collectionCacheStrategies; + } + + /** + * Specify the Hibernate event listeners to register, with listener types + * as keys and listener objects as values. Instead of a single listener object, + * you can also pass in a list or set of listeners objects as value. + *

See the Hibernate documentation for further details on listener types + * and associated listener interfaces. + * @param eventListeners Map with listener type Strings as keys and + * listener objects as values + * @see org.hibernate.cfg.Configuration#setListener(String, Object) + */ + public void setEventListeners(Map eventListeners) { + this.eventListeners = eventListeners; + } + + /** + * Set whether to execute a schema update after SessionFactory initialization. + *

For details on how to make schema update scripts work, see the Hibernate + * documentation, as this class leverages the same schema update script support + * in org.hibernate.cfg.Configuration as Hibernate's own SchemaUpdate tool. + * @see org.hibernate.cfg.Configuration#generateSchemaUpdateScript + * @see org.hibernate.tool.hbm2ddl.SchemaUpdate + */ + public void setSchemaUpdate(boolean schemaUpdate) { + this.schemaUpdate = schemaUpdate; + } + + public void setBeanClassLoader(ClassLoader beanClassLoader) { + this.beanClassLoader = beanClassLoader; + } + + @Override - protected final void preBuildSessionFactory() { - delegate.preBuildSessionFactory(); + @SuppressWarnings("unchecked") + protected SessionFactory buildSessionFactory() throws Exception { + // Create Configuration instance. + Configuration config = newConfiguration(); + + DataSource dataSource = getDataSource(); + if (dataSource != null) { + // Make given DataSource available for SessionFactory configuration. + configTimeDataSourceHolder.set(dataSource); + } + if (this.jtaTransactionManager != null) { + // Make Spring-provided JTA TransactionManager available. + configTimeTransactionManagerHolder.set(this.jtaTransactionManager); + } + if (this.cacheRegionFactory != null) { + // Make Spring-provided Hibernate RegionFactory available. + configTimeRegionFactoryHolder.set(this.cacheRegionFactory); + } + if (this.cacheProvider != null) { + // Make Spring-provided Hibernate CacheProvider available. + configTimeCacheProviderHolder.set(this.cacheProvider); + } + if (this.lobHandler != null) { + // Make given LobHandler available for SessionFactory configuration. + // Do early because because mapping resource might refer to custom types. + configTimeLobHandlerHolder.set(this.lobHandler); + } + + // Analogous to Hibernate EntityManager's Ejb3Configuration: + // Hibernate doesn't allow setting the bean ClassLoader explicitly, + // so we need to expose it as thread context ClassLoader accordingly. + Thread currentThread = Thread.currentThread(); + ClassLoader threadContextClassLoader = currentThread.getContextClassLoader(); + boolean overrideClassLoader = + (this.beanClassLoader != null && !this.beanClassLoader.equals(threadContextClassLoader)); + if (overrideClassLoader) { + currentThread.setContextClassLoader(this.beanClassLoader); + } + + try { + if (isExposeTransactionAwareSessionFactory()) { + // Set Hibernate 3.1+ CurrentSessionContext implementation, + // providing the Spring-managed Session as current Session. + // Can be overridden by a custom value for the corresponding Hibernate property. + config.setProperty( + Environment.CURRENT_SESSION_CONTEXT_CLASS, SpringSessionContext.class.getName()); + } + + if (this.jtaTransactionManager != null) { + // Set Spring-provided JTA TransactionManager as Hibernate property. + config.setProperty( + Environment.TRANSACTION_STRATEGY, JTATransactionFactory.class.getName()); + config.setProperty( + Environment.TRANSACTION_MANAGER_STRATEGY, LocalTransactionManagerLookup.class.getName()); + } + else { + // Makes the Hibernate Session aware of the presence of a Spring-managed transaction. + // Also sets connection release mode to ON_CLOSE by default. + config.setProperty( + Environment.TRANSACTION_STRATEGY, SpringTransactionFactory.class.getName()); + } + + if (this.entityInterceptor != null) { + // Set given entity interceptor at SessionFactory level. + config.setInterceptor(this.entityInterceptor); + } + + if (this.namingStrategy != null) { + // Pass given naming strategy to Hibernate Configuration. + config.setNamingStrategy(this.namingStrategy); + } + + if (this.typeDefinitions != null) { + // Register specified Hibernate type definitions. + // Use reflection for compatibility with both Hibernate 3.3 and 3.5: + // the returned Mappings object changed from a class to an interface. + Method createMappings = Configuration.class.getMethod("createMappings"); + Method addTypeDef = createMappings.getReturnType().getMethod( + "addTypeDef", String.class, String.class, Properties.class); + Object mappings = ReflectionUtils.invokeMethod(createMappings, config); + for (TypeDefinitionBean typeDef : this.typeDefinitions) { + ReflectionUtils.invokeMethod(addTypeDef, mappings, + typeDef.getTypeName(), typeDef.getTypeClass(), typeDef.getParameters()); + } + } + + if (this.filterDefinitions != null) { + // Register specified Hibernate FilterDefinitions. + for (FilterDefinition filterDef : this.filterDefinitions) { + config.addFilterDefinition(filterDef); + } + } + + if (this.configLocations != null) { + for (Resource resource : this.configLocations) { + // Load Hibernate configuration from given location. + config.configure(resource.getURL()); + } + } + + if (this.hibernateProperties != null) { + // Add given Hibernate properties to Configuration. + config.addProperties(this.hibernateProperties); + } + + if (dataSource != null) { + Class providerClass = LocalDataSourceConnectionProvider.class; + if (isUseTransactionAwareDataSource() || dataSource instanceof TransactionAwareDataSourceProxy) { + providerClass = TransactionAwareDataSourceConnectionProvider.class; + } + else if (config.getProperty(Environment.TRANSACTION_MANAGER_STRATEGY) != null) { + providerClass = LocalJtaDataSourceConnectionProvider.class; + } + // Set Spring-provided DataSource as Hibernate ConnectionProvider. + config.setProperty(Environment.CONNECTION_PROVIDER, providerClass.getName()); + } + + if (this.cacheRegionFactory != null) { + // Expose Spring-provided Hibernate RegionFactory. + config.setProperty(Environment.CACHE_REGION_FACTORY, + "org.springframework.orm.hibernate3.LocalRegionFactoryProxy"); + } + else if (this.cacheProvider != null) { + // Expose Spring-provided Hibernate CacheProvider. + config.setProperty(Environment.CACHE_PROVIDER, LocalCacheProviderProxy.class.getName()); + } + + if (this.mappingResources != null) { + // Register given Hibernate mapping definitions, contained in resource files. + for (String mapping : this.mappingResources) { + Resource resource = new ClassPathResource(mapping.trim(), this.beanClassLoader); + config.addInputStream(resource.getInputStream()); + } + } + + if (this.mappingLocations != null) { + // Register given Hibernate mapping definitions, contained in resource files. + for (Resource resource : this.mappingLocations) { + config.addInputStream(resource.getInputStream()); + } + } + + if (this.cacheableMappingLocations != null) { + // Register given cacheable Hibernate mapping definitions, read from the file system. + for (Resource resource : this.cacheableMappingLocations) { + config.addCacheableFile(resource.getFile()); + } + } + + if (this.mappingJarLocations != null) { + // Register given Hibernate mapping definitions, contained in jar files. + for (Resource resource : this.mappingJarLocations) { + config.addJar(resource.getFile()); + } + } + + if (this.mappingDirectoryLocations != null) { + // Register all Hibernate mapping definitions in the given directories. + for (Resource resource : this.mappingDirectoryLocations) { + File file = resource.getFile(); + if (!file.isDirectory()) { + throw new IllegalArgumentException( + "Mapping directory location [" + resource + "] does not denote a directory"); + } + config.addDirectory(file); + } + } + + // Tell Hibernate to eagerly compile the mappings that we registered, + // for availability of the mapping information in further processing. + postProcessMappings(config); + config.buildMappings(); + + if (this.entityCacheStrategies != null) { + // Register cache strategies for mapped entities. + for (Enumeration classNames = this.entityCacheStrategies.propertyNames(); classNames.hasMoreElements();) { + String className = (String) classNames.nextElement(); + String[] strategyAndRegion = + StringUtils.commaDelimitedListToStringArray(this.entityCacheStrategies.getProperty(className)); + if (strategyAndRegion.length > 1) { + // method signature declares return type as Configuration on Hibernate 3.6 + // but as void on Hibernate 3.3 and 3.5 + Method setCacheConcurrencyStrategy = Configuration.class.getMethod( + "setCacheConcurrencyStrategy", String.class, String.class, String.class); + ReflectionUtils.invokeMethod(setCacheConcurrencyStrategy, config, + className, strategyAndRegion[0], strategyAndRegion[1]); + } + else if (strategyAndRegion.length > 0) { + config.setCacheConcurrencyStrategy(className, strategyAndRegion[0]); + } + } + } + + if (this.collectionCacheStrategies != null) { + // Register cache strategies for mapped collections. + for (Enumeration collRoles = this.collectionCacheStrategies.propertyNames(); collRoles.hasMoreElements();) { + String collRole = (String) collRoles.nextElement(); + String[] strategyAndRegion = + StringUtils.commaDelimitedListToStringArray(this.collectionCacheStrategies.getProperty(collRole)); + if (strategyAndRegion.length > 1) { + config.setCollectionCacheConcurrencyStrategy(collRole, strategyAndRegion[0], strategyAndRegion[1]); + } + else if (strategyAndRegion.length > 0) { + config.setCollectionCacheConcurrencyStrategy(collRole, strategyAndRegion[0]); + } + } + } + + if (this.eventListeners != null) { + // Register specified Hibernate event listeners. + for (Map.Entry entry : this.eventListeners.entrySet()) { + String listenerType = entry.getKey(); + Object listenerObject = entry.getValue(); + if (listenerObject instanceof Collection) { + Collection listeners = (Collection) listenerObject; + EventListeners listenerRegistry = config.getEventListeners(); + Object[] listenerArray = + (Object[]) Array.newInstance(listenerRegistry.getListenerClassFor(listenerType), listeners.size()); + listenerArray = listeners.toArray(listenerArray); + config.setListeners(listenerType, listenerArray); + } + else { + config.setListener(listenerType, listenerObject); + } + } + } + + // Perform custom post-processing in subclasses. + postProcessConfiguration(config); + + // Build SessionFactory instance. + logger.info("Building new Hibernate SessionFactory"); + this.configuration = config; + return newSessionFactory(config); + } + + finally { + if (dataSource != null) { + configTimeDataSourceHolder.remove(); + } + if (this.jtaTransactionManager != null) { + configTimeTransactionManagerHolder.remove(); + } + if (this.cacheRegionFactory != null) { + configTimeCacheProviderHolder.remove(); + } + if (this.cacheProvider != null) { + configTimeCacheProviderHolder.remove(); + } + if (this.lobHandler != null) { + configTimeLobHandlerHolder.remove(); + } + if (overrideClassLoader) { + // Reset original thread context ClassLoader. + currentThread.setContextClassLoader(threadContextClassLoader); + } + } } + /** + * Subclasses can override this method to perform custom initialization + * of the Configuration instance used for SessionFactory creation. + * The properties of this LocalSessionFactoryBean will be applied to + * the Configuration object that gets returned here. + *

The default implementation creates a new Configuration instance. + * A custom implementation could prepare the instance in a specific way, + * or use a custom Configuration subclass. + * @return the Configuration instance + * @throws HibernateException in case of Hibernate initialization errors + * @see org.hibernate.cfg.Configuration#Configuration() + */ + protected Configuration newConfiguration() throws HibernateException { + return BeanUtils.instantiateClass(this.configurationClass); + } + + /** + * To be implemented by subclasses that want to to register further mappings + * on the Configuration object after this FactoryBean registered its specified + * mappings. + *

Invoked before the Configuration.buildMappings() call, + * so that it can still extend and modify the mapping information. + * @param config the current Configuration object + * @throws HibernateException in case of Hibernate initialization errors + * @see org.hibernate.cfg.Configuration#buildMappings() + */ + protected void postProcessMappings(Configuration config) throws HibernateException { + } + + /** + * To be implemented by subclasses that want to to perform custom + * post-processing of the Configuration object after this FactoryBean + * performed its default initialization. + *

Invoked after the Configuration.buildMappings() call, + * so that it can operate on the completed and fully parsed mapping information. + * @param config the current Configuration object + * @throws HibernateException in case of Hibernate initialization errors + * @see org.hibernate.cfg.Configuration#buildMappings() + */ + protected void postProcessConfiguration(Configuration config) throws HibernateException { + } + + /** + * Subclasses can override this method to perform custom initialization + * of the SessionFactory instance, creating it via the given Configuration + * object that got prepared by this LocalSessionFactoryBean. + *

The default implementation invokes Configuration's buildSessionFactory. + * A custom implementation could prepare the instance in a specific way, + * or use a custom SessionFactoryImpl subclass. + * @param config Configuration prepared by this LocalSessionFactoryBean + * @return the SessionFactory instance + * @throws HibernateException in case of Hibernate initialization errors + * @see org.hibernate.cfg.Configuration#buildSessionFactory + */ + protected SessionFactory newSessionFactory(Configuration config) throws HibernateException { + return config.buildSessionFactory(); + } + + /** + * Return the Configuration object used to build the SessionFactory. + * Allows access to configuration metadata stored there (rarely needed). + * @throws IllegalStateException if the Configuration object has not been initialized yet + */ + public final Configuration getConfiguration() { + if (this.configuration == null) { + throw new IllegalStateException("Configuration not initialized yet"); + } + return this.configuration; + } + + /** + * Executes schema update if requested. + * @see #setSchemaUpdate + * @see #updateDatabaseSchema() + */ @Override - protected final void postBuildSessionFactory() { - delegate.postBuildSessionFactory(); + protected void afterSessionFactoryCreation() throws Exception { + if (this.schemaUpdate) { + updateDatabaseSchema(); + } } + /** + * Allows for schema export on shutdown. + */ + @Override public void destroy() throws HibernateException { - delegate.destroy(); + DataSource dataSource = getDataSource(); + if (dataSource != null) { + // Make given DataSource available for potential SchemaExport, + // which unfortunately reinstantiates a ConnectionProvider. + configTimeDataSourceHolder.set(dataSource); + } + try { + super.destroy(); + } + finally { + if (dataSource != null) { + // Reset DataSource holder. + configTimeDataSourceHolder.remove(); + } + } } - public SessionFactory getObject() throws Exception { - return delegate.getSessionFactory(); - } - public Class getObjectType() { - return delegate.getObjectType(); - } - - public void setBeanClassLoader(ClassLoader classLoader) { - delegate.setBeanClassLoader(classLoader); - } - - public boolean isSingleton() { - return delegate.isSingleton(); - } - - public void afterPropertiesSet() throws Exception { - delegate.afterPropertiesSet(); - } - - public DataAccessException translateExceptionIfPossible(RuntimeException ex) { - return delegate.translateExceptionIfPossible(ex); - } - - public void setJdbcExceptionTranslator( - SQLExceptionTranslator jdbcExceptionTranslator) { - delegate.setJdbcExceptionTranslator(jdbcExceptionTranslator); - } - - public void setPersistenceExceptionTranslator( - HibernateExceptionTranslator hibernateExceptionTranslator) { - delegate.setPersistenceExceptionTranslator(hibernateExceptionTranslator); + /** + * Execute schema update script, determined by the Configuration object + * used for creating the SessionFactory. A replacement for Hibernate's + * SchemaUpdate class, for automatically executing schema update scripts + * on application startup. Can also be invoked manually. + *

Fetch the LocalSessionFactoryBean itself rather than the exposed + * SessionFactory to be able to invoke this method, e.g. via + * LocalSessionFactoryBean lsfb = (LocalSessionFactoryBean) ctx.getBean("&mySessionFactory");. + *

Uses the SessionFactory that this bean generates for accessing a + * JDBC connection to perform the script. + * @throws DataAccessException in case of script execution errors + * @see #setSchemaUpdate + * @see org.hibernate.cfg.Configuration#generateSchemaUpdateScript + * @see org.hibernate.tool.hbm2ddl.SchemaUpdate + */ + public void updateDatabaseSchema() throws DataAccessException { + logger.info("Updating database schema for Hibernate SessionFactory"); + DataSource dataSource = getDataSource(); + if (dataSource != null) { + // Make given DataSource available for the schema update. + configTimeDataSourceHolder.set(dataSource); + } + try { + HibernateTemplate hibernateTemplate = new HibernateTemplate(getSessionFactory()); + hibernateTemplate.setFlushMode(HibernateTemplate.FLUSH_NEVER); + hibernateTemplate.execute( + new HibernateCallback() { + public Object doInHibernate(Session session) throws HibernateException, SQLException { + Connection con = session.connection(); + Dialect dialect = Dialect.getDialect(getConfiguration().getProperties()); + DatabaseMetadata metadata = new DatabaseMetadata(con, dialect); + String[] sql = getConfiguration().generateSchemaUpdateScript(dialect, metadata); + executeSchemaScript(con, sql); + return null; + } + } + ); + } + finally { + if (dataSource != null) { + configTimeDataSourceHolder.remove(); + } + } } /** - * @deprecated as of Spring 3.1 in favor of {@link #newSessionFactory()} which - * can access the internal {@code Configuration} instance via {@link #getConfiguration()}. + * Execute schema creation script, determined by the Configuration object + * used for creating the SessionFactory. A replacement for Hibernate's + * SchemaValidator class, to be invoked after application startup. + *

Fetch the LocalSessionFactoryBean itself rather than the exposed + * SessionFactory to be able to invoke this method, e.g. via + * LocalSessionFactoryBean lsfb = (LocalSessionFactoryBean) ctx.getBean("&mySessionFactory");. + *

Uses the SessionFactory that this bean generates for accessing a + * JDBC connection to perform the script. + * @throws DataAccessException in case of script execution errors + * @see org.hibernate.cfg.Configuration#validateSchema + * @see org.hibernate.tool.hbm2ddl.SchemaValidator */ - @Deprecated - protected SessionFactory newSessionFactory(org.hibernate.cfg.Configuration config) throws HibernateException { - return this.newSessionFactory(); + public void validateDatabaseSchema() throws DataAccessException { + logger.info("Validating database schema for Hibernate SessionFactory"); + DataSource dataSource = getDataSource(); + if (dataSource != null) { + // Make given DataSource available for the schema update. + configTimeDataSourceHolder.set(dataSource); + } + try { + HibernateTemplate hibernateTemplate = new HibernateTemplate(getSessionFactory()); + hibernateTemplate.setFlushMode(HibernateTemplate.FLUSH_NEVER); + hibernateTemplate.execute( + new HibernateCallback() { + public Object doInHibernate(Session session) throws HibernateException, SQLException { + Connection con = session.connection(); + Dialect dialect = Dialect.getDialect(getConfiguration().getProperties()); + DatabaseMetadata metadata = new DatabaseMetadata(con, dialect, false); + getConfiguration().validateSchema(dialect, metadata); + return null; + } + } + ); + } + finally { + if (dataSource != null) { + configTimeDataSourceHolder.remove(); + } + } } /** - * @deprecated as of Spring 3.1 in favor of {@link #postProcessMappings()} which - * can access the internal {@code Configuration} instance via {@link #getConfiguration()}. + * Execute schema drop script, determined by the Configuration object + * used for creating the SessionFactory. A replacement for Hibernate's + * SchemaExport class, to be invoked on application setup. + *

Fetch the LocalSessionFactoryBean itself rather than the exposed + * SessionFactory to be able to invoke this method, e.g. via + * LocalSessionFactoryBean lsfb = (LocalSessionFactoryBean) ctx.getBean("&mySessionFactory");. + *

Uses the SessionFactory that this bean generates for accessing a + * JDBC connection to perform the script. + * @throws org.springframework.dao.DataAccessException in case of script execution errors + * @see org.hibernate.cfg.Configuration#generateDropSchemaScript + * @see org.hibernate.tool.hbm2ddl.SchemaExport#drop */ - @Deprecated - protected void postProcessMappings(org.hibernate.cfg.Configuration config) throws HibernateException { - this.postProcessMappings(); + public void dropDatabaseSchema() throws DataAccessException { + logger.info("Dropping database schema for Hibernate SessionFactory"); + HibernateTemplate hibernateTemplate = new HibernateTemplate(getSessionFactory()); + hibernateTemplate.execute( + new HibernateCallback() { + public Object doInHibernate(Session session) throws HibernateException, SQLException { + Connection con = session.connection(); + Dialect dialect = Dialect.getDialect(getConfiguration().getProperties()); + String[] sql = getConfiguration().generateDropSchemaScript(dialect); + executeSchemaScript(con, sql); + return null; + } + } + ); } /** - * @deprecated as of Spring 3.1 in favor of {@link #postProcessConfiguration()} which - * can access the internal {@code Configuration} instance via {@link #getConfiguration()}. + * Execute schema creation script, determined by the Configuration object + * used for creating the SessionFactory. A replacement for Hibernate's + * SchemaExport class, to be invoked on application setup. + *

Fetch the LocalSessionFactoryBean itself rather than the exposed + * SessionFactory to be able to invoke this method, e.g. via + * LocalSessionFactoryBean lsfb = (LocalSessionFactoryBean) ctx.getBean("&mySessionFactory");. + *

Uses the SessionFactory that this bean generates for accessing a + * JDBC connection to perform the script. + * @throws DataAccessException in case of script execution errors + * @see org.hibernate.cfg.Configuration#generateSchemaCreationScript + * @see org.hibernate.tool.hbm2ddl.SchemaExport#create */ - @Deprecated - protected void postProcessConfiguration(org.hibernate.cfg.Configuration config) throws HibernateException { - this.postProcessConfiguration(); + public void createDatabaseSchema() throws DataAccessException { + logger.info("Creating database schema for Hibernate SessionFactory"); + DataSource dataSource = getDataSource(); + if (dataSource != null) { + // Make given DataSource available for the schema update. + configTimeDataSourceHolder.set(dataSource); + } + try { + HibernateTemplate hibernateTemplate = new HibernateTemplate(getSessionFactory()); + hibernateTemplate.execute( + new HibernateCallback() { + public Object doInHibernate(Session session) throws HibernateException, SQLException { + Connection con = session.connection(); + Dialect dialect = Dialect.getDialect(getConfiguration().getProperties()); + String[] sql = getConfiguration().generateSchemaCreationScript(dialect); + executeSchemaScript(con, sql); + return null; + } + } + ); + } + finally { + if (dataSource != null) { + configTimeDataSourceHolder.remove(); + } + } + } + + /** + * Execute the given schema script on the given JDBC Connection. + *

Note that the default implementation will log unsuccessful statements + * and continue to execute. Override the executeSchemaStatement + * method to treat failures differently. + * @param con the JDBC Connection to execute the script on + * @param sql the SQL statements to execute + * @throws SQLException if thrown by JDBC methods + * @see #executeSchemaStatement + */ + protected void executeSchemaScript(Connection con, String[] sql) throws SQLException { + if (sql != null && sql.length > 0) { + boolean oldAutoCommit = con.getAutoCommit(); + if (!oldAutoCommit) { + con.setAutoCommit(true); + } + try { + Statement stmt = con.createStatement(); + try { + for (String sqlStmt : sql) { + executeSchemaStatement(stmt, sqlStmt); + } + } + finally { + JdbcUtils.closeStatement(stmt); + } + } + finally { + if (!oldAutoCommit) { + con.setAutoCommit(false); + } + } + } + } + + /** + * Execute the given schema SQL on the given JDBC Statement. + *

Note that the default implementation will log unsuccessful statements + * and continue to execute. Override this method to treat failures differently. + * @param stmt the JDBC Statement to execute the SQL on + * @param sql the SQL statement to execute + * @throws SQLException if thrown by JDBC methods (and considered fatal) + */ + protected void executeSchemaStatement(Statement stmt, String sql) throws SQLException { + if (logger.isDebugEnabled()) { + logger.debug("Executing schema statement: " + sql); + } + try { + stmt.executeUpdate(sql); + } + catch (SQLException ex) { + if (logger.isWarnEnabled()) { + logger.warn("Unsuccessful schema statement: " + sql, ex); + } + } } } diff --git a/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/LocalTransactionManagerLookup.java b/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/LocalTransactionManagerLookup.java index f02770f621..0990f8384f 100644 --- a/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/LocalTransactionManagerLookup.java +++ b/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/LocalTransactionManagerLookup.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2011 the original author or authors. + * Copyright 2002-2008 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -26,11 +26,11 @@ import org.hibernate.transaction.TransactionManagerLookup; /** * Implementation of Hibernate's {@link TransactionManagerLookup} interface * that returns a Spring-managed JTA {@link TransactionManager}, determined - * by SessionFactoryBuilder's "jtaTransactionManager" property. + * by LocalSessionFactoryBean's "jtaTransactionManager" property. * *

The main advantage of this TransactionManagerLookup is that it avoids * double configuration of JTA specifics. A single TransactionManager bean can - * be used for both JtaTransactionManager and SessionFactoryBuilder, with no + * be used for both JtaTransactionManager and LocalSessionFactoryBean, with no * JTA setup in Hibernate configuration. * *

Alternatively, use Hibernate's own TransactionManagerLookup implementations: @@ -40,7 +40,7 @@ import org.hibernate.transaction.TransactionManagerLookup; * * @author Juergen Hoeller * @since 1.2 - * @see SessionFactoryBuilder#setJtaTransactionManager + * @see LocalSessionFactoryBean#setJtaTransactionManager * @see org.springframework.transaction.jta.JtaTransactionManager#setTransactionManager */ public class LocalTransactionManagerLookup implements TransactionManagerLookup { @@ -49,11 +49,11 @@ public class LocalTransactionManagerLookup implements TransactionManagerLookup { public LocalTransactionManagerLookup() { - TransactionManager tm = SessionFactoryBuilderSupport.getConfigTimeTransactionManager(); + TransactionManager tm = LocalSessionFactoryBean.getConfigTimeTransactionManager(); // absolutely needs thread-bound TransactionManager to initialize if (tm == null) { throw new IllegalStateException("No JTA TransactionManager found - " + - "'jtaTransactionManager' property must be set on SessionFactoryBuilder"); + "'jtaTransactionManager' property must be set on LocalSessionFactoryBean"); } this.transactionManager = tm; } diff --git a/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/SessionFactoryBeanDelegate.java b/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/SessionFactoryBeanDelegate.java deleted file mode 100644 index 4bf3b61323..0000000000 --- a/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/SessionFactoryBeanDelegate.java +++ /dev/null @@ -1,198 +0,0 @@ -/* - * Copyright 2002-2011 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.orm.hibernate3; - -import javax.sql.DataSource; - -import org.hibernate.HibernateException; -import org.hibernate.SessionFactory; -import org.hibernate.cache.RegionFactory; -import org.hibernate.cfg.Environment; -import org.springframework.dao.DataAccessException; -import org.springframework.jdbc.support.SQLExceptionTranslator; - -/** - * Encapsulates common {@link SessionFactoryBeanOperations} behavior in order - * to avoid multiple-inheritance issues with {@code SessionFactoryBeanOperations} - * implementations that need to extend {@code *SessionFactoryBuilder} types. - * - *

Maintainer's note: Unless otherwise documented, JavaDoc for all methods is - * inherited from {@link SessionFactoryBeanOperations}. - * - * @author Chris Beams - * @since 3.1 - */ -public class SessionFactoryBeanDelegate implements SessionFactoryBeanOperations { - - private SessionFactory sessionFactory; - - private HibernateExceptionTranslator hibernateExceptionTranslator = new HibernateExceptionTranslator(); - - private final SessionFactoryBuilderSupport builder; - - private final ThreadContextClassLoaderHelper threadContextClassLoader = new ThreadContextClassLoaderHelper(); - - @Deprecated - private org.hibernate.cache.CacheProvider cacheProvider; - - @Deprecated - private static final ThreadLocal configTimeCacheProviderHolder = - new ThreadLocal(); - - /** - * Create a new {@code SessionFactoryBeanDelegate} - * @param builder the {@code *SessionFactoryBuilder} that delegates to this - * instance. - */ - public SessionFactoryBeanDelegate(SessionFactoryBuilderSupport builder) { - this.builder = builder; - } - - /** - * Return the {@code SessionFactory} maintained by this delegate. - */ - public SessionFactory getSessionFactory() { - return sessionFactory; - } - - /** - * Return the CacheProvider for the currently configured Hibernate SessionFactory, - * to be used by LocalCacheProviderProxy. - *

This instance will be set before initialization of the corresponding - * SessionFactory, and reset immediately afterwards. It is thus only available - * during configuration. - * @see #setCacheProvider - * @deprecated as of Spring 3.1 in favor of Hibernate's {@link RegionFactory} SPI - */ - @Deprecated - public static org.hibernate.cache.CacheProvider getConfigTimeCacheProvider() { - return configTimeCacheProviderHolder.get(); - } - - @Deprecated - public void setCacheProvider(org.hibernate.cache.CacheProvider cacheProvider) { - this.cacheProvider = cacheProvider; - } - - public void setPersistenceExceptionTranslator(HibernateExceptionTranslator hibernateExceptionTranslator) { - this.hibernateExceptionTranslator = hibernateExceptionTranslator; - } - - public void setBeanClassLoader(ClassLoader beanClassLoader) { - builder.setClassLoader(beanClassLoader); - } - - public SessionFactory getObject() { - return this.sessionFactory; - } - - public Class getObjectType() { - return (this.sessionFactory != null ? this.sessionFactory.getClass() : SessionFactory.class); - } - - public boolean isSingleton() { - return true; - } - - public void afterPropertiesSet() throws Exception { - SessionFactory rawSf = builder.doBuildSessionFactory(); - this.sessionFactory = builder.wrapSessionFactoryIfNecessary(rawSf); - builder.afterSessionFactoryCreation(); - } - - public void destroy() throws HibernateException { - builder.logger.info("Closing Hibernate SessionFactory"); - DataSource dataSource = builder.getDataSource(); - if (dataSource != null) { - // Make given DataSource available for potential SchemaExport, - // which unfortunately reinstantiates a ConnectionProvider. - SessionFactoryBuilderSupport.configTimeDataSourceHolder.set(dataSource); - } - try { - builder.beforeSessionFactoryDestruction(); - } - finally { - this.sessionFactory.close(); - if (dataSource != null) { - // Reset DataSource holder. - SessionFactoryBuilderSupport.configTimeDataSourceHolder.remove(); - } - } - } - - public void setJdbcExceptionTranslator(SQLExceptionTranslator jdbcExceptionTranslator) { - this.hibernateExceptionTranslator.setJdbcExceptionTranslator(jdbcExceptionTranslator); - } - - public DataAccessException translateExceptionIfPossible(RuntimeException ex) { - return hibernateExceptionTranslator.translateExceptionIfPossible(ex); - } - - /** - * @see SessionFactoryBuilderSupport#preBuildSessionFactory() - */ - @SuppressWarnings("deprecation") - public void preBuildSessionFactory() { - if (this.cacheProvider != null) { - // Make Spring-provided Hibernate CacheProvider available. - configTimeCacheProviderHolder.set(this.cacheProvider); - } - if (builder.getCacheRegionFactory() == null && this.cacheProvider != null) { - // Expose Spring-provided Hibernate CacheProvider. - builder.getConfiguration().setProperty(Environment.CACHE_PROVIDER, LocalCacheProviderProxy.class.getName()); - } - - // Analogous to Hibernate EntityManager's Ejb3Configuration: - // Hibernate doesn't allow setting the bean ClassLoader explicitly, - // so we need to expose it as thread context ClassLoader accordingly. - threadContextClassLoader.overrideIfNecessary(); - } - - /** - * @see SessionFactoryBuilderSupport#postBuildSessionFactory - */ - public void postBuildSessionFactory() { - if (this.cacheProvider != null) { - configTimeCacheProviderHolder.remove(); - } - threadContextClassLoader.resetIfNecessary(); - } - - - private class ThreadContextClassLoaderHelper { - private Thread currentThread = Thread.currentThread(); - private boolean shouldOverride = false; - private ClassLoader originalLoader; - - void overrideIfNecessary() { - this.originalLoader = currentThread.getContextClassLoader(); - this.shouldOverride = - (builder.getBeanClassLoader() != null && !builder.getBeanClassLoader().equals(this.originalLoader)); - if (shouldOverride) { - this.currentThread.setContextClassLoader(builder.getBeanClassLoader()); - } - } - - void resetIfNecessary() { - if (this.shouldOverride) { - // Reset original thread context ClassLoader. - this.currentThread.setContextClassLoader(this.originalLoader); - } - } - } - -} diff --git a/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/SessionFactoryBeanOperations.java b/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/SessionFactoryBeanOperations.java deleted file mode 100644 index e4c810d8aa..0000000000 --- a/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/SessionFactoryBeanOperations.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright 2002-2011 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.orm.hibernate3; - -import org.hibernate.HibernateException; -import org.hibernate.SessionFactory; -import org.hibernate.cache.RegionFactory; -import org.springframework.beans.factory.BeanClassLoaderAware; -import org.springframework.beans.factory.DisposableBean; -import org.springframework.beans.factory.FactoryBean; -import org.springframework.beans.factory.InitializingBean; -import org.springframework.dao.DataAccessException; -import org.springframework.dao.support.PersistenceExceptionTranslator; -import org.springframework.jdbc.support.SQLExceptionTranslator; -import org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean; - -/** - * Operations common to {@link LocalSessionFactoryBean} and - * {@link AnnotationSessionFactoryBean} types but not available via - * their respective {@code *Builder} supertypes. - * - * @author Chris Beams - * @since 3.1 - * @see LocalSessionFactoryBean - * @see AnnotationSessionFactoryBean - * @see SessionFactoryBeanDelegate - */ -public interface SessionFactoryBeanOperations - extends BeanClassLoaderAware, FactoryBean, - InitializingBean, DisposableBean, PersistenceExceptionTranslator { - - /** - * Deprecated. as of Spring 3.0 in favor of {@code setCacheRegionFactory} - * following Hibernate 3.3's deprecation of the {@code CacheProvider} SPI. - *

Set the Hibernate {@code CacheProvider} to use for the {@code SessionFactory}. - * Allows for using a Spring-managed {@code CacheProvider} instance. - *

Note: If this is set, the Hibernate settings should not define a - * cache provider to avoid meaningless double configuration. - * of the {@code CacheProvider} SPI in favor of {@link RegionFactory} SPI. - */ - @Deprecated - void setCacheProvider(org.hibernate.cache.CacheProvider cacheProvider); - - /** - * Customize the {@code HibernateExceptionTranslator} to be used when translating native - * {@code HibernateException} types to Spring's {@code DataAccessException} hierarchy. - */ - void setPersistenceExceptionTranslator(HibernateExceptionTranslator hibernateExceptionTranslator); - - /** - * Exists for compatibility with {@link BeanClassLoaderAware} but - * simply delegates to - * {@link SessionFactoryBuilderSupport#setClassLoader setClassLoader}. - */ - void setBeanClassLoader(ClassLoader beanClassLoader); - - /** - * Return the singleton SessionFactory. - */ - SessionFactory getObject() throws Exception; - - /** - * Return the SessionFactory class used. - */ - Class getObjectType(); - - /** - * Return {@code true}. - */ - boolean isSingleton(); - - /** - * Build and expose the SessionFactory. - * @see SessionFactoryBuilderSupport#buildSessionFactory - * @see SessionFactoryBuilderSupport#doBuildSessionFactory - * @see SessionFactoryBuilderSupport#wrapSessionFactoryIfNecessary - * @see SessionFactoryBuilderSupport#afterSessionFactoryCreation - */ - void afterPropertiesSet() throws Exception; - - /** - * Close the SessionFactory on bean factory shutdown. - */ - void destroy() throws HibernateException; - - /** - * Set the JDBC exception translator for the SessionFactory - * on this instance's underlying {@link #setPersistenceExceptionTranslator - * HibernateExceptionTranslator}. - *

Applied to any SQLException root cause of a Hibernate JDBCException, - * overriding Hibernate's default SQLException translation (which is - * based on Hibernate's Dialect for a specific target database). - * @param jdbcExceptionTranslator the exception translator - * @see #setPersistenceExceptionTranslator(HibernateExceptionTranslator) - * @see HibernateExceptionTranslator#setJdbcExceptionTranslator - * @see java.sql.SQLException - * @see org.hibernate.JDBCException - * @see org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator - * @see org.springframework.jdbc.support.SQLStateSQLExceptionTranslator - * @see org.springframework.dao.support.PersistenceExceptionTranslator - */ - void setJdbcExceptionTranslator(SQLExceptionTranslator jdbcExceptionTranslator); - - /** - * Implementation of the PersistenceExceptionTranslator interface, - * as autodetected by Spring's PersistenceExceptionTranslationPostProcessor. - *

Converts the exception if it is a HibernateException; - * else returns null to indicate an unknown exception. - * @see org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor - * @see #convertHibernateAccessException - */ - DataAccessException translateExceptionIfPossible(RuntimeException ex); - -} diff --git a/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/SessionFactoryBuilder.java b/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/SessionFactoryBuilder.java deleted file mode 100644 index bcd7e82d56..0000000000 --- a/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/SessionFactoryBuilder.java +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright 2002-2011 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.orm.hibernate3; - -import javax.sql.DataSource; - -import org.hibernate.cfg.Configuration; -import org.springframework.context.annotation.Bean; - -/** - * Hibernate {@link Configuration} builder suitable for use within Spring - * {@link org.springframework.context.annotation.Configuration @Configuration} - * class {@link Bean @Bean} methods. For complete details on features, see the - * JavaDoc for the {@link SessionFactoryBuilderSupport} superclass. For use in - * Spring XML configuration, see the {@link LocalSessionFactoryBean} subclass. - * - *

As noted in {@code SessionFactoryBuilderSupport} JavaDoc, this class requires - * Hibernate 3.2 or later; it additionally requires that the Java Persistence API - * and Hibernate Annotations add-ons are present. - * - *

Setter methods return the builder instance in order to facilitate - * a concise and convenient method-chaining style. For example: - *

- * {@code @Configuration}
- * public class DataConfig {
- *     {@code @Bean}
- *     public SessionFactory sessionFactory() {
- *         return new SessionFactoryBean()
- *             .setDataSource(dataSource())
- *             .setMappingLocations("classpath:com/myco/*.hbm.xml"})
- *             .buildSessionFactory();
- *     }
- * }
- * 
- * - *

Most Hibernate configuration operations can be performed directly against - * this API; however you may also access access and configure the underlying - * {@code Configuration} object by using the {@link #doWithConfiguration} method - * and providing a {@code HibernateConfigurationCallback} as follows: - *

- * SessionFactory sessionFactory =
- *     new SessionFactoryBuilder()
- *         // ...
- *         .doWithConfiguration(new HibernateConfigurationCallback<Configuration>() {
- *             public void configure(Configuration cfg) {
- *                 cfg.setNamingStrategy(MyNamingStrategy.class);
- *             }
- *          })
- *         .buildSessionFactory();
- * 
- * - * @author Juergen Hoeller - * @author Chris Beams - * @since 3.1 - * @see SessionFactoryBuilderSupport - * @see LocalSessionFactoryBean - * @see org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBuilder - * @see org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean - */ -public class SessionFactoryBuilder extends SessionFactoryBuilderSupport { - - /** - * Construct a new {@code SessionFactoryBuilder} - */ - public SessionFactoryBuilder() { - super(); - } - - /** - * Construct a new {@code SessionFactoryBuilder} with the given - * Spring-managed {@code DataSource} instance. - * @see #setDataSource - */ - public SessionFactoryBuilder(DataSource dataSource) { - super(dataSource); - } - - /** - * {@inheritDoc} - *

This implementation returns {@code org.hibernate.cfg.Configuration} - */ - @Override - protected Class getDefaultConfigurationClass() { - return Configuration.class; - } - -} diff --git a/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/SessionFactoryBuilderSupport.java b/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/SessionFactoryBuilderSupport.java deleted file mode 100644 index c7c82d394c..0000000000 --- a/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/SessionFactoryBuilderSupport.java +++ /dev/null @@ -1,1408 +0,0 @@ -/* - * Copyright 2002-2011 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.orm.hibernate3; - -import java.io.File; -import java.lang.reflect.Array; -import java.lang.reflect.Method; -import java.sql.Connection; -import java.sql.SQLException; -import java.sql.Statement; -import java.util.Collection; -import java.util.Enumeration; -import java.util.Map; -import java.util.Properties; - -import javax.sql.DataSource; -import javax.transaction.TransactionManager; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.hibernate.HibernateException; -import org.hibernate.Interceptor; -import org.hibernate.Session; -import org.hibernate.SessionFactory; -import org.hibernate.cfg.Configuration; -import org.hibernate.cfg.Environment; -import org.hibernate.cfg.NamingStrategy; -import org.hibernate.dialect.Dialect; -import org.hibernate.engine.FilterDefinition; -import org.hibernate.engine.SessionFactoryImplementor; -import org.hibernate.event.EventListeners; -import org.hibernate.tool.hbm2ddl.DatabaseMetadata; -import org.hibernate.transaction.JTATransactionFactory; -import org.springframework.beans.BeanUtils; -import org.springframework.core.io.ClassPathResource; -import org.springframework.core.io.Resource; -import org.springframework.dao.DataAccessException; -import org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy; -import org.springframework.jdbc.support.JdbcUtils; -import org.springframework.jdbc.support.lob.LobHandler; -import org.springframework.util.Assert; -import org.springframework.util.ClassUtils; -import org.springframework.util.ReflectionUtils; -import org.springframework.util.StringUtils; - -/** - * Abstract base class for Spring's Hibernate {@code SessionFactory} {@code - * *Builder} and {@code *FactoryBean} types. Provides functionality suitable for - * setting up a shared Hibernate {@code SessionFactory} in a Spring application - * context; the {@code SessionFactory} can then be passed to Hibernate-based - * Repositories/DAOs via dependency injection. - * - *

Configuration settings can either be read from a - * Hibernate XML file, specified by the - * {@linkplain #setConfigLocation configLocation} property, or completely via this - * class. A typical local configuration consists of one or more {@linkplain - * #setMappingResources mappingResources}, various {@linkplain - * #setHibernateProperties hibernateProperties} (not strictly necessary), and a - * {@linkplain #setDataSource dataSource} that the {@code SessionFactory} should - * use. The latter can also be specified via Hibernate properties, but {@link - * #setDataSource} supports any Spring-configured {@code DataSource}, instead of - * relying on Hibernate's own connection providers. - * - *

This {@code SessionFactory} handling strategy is appropriate for most types - * of applications, from Hibernate-only single database apps to ones that need - * distributed transactions. Either a {@link HibernateTransactionManager} or {@link - * org.springframework.transaction.jta.JtaTransactionManager JtaTransactionManager} - * can be used for transaction demarcation, with the latter only necessary for - * transactions which span multiple databases. - * - *

By default a transaction-aware {@code SessionFactory} proxy will be exposed, - * letting data access code work with the plain Hibernate {@code SessionFactory} - * and its {@code getCurrentSession()} method, while still being able to - * participate in current Spring-managed transactions: with any transaction - * management strategy, either local or JTA / EJB CMT, and any transaction - * synchronization mechanism, either Spring or JTA. Furthermore, - * {@code getCurrentSession()} will also seamlessly work with a request-scoped - * {@code Session} managed by - * {@link org.springframework.orm.hibernate3.support.OpenSessionInViewFilter} or - * {@link org.springframework.orm.hibernate3.support.OpenSessionInViewInterceptor}. - * - *

Requires Hibernate 3.2 or later; tested against 3.2, 3.3, 3.5 and 3.6. - * Note that this factory will use "on_close" as default Hibernate connection - * release mode, unless in the case of a {@linkplain #setJtaTransactionManager - * jtaTransactionManager} being specified, as this is appropriate for most - * Spring-based applications (in particular when using Spring's - * {@code HibernateTransactionManager}). - * - *

Concrete {@code *Builder} subclasses are designed for use within Spring - * {@link org.springframework.context.annotation.Configuration @Configuration} - * classes, while {@code *FactoryBean} subclasses are designed for use when - * configuring the container via Spring XML. See individual subclass documentation - * for complete details. - * - *

It is common to use the subclasses mentioned above in conjunction with - * Spring's {@link HibernateExceptionTranslator} and a - * {@code PersistenceExceptionTranslationPostProcessor} in order to convert native - * {@code HibernateException} types to Spring's {@link DataAccessException} - * hierarchy. {@code *FactoryBean} automatically perform translation through a - * built-in {@code HibernateExceptionTranslator}, but {@code @Configuration} - * class {@code @Bean} methods that use {@code *Builder} subclasses should - * manually register a {@code HibernateExceptionTranslator} {@code @Bean}. - * When using either type of subclass you must manually register a - * {@code PersistenceExceptionTranslationPostProcessor} bean. - * - * @author Juergen Hoeller - * @author Chris Beams - * @since 3.1 - * @see SessionFactoryBuilder - * @see LocalSessionFactoryBean - * @see org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBuilder - * @see org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean - * @see org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor - * @see org.springframework.orm.hibernate3.HibernateExceptionTranslator - * @see HibernateTemplate#setSessionFactory - * @see HibernateTransactionManager#setSessionFactory - * @see #setExposeTransactionAwareSessionFactory - * @see #setJtaTransactionManager - * @see org.hibernate.SessionFactory#getCurrentSession - * @see HibernateTransactionManager - */ -public abstract class SessionFactoryBuilderSupport> { - - static final ThreadLocal configTimeDataSourceHolder = - new ThreadLocal(); - - private static final ThreadLocal configTimeTransactionManagerHolder = - new ThreadLocal(); - - private static final ThreadLocal configTimeRegionFactoryHolder = - new ThreadLocal(); - - private static final ThreadLocal configTimeLobHandlerHolder = - new ThreadLocal(); - - /** Logger available to subclasses */ - protected final Log logger = LogFactory.getLog(getClass()); - - @SuppressWarnings("unchecked") - private final This instance = (This) this; - - private Class configurationClass = getDefaultConfigurationClass(); - - /** Lazily initialized during calls to {@link #getConfiguration()} */ - private Configuration configuration; - - private DataSource dataSource; - - private SessionFactory sessionFactory; - - private boolean schemaUpdate = false; - - private boolean exposeTransactionAwareSessionFactory = true; - - private boolean useTransactionAwareDataSource = false; - - private ClassLoader beanClassLoader = ClassUtils.getDefaultClassLoader(); - - private Resource[] mappingLocations; - - private Resource[] cacheableMappingLocations; - - private Resource[] mappingJarLocations; - - private Resource[] mappingDirectoryLocations; - - private TransactionManager jtaTransactionManager; - - private Object cacheRegionFactory; - - private LobHandler lobHandler; - - private Interceptor entityInterceptor; - - private NamingStrategy namingStrategy; - - private TypeDefinitionBean[] typeDefinitions; - - private FilterDefinition[] filterDefinitions; - - private Resource[] configLocations; - - private Properties hibernateProperties; - - private Properties entityCacheStrategies; - - private Properties collectionCacheStrategies; - - private Map eventListeners; - - private String[] mappingResources; - - /** - * Constructor for use when DataSource is not available as a Spring bean - * instance, i.e.: when DataSource configuration should be read from - * {@code hibernate.cfg.xml} - * @see SessionFactoryBuilderSupport#AbstractSessionFactoryBuilder(DataSource) - */ - public SessionFactoryBuilderSupport() { - } - - public SessionFactoryBuilderSupport(DataSource dataSource) { - this.dataSource = dataSource; - } - - /** - * Return the default Configuration type used by this instance. - * May be overridden with {@link #setConfigurationClass(Class)}. - * @see #setConfigurationClass(Class) - */ - protected abstract Class getDefaultConfigurationClass(); - - /** - * Build the underlying Hibernate SessionFactory. - * @return the raw SessionFactory (potentially to be wrapped with a - * transaction-aware proxy before it is exposed to the application) - * @throws Exception in case of initialization failure - */ - public SessionFactory buildSessionFactory() throws Exception { - this.sessionFactory = wrapSessionFactoryIfNecessary(doBuildSessionFactory()); - afterSessionFactoryCreation(); - return this.sessionFactory; - } - - /** - * Populate the underlying {@code Configuration} instance with the various - * properties of this builder. Customization may be performed through - * {@code pre*} and {@code post*} methods. - * @see #preBuildSessionFactory() - * @see #postProcessMappings() - * @see #postBuildSessionFactory() - * @see #postBuildSessionFactory() - */ - protected final SessionFactory doBuildSessionFactory() throws Exception { - initializeConfigurationIfNecessary(); - - if (this.dataSource != null) { - // Make given DataSource available for SessionFactory configuration. - configTimeDataSourceHolder.set(this.dataSource); - } - if (this.jtaTransactionManager != null) { - // Make Spring-provided JTA TransactionManager available. - configTimeTransactionManagerHolder.set(this.jtaTransactionManager); - } - if (this.cacheRegionFactory != null) { - // Make Spring-provided Hibernate RegionFactory available. - configTimeRegionFactoryHolder.set(this.cacheRegionFactory); - } - if (this.lobHandler != null) { - // Make given LobHandler available for SessionFactory configuration. - // Do early because because mapping resource might refer to custom types. - configTimeLobHandlerHolder.set(this.lobHandler); - } - - try { - if (isExposeTransactionAwareSessionFactory()) { - // Set Hibernate 3.1+ CurrentSessionContext implementation, - // providing the Spring-managed Session as current Session. - // Can be overridden by a custom value for the corresponding Hibernate property. - this.configuration.setProperty( - Environment.CURRENT_SESSION_CONTEXT_CLASS, SpringSessionContext.class.getName()); - } - - if (this.jtaTransactionManager != null) { - // Set Spring-provided JTA TransactionManager as Hibernate property. - this.configuration.setProperty( - Environment.TRANSACTION_STRATEGY, JTATransactionFactory.class.getName()); - this.configuration.setProperty( - Environment.TRANSACTION_MANAGER_STRATEGY, LocalTransactionManagerLookup.class.getName()); - } - else { - // Makes the Hibernate Session aware of the presence of a Spring-managed transaction. - // Also sets connection release mode to ON_CLOSE by default. - this.configuration.setProperty( - Environment.TRANSACTION_STRATEGY, SpringTransactionFactory.class.getName()); - } - - if (this.entityInterceptor != null) { - // Set given entity interceptor at SessionFactory level. - this.configuration.setInterceptor(this.entityInterceptor); - } - - if (this.namingStrategy != null) { - // Pass given naming strategy to Hibernate Configuration. - this.configuration.setNamingStrategy(this.namingStrategy); - } - - if (this.typeDefinitions != null) { - // Register specified Hibernate type definitions. - // Use reflection for compatibility with both Hibernate 3.3 and 3.5: - // the returned Mappings object changed from a class to an interface. - Method createMappings = Configuration.class.getMethod("createMappings"); - Method addTypeDef = createMappings.getReturnType().getMethod( - "addTypeDef", String.class, String.class, Properties.class); - Object mappings = ReflectionUtils.invokeMethod(createMappings, this.configuration); - for (TypeDefinitionBean typeDef : this.typeDefinitions) { - ReflectionUtils.invokeMethod(addTypeDef, mappings, - typeDef.getTypeName(), typeDef.getTypeClass(), typeDef.getParameters()); - } - } - - if (this.filterDefinitions != null) { - // Register specified Hibernate FilterDefinitions. - for (FilterDefinition filterDef : this.filterDefinitions) { - this.configuration.addFilterDefinition(filterDef); - } - } - - if (this.configLocations != null) { - for (Resource resource : this.configLocations) { - // Load Hibernate configuration from given location. - this.configuration.configure(resource.getURL()); - } - } - - if (this.hibernateProperties != null) { - // Add given Hibernate properties to Configuration. - this.configuration.addProperties(this.hibernateProperties); - } - - if (dataSource != null) { - Class providerClass = LocalDataSourceConnectionProvider.class; - if (isUseTransactionAwareDataSource() || dataSource instanceof TransactionAwareDataSourceProxy) { - providerClass = TransactionAwareDataSourceConnectionProvider.class; - } - else if (this.configuration.getProperty(Environment.TRANSACTION_MANAGER_STRATEGY) != null) { - providerClass = LocalJtaDataSourceConnectionProvider.class; - } - // Set Spring-provided DataSource as Hibernate ConnectionProvider. - this.configuration.setProperty(Environment.CONNECTION_PROVIDER, providerClass.getName()); - } - - if (this.cacheRegionFactory != null) { - // Expose Spring-provided Hibernate RegionFactory. - this.configuration.setProperty(Environment.CACHE_REGION_FACTORY, - "org.springframework.orm.hibernate3.LocalRegionFactoryProxy"); - } - - if (this.mappingResources != null) { - // Register given Hibernate mapping definitions, contained in resource files. - for (String mapping : this.mappingResources) { - Resource resource = new ClassPathResource(mapping.trim(), this.beanClassLoader); - this.configuration.addInputStream(resource.getInputStream()); - } - } - - if (this.mappingLocations != null) { - // Register given Hibernate mapping definitions, contained in resource files. - for (Resource resource : this.mappingLocations) { - this.configuration.addInputStream(resource.getInputStream()); - } - } - - if (this.cacheableMappingLocations != null) { - // Register given cacheable Hibernate mapping definitions, read from the file system. - for (Resource resource : this.cacheableMappingLocations) { - this.configuration.addCacheableFile(resource.getFile()); - } - } - - if (this.mappingJarLocations != null) { - // Register given Hibernate mapping definitions, contained in jar files. - for (Resource resource : this.mappingJarLocations) { - this.configuration.addJar(resource.getFile()); - } - } - - if (this.mappingDirectoryLocations != null) { - // Register all Hibernate mapping definitions in the given directories. - for (Resource resource : this.mappingDirectoryLocations) { - File file = resource.getFile(); - if (!file.isDirectory()) { - throw new IllegalArgumentException( - "Mapping directory location [" + resource + "] does not denote a directory"); - } - this.configuration.addDirectory(file); - } - } - - // Tell Hibernate to eagerly compile the mappings that we registered, - // for availability of the mapping information in further processing. - postProcessMappings(); - this.configuration.buildMappings(); - - if (this.entityCacheStrategies != null) { - // Register cache strategies for mapped entities. - for (Enumeration classNames = this.entityCacheStrategies.propertyNames(); classNames.hasMoreElements();) { - String className = (String) classNames.nextElement(); - String[] strategyAndRegion = - StringUtils.commaDelimitedListToStringArray(this.entityCacheStrategies.getProperty(className)); - if (strategyAndRegion.length > 1) { - // method signature declares return type as Configuration on Hibernate 3.6 - // but as void on Hibernate 3.3 and 3.5 - Method setCacheConcurrencyStrategy = Configuration.class.getMethod( - "setCacheConcurrencyStrategy", String.class, String.class, String.class); - ReflectionUtils.invokeMethod(setCacheConcurrencyStrategy, this.configuration, - className, strategyAndRegion[0], strategyAndRegion[1]); - } - else if (strategyAndRegion.length > 0) { - this.configuration.setCacheConcurrencyStrategy(className, strategyAndRegion[0]); - } - } - } - - if (this.collectionCacheStrategies != null) { - // Register cache strategies for mapped collections. - for (Enumeration collRoles = this.collectionCacheStrategies.propertyNames(); collRoles.hasMoreElements();) { - String collRole = (String) collRoles.nextElement(); - String[] strategyAndRegion = - StringUtils.commaDelimitedListToStringArray(this.collectionCacheStrategies.getProperty(collRole)); - if (strategyAndRegion.length > 1) { - this.configuration.setCollectionCacheConcurrencyStrategy(collRole, strategyAndRegion[0], strategyAndRegion[1]); - } - else if (strategyAndRegion.length > 0) { - this.configuration.setCollectionCacheConcurrencyStrategy(collRole, strategyAndRegion[0]); - } - } - } - - if (this.eventListeners != null) { - // Register specified Hibernate event listeners. - for (Map.Entry entry : this.eventListeners.entrySet()) { - String listenerType = entry.getKey(); - Object listenerObject = entry.getValue(); - if (listenerObject instanceof Collection) { - Collection listeners = (Collection) listenerObject; - EventListeners listenerRegistry = this.configuration.getEventListeners(); - Object[] listenerArray = - (Object[]) Array.newInstance(listenerRegistry.getListenerClassFor(listenerType), listeners.size()); - listenerArray = listeners.toArray(listenerArray); - this.configuration.setListeners(listenerType, listenerArray); - } - else { - this.configuration.setListener(listenerType, listenerObject); - } - } - } - - preBuildSessionFactory(); - - // Perform custom post-processing in subclasses. - postProcessConfiguration(); - - // Build SessionFactory instance. - logger.info("Building new Hibernate SessionFactory"); - - return this.sessionFactory = newSessionFactory(); - } - finally { - if (dataSource != null) { - SessionFactoryBuilderSupport.configTimeDataSourceHolder.remove(); - } - if (this.jtaTransactionManager != null) { - SessionFactoryBuilderSupport.configTimeTransactionManagerHolder.remove(); - } - if (this.cacheRegionFactory != null) { - SessionFactoryBuilderSupport.configTimeRegionFactoryHolder.remove(); - } - if (this.lobHandler != null) { - SessionFactoryBuilderSupport.configTimeLobHandlerHolder.remove(); - } - - postBuildSessionFactory(); - } - } - - /** - * Return the Hibernate {@link Configuration} object used to build the {@link SessionFactory}. - * Allows access to configuration metadata stored there (rarely needed). - *

Favor use of {@link #doWithConfiguration(HibernateConfigurationCallback)} - * in order to customize the internal {@code Configuration} object. - * @see #doWithConfiguration(HibernateConfigurationCallback) - * @throws IllegalStateException if the Configuration object has not been initialized yet - */ - protected final Configuration getConfiguration() { - initializeConfigurationIfNecessary(); - return this.configuration; - } - - private void initializeConfigurationIfNecessary() { - if (this.configuration == null) { - this.configuration = newConfiguration(); - } - } - - /** - * Subclasses can override this method to perform custom initialization - * of the Configuration instance used for SessionFactory creation. - * The properties of this Builder will be applied to - * the Configuration object that gets returned here. - *

The default implementation creates a new Configuration instance. - * A custom implementation could prepare the instance in a specific way, - * or use a custom Configuration subclass. - * @return the Configuration instance - * @throws HibernateException in case of Hibernate initialization errors - * @see org.hibernate.cfg.Configuration#Configuration() - */ - /** - * Instantiate and return an instance of the {@link Configuration} class - * type for this builder. Subclasses may override in order to customize - * instantiation logic, but clients should use {@link #doWithConfiguration} - * to directly customize the {@code Configuration} instance. - * @see #getDefaultConfigurationClass() - * @see #setConfigurationClass(Class) - * @see #getConfiguration() - * @see #doWithConfiguration(HibernateConfigurationCallback) - */ - protected Configuration newConfiguration() { - return BeanUtils.instantiateClass(this.configurationClass); - } - - /** - * Return the exposed SessionFactory. - * Will throw an exception if not initialized yet. - * @return the SessionFactory (never null) - * @throws IllegalStateException if the SessionFactory has not been initialized yet - */ - protected final SessionFactory getSessionFactory() { - if (this.sessionFactory == null) { - throw new IllegalStateException("SessionFactory not initialized yet. Have you called buildSessionFactory()?"); - } - return this.sessionFactory; - } - - /** - * Allow additional population of the underlying {@code Configuration} - * instance. Called during {@link #doBuildSessionFactory()}. - */ - protected void preBuildSessionFactory() { - } - - /** - * Allow cleaning up resources, thread locals, etc after building the - * {@code SessionFactory}. Called during the {@code finally} block of - * {@link #doBuildSessionFactory()}. - */ - protected void postBuildSessionFactory() { - } - - /** - * Wrap the given SessionFactory with a proxy, if demanded. - *

The default implementation simply returns the given SessionFactory as-is. - * Subclasses may override this to implement transaction awareness through - * a SessionFactory proxy, for example. - * @param rawSf the raw SessionFactory as built by {@link #buildSessionFactory()} - * @return the SessionFactory reference to expose - * @see #buildSessionFactory() - */ - protected SessionFactory wrapSessionFactoryIfNecessary(SessionFactory rawSf) { - return rawSf; - } - - /** - * Subclasses can override this method to perform custom initialization - * of the SessionFactory instance, creating it via the given Configuration - * object that got prepared by this Builder. - *

The default implementation invokes Configuration's buildSessionFactory. - * A custom implementation could prepare the instance in a specific way, - * or use a custom SessionFactoryImpl subclass. - * @param config Configuration prepared by this Builder - * @return the SessionFactory instance - * @throws HibernateException in case of Hibernate initialization errors - * @see org.hibernate.cfg.Configuration#buildSessionFactory - */ - protected SessionFactory newSessionFactory() throws HibernateException { - return this.configuration.buildSessionFactory(); - } - - /** - * To be implemented by subclasses that want to to register further mappings - * on the Configuration object after this FactoryBean registered its specified - * mappings. - *

Invoked before the Configuration.buildMappings() call, - * so that it can still extend and modify the mapping information. - * @param config the current Configuration object - * @throws HibernateException in case of Hibernate initialization errors - * @see org.hibernate.cfg.Configuration#buildMappings() - */ - protected void postProcessMappings() throws HibernateException { - } - - /** - * To be implemented by subclasses that want to to perform custom - * post-processing of the Configuration object after this FactoryBean - * performed its default initialization. - *

Invoked after the Configuration.buildMappings() call, - * so that it can operate on the completed and fully parsed mapping information. - * @throws HibernateException in case of Hibernate initialization errors - * @see org.hibernate.cfg.Configuration#buildMappings() - */ - protected void postProcessConfiguration() throws HibernateException { - } - - /** - * Hook that allows post-processing after the SessionFactory has been - * successfully created. The SessionFactory is already available through - * getSessionFactory() at this point. - *

This implementation is empty. - * @throws Exception in case of initialization failure - * @see #getSessionFactory() - */ - /** - * Executes schema update if requested. - * @see #setSchemaUpdate - * @see #updateDatabaseSchema() - */ - protected void afterSessionFactoryCreation() throws Exception { - if (this.schemaUpdate) { - updateDatabaseSchema(); - } - } - - /** - * Hook that allows shutdown processing before the SessionFactory - * will be closed. The SessionFactory is still available through - * getSessionFactory() at this point. - *

This implementation is empty. - * @see #getSessionFactory() - */ - protected void beforeSessionFactoryDestruction() { - } - - /** - * Execute schema creation script, determined by the Configuration object - * used for creating the SessionFactory. A replacement for Hibernate's - * SchemaExport class, to be invoked on application setup. - *

Fetch the FactoryBean itself by rather than the exposed - * SessionFactory to be able to invoke this method, e.g. via - *

-	 * LocalSessionFactoryBean sfb = ctx.getBean("&mySessionFactory", LocalSessionFactoryBean.class);
-	 * 
- * or in the case of {@code @Configuration} class usage, register the - * SessionFactoryBuilder as a {@code @Bean} and fetch it by type: - *
-	 * SessionFactoryBuilder sfb = ctx.getBean(SessionFactoryBuilder.class);
-	 * 
- *

Uses the SessionFactory that this bean generates for accessing a - * JDBC connection to perform the script. - * @throws DataAccessException in case of script execution errors - * @see org.hibernate.cfg.Configuration#generateSchemaCreationScript - * @see org.hibernate.tool.hbm2ddl.SchemaExport#create - */ - public void createDatabaseSchema() throws DataAccessException { - logger.info("Creating database schema for Hibernate SessionFactory"); - DataSource dataSource = getDataSource(); - if (dataSource != null) { - // Make given DataSource available for the schema update. - SessionFactoryBuilderSupport.configTimeDataSourceHolder.set(dataSource); - } - try { - HibernateTemplate hibernateTemplate = new HibernateTemplate(getSessionFactory()); - hibernateTemplate.execute( - new HibernateCallback() { - @SuppressWarnings("deprecation") - public Object doInHibernate(Session session) throws HibernateException, SQLException { - Dialect dialect = ((SessionFactoryImplementor)session.getSessionFactory()).getDialect(); - String[] sql = configuration.generateSchemaCreationScript(dialect); - executeSchemaScript(session.connection(), sql); - return null; - } - } - ); - } - finally { - if (dataSource != null) { - SessionFactoryBuilderSupport.configTimeDataSourceHolder.remove(); - } - } - } - - /** - * Execute schema update script, determined by the Configuration object - * used for creating the SessionFactory. A replacement for Hibernate's - * SchemaUpdate class, for automatically executing schema update scripts - * on application startup. Can also be invoked manually. - *

Fetch the FactoryBean itself by rather than the exposed - * SessionFactory to be able to invoke this method, e.g. via - *

-	 * LocalSessionFactoryBean sfb = ctx.getBean("&mySessionFactory", LocalSessionFactoryBean.class);
-	 * 
- * or in the case of {@code @Configuration} class usage, register the - * SessionFactoryBuilder as a {@code @Bean} and fetch it by type: - *
-	 * SessionFactoryBuilder sfb = ctx.getBean(SessionFactoryBuilder.class);
-	 * 
- *

Uses the SessionFactory that this bean generates for accessing a - * JDBC connection to perform the script. - * @throws DataAccessException in case of script execution errors - * @see #setSchemaUpdate - * @see org.hibernate.cfg.Configuration#generateSchemaUpdateScript - * @see org.hibernate.tool.hbm2ddl.SchemaUpdate - */ - public void updateDatabaseSchema() throws DataAccessException { - logger.info("Updating database schema for Hibernate SessionFactory"); - if (this.dataSource != null) { - // Make given DataSource available for the schema update. - configTimeDataSourceHolder.set(this.dataSource); - } - try { - HibernateTemplate hibernateTemplate = new HibernateTemplate(getSessionFactory()); - hibernateTemplate.setFlushMode(HibernateTemplate.FLUSH_NEVER); - hibernateTemplate.execute( - new HibernateCallback() { - public Void doInHibernate(Session session) throws HibernateException, SQLException { - @SuppressWarnings("deprecation") - Connection conn = session.connection(); - Dialect dialect = ((SessionFactoryImplementor)session.getSessionFactory()).getDialect(); - DatabaseMetadata metadata = new DatabaseMetadata(conn, dialect); - String[] sql = configuration.generateSchemaUpdateScript(dialect, metadata); - executeSchemaScript(conn, sql); - return null; - } - } - ); - } - finally { - if (dataSource != null) { - configTimeDataSourceHolder.remove(); - } - } - } - - /** - * Execute schema creation script, determined by the Configuration object - * used for creating the SessionFactory. A replacement for Hibernate's - * SchemaValidator class, to be invoked after application startup. - *

Fetch the FactoryBean itself by rather than the exposed - * SessionFactory to be able to invoke this method, e.g. via - *

-	 * LocalSessionFactoryBean sfb = ctx.getBean("&mySessionFactory", LocalSessionFactoryBean.class);
-	 * 
- * or in the case of {@code @Configuration} class usage, register the - * SessionFactoryBuilder as a {@code @Bean} and fetch it by type: - *
-	 * SessionFactoryBuilder sfb = ctx.getBean(SessionFactoryBuilder.class);
-	 * 
- *

Uses the SessionFactory that this bean generates for accessing a - * JDBC connection to perform the script. - * @throws DataAccessException in case of script execution errors - * @see org.hibernate.cfg.Configuration#validateSchema - * @see org.hibernate.tool.hbm2ddl.SchemaValidator - */ - public void validateDatabaseSchema() throws DataAccessException { - logger.info("Validating database schema for Hibernate SessionFactory"); - DataSource dataSource = getDataSource(); - if (dataSource != null) { - // Make given DataSource available for the schema update. - SessionFactoryBuilderSupport.configTimeDataSourceHolder.set(dataSource); - } - try { - HibernateTemplate hibernateTemplate = new HibernateTemplate(getSessionFactory()); - hibernateTemplate.setFlushMode(HibernateTemplate.FLUSH_NEVER); - hibernateTemplate.execute( - new HibernateCallback() { - @SuppressWarnings("deprecation") - public Object doInHibernate(Session session) throws HibernateException, SQLException { - Dialect dialect = ((SessionFactoryImplementor)session.getSessionFactory()).getDialect(); - DatabaseMetadata metadata = new DatabaseMetadata(session.connection(), dialect); - configuration.validateSchema(dialect, metadata); - return null; - } - } - ); - } - finally { - if (dataSource != null) { - SessionFactoryBuilderSupport.configTimeDataSourceHolder.remove(); - } - } - } - - /** - * Execute schema drop script, determined by the Configuration object - * used for creating the SessionFactory. A replacement for Hibernate's - * SchemaExport class, to be invoked on application setup. - *

Fetch the FactoryBean itself by rather than the exposed - * SessionFactory to be able to invoke this method, e.g. via - *

-	 * LocalSessionFactoryBean sfb = ctx.getBean("&mySessionFactory", LocalSessionFactoryBean.class);
-	 * 
- * or in the case of {@code @Configuration} class usage, register the - * SessionFactoryBuilder as a {@code @Bean} and fetch it by type: - *
-	 * SessionFactoryBuilder sfb = ctx.getBean(SessionFactoryBuilder.class);
-	 * 
- *

Uses the SessionFactory that this bean generates for accessing a - * JDBC connection to perform the script. - * @throws org.springframework.dao.DataAccessException in case of script execution errors - * @see org.hibernate.cfg.Configuration#generateDropSchemaScript - * @see org.hibernate.tool.hbm2ddl.SchemaExport#drop - */ - public void dropDatabaseSchema() throws DataAccessException { - logger.info("Dropping database schema for Hibernate SessionFactory"); - HibernateTemplate hibernateTemplate = new HibernateTemplate(getSessionFactory()); - hibernateTemplate.execute( - new HibernateCallback() { - @SuppressWarnings("deprecation") - public Void doInHibernate(Session session) throws HibernateException, SQLException { - Dialect dialect = ((SessionFactoryImplementor)session.getSessionFactory()).getDialect(); - String[] sql = configuration.generateDropSchemaScript(dialect); - executeSchemaScript(session.connection(), sql); - return null; - } - } - ); - } - - /** - * Execute the given schema script on the given JDBC Connection. - *

Note that the default implementation will log unsuccessful statements - * and continue to execute. Override the executeSchemaStatement - * method to treat failures differently. - * @param con the JDBC Connection to execute the script on - * @param sql the SQL statements to execute - * @throws SQLException if thrown by JDBC methods - * @see #executeSchemaStatement - */ - protected void executeSchemaScript(Connection con, String[] sql) throws SQLException { - if (sql != null && sql.length > 0) { - boolean oldAutoCommit = con.getAutoCommit(); - if (!oldAutoCommit) { - con.setAutoCommit(true); - } - try { - Statement stmt = con.createStatement(); - try { - for (String sqlStmt : sql) { - executeSchemaStatement(stmt, sqlStmt); - } - } - finally { - JdbcUtils.closeStatement(stmt); - } - } - finally { - if (!oldAutoCommit) { - con.setAutoCommit(false); - } - } - } - } - - /** - * Execute the given schema SQL on the given JDBC Statement. - *

Note that the default implementation will log unsuccessful statements - * and continue to execute. Override this method to treat failures differently. - * @param stmt the JDBC Statement to execute the SQL on - * @param sql the SQL statement to execute - * @throws SQLException if thrown by JDBC methods (and considered fatal) - */ - protected void executeSchemaStatement(Statement stmt, String sql) throws SQLException { - if (logger.isDebugEnabled()) { - logger.debug("Executing schema statement: " + sql); - } - try { - stmt.executeUpdate(sql); - } - catch (SQLException ex) { - if (logger.isWarnEnabled()) { - logger.warn("Unsuccessful schema statement: " + sql, ex); - } - } - } - - /** - * Specify the Hibernate Configuration class to use. - * Default is {@code org.hibernate.cfg.Configuration}; any subclass of - * this default Hibernate {@code Configuration} class can be specified. - *

Can be set to {@code org.hibernate.cfg.AnnotationConfiguration} for - * using Hibernate3 annotation support (initially only available as - * alpha download separate from the main Hibernate3 distribution). - *

Annotated packages and annotated classes can be specified via the - * corresponding tags in "hibernate.cfg.xml" then, so this will usually - * be combined with a "configLocation" property that points at such a - * standard Hibernate configuration file. - * @see #setConfigLocation - * @see #doWithConfiguration - * @see org.hibernate.cfg.Configuration - * @see org.hibernate.cfg.AnnotationConfiguration - */ - public final This setConfigurationClass(Class configurationClass) { - Assert.notNull(configurationClass, "configurationClass must not be null"); - if (this.configuration != null) { - throw new IllegalStateException( - "setConfigurationClass() must be called before the internal " + - "Configuration instance has been created. Have you perhaps called " + - "getConfiguration() or doWithConfiguration() earlier than your call " + - "to setConfiguration()?"); - } - this.configurationClass = configurationClass; - return this.instance; - } - - /** - * Use the given {@link HibernateConfigurationCallback} instance to configure - * this {@code Builder}'s underlying Hibernate {@code Configuration} object. - *

The {@code HibernateConfigurationCallback} type may be parameterized to - * {@code org.hibernate.cfg.Configuration} (the default), or {@code - * org.hibernate.cfg.AnnotationConfiguration} if running a Hibernate version - * less than 3.6. Otherwise, may be parameterized to any custom {@code Configuration} - * class provided to {@link #setConfigurationClass} - * @throws Exception propagating any exception thrown during operations against - * the underlying {@code Configuration} object. {@code @Bean} methods should - * declare {@code throws Exception} when using this method, allowing the Spring - * container to deal with it and fail appropriately. - * @see #setConfigurationClass(Class) - */ - @SuppressWarnings("unchecked") - public This doWithConfiguration(HibernateConfigurationCallback callback) - throws Exception { - callback.configure((C)this.getConfiguration()); - return this.instance; - } - - /** - * Set the DataSource to be used by the SessionFactory. - * If set, this will override corresponding settings in Hibernate properties. - *

If this is set, the Hibernate settings should not define - * a connection provider to avoid meaningless double configuration. - *

If using HibernateTransactionManager as transaction strategy, consider - * proxying your target DataSource with a LazyConnectionDataSourceProxy. - * This defers fetching of an actual JDBC Connection until the first JDBC - * Statement gets executed, even within JDBC transactions (as performed by - * HibernateTransactionManager). Such lazy fetching is particularly beneficial - * for read-only operations, in particular if the chances of resolving the - * result in the second-level cache are high. - *

As JTA and transactional JNDI DataSources already provide lazy enlistment - * of JDBC Connections, LazyConnectionDataSourceProxy does not add value with - * JTA (i.e. Spring's JtaTransactionManager) as transaction strategy. - * @see #setUseTransactionAwareDataSource - * @see HibernateTransactionManager - * @see org.springframework.transaction.jta.JtaTransactionManager - * @see org.springframework.jdbc.datasource.LazyConnectionDataSourceProxy - */ - public This setDataSource(DataSource dataSource) { - this.dataSource = dataSource; - return this.instance; - } - - /** - * Return the DataSource to be used by the SessionFactory. - */ - public DataSource getDataSource() { - return this.dataSource; - } - - - /** - * Set the location of a single Hibernate XML config file, for example as - * classpath resource "classpath:hibernate.cfg.xml". - *

Note: Can be omitted when all necessary properties and mapping - * resources are specified locally via this bean. - * @see org.hibernate.cfg.Configuration#configure(java.net.URL) - */ - public void setConfigLocation(Resource configLocation) { - this.configLocations = new Resource[] {configLocation}; - } - - /** - * Return the Hibernate properties, if any. Mainly available for - * configuration through property paths that specify individual keys. - */ - public Properties getHibernateProperties() { - if (this.hibernateProperties == null) { - this.hibernateProperties = new Properties(); - } - return this.hibernateProperties; - } - - /** - * Set locations of cacheable Hibernate mapping files, for example as web app - * resource "/WEB-INF/mapping/example.hbm.xml". Supports any resource location - * via Spring's resource abstraction, as long as the resource can be resolved - * in the file system. - *

Can be used to add to mappings from a Hibernate XML config file, - * or to specify all mappings locally. - * @see org.hibernate.cfg.Configuration#addCacheableFile(java.io.File) - */ - public void setCacheableMappingLocations(Resource[] cacheableMappingLocations) { - this.cacheableMappingLocations = cacheableMappingLocations; - } - - - /** - * Set the locations of multiple Hibernate XML config files, for example as - * classpath resources "classpath:hibernate.cfg.xml,classpath:extension.cfg.xml". - *

Note: Can be omitted when all necessary properties and mapping - * resources are specified locally via this bean. - * @see org.hibernate.cfg.Configuration#configure(java.net.URL) - */ - public void setConfigLocations(Resource[] configLocations) { - this.configLocations = configLocations; - } - - /** - * Set the LobHandler to be used by the SessionFactory. - * Will be exposed at config time for UserType implementations. - * @see #getConfigTimeLobHandler - * @see org.hibernate.usertype.UserType - * @see org.springframework.orm.hibernate3.support.ClobStringType - * @see org.springframework.orm.hibernate3.support.BlobByteArrayType - * @see org.springframework.orm.hibernate3.support.BlobSerializableType - */ - public void setLobHandler(LobHandler lobHandler) { - this.lobHandler = lobHandler; - } - - /** - * Set the Hibernate RegionFactory to use for the SessionFactory. - * Allows for using a Spring-managed RegionFactory instance. - *

As of Hibernate 3.3, this is the preferred mechanism for configuring - * caches, superseding the {@link #setCacheProvider CacheProvider SPI}. - * For Hibernate 3.2 compatibility purposes, the accepted reference is of type - * Object: the actual type is org.hibernate.cache.RegionFactory. - *

Note: If this is set, the Hibernate settings should not define a - * cache provider to avoid meaningless double configuration. - * @see org.hibernate.cache.RegionFactory - */ - public This setCacheRegionFactory(Object cacheRegionFactory) { - this.cacheRegionFactory = cacheRegionFactory; - return instance; - } - - protected Object getCacheRegionFactory() { - return this.cacheRegionFactory; - } - - /** - * Set whether to expose a transaction-aware current Session from the - * SessionFactory's getCurrentSession() method, returning the - * Session that's associated with the current Spring-managed transaction, if any. - *

Default is "true", letting data access code work with the plain - * Hibernate SessionFactory and its getCurrentSession() method, - * while still being able to participate in current Spring-managed transactions: - * with any transaction management strategy, either local or JTA / EJB CMT, - * and any transaction synchronization mechanism, either Spring or JTA. - * Furthermore, getCurrentSession() will also seamlessly work with - * a request-scoped Session managed by OpenSessionInViewFilter/Interceptor. - *

Turn this flag off to expose the plain Hibernate SessionFactory with - * Hibernate's default getCurrentSession() behavior, supporting - * plain JTA synchronization only. Alternatively, simply override the - * corresponding Hibernate property "hibernate.current_session_context_class". - * @see SpringSessionContext - * @see org.hibernate.SessionFactory#getCurrentSession() - * @see org.springframework.transaction.jta.JtaTransactionManager - * @see HibernateTransactionManager - * @see org.springframework.orm.hibernate3.support.OpenSessionInViewFilter - * @see org.springframework.orm.hibernate3.support.OpenSessionInViewInterceptor - */ - public This setExposeTransactionAwareSessionFactory(boolean exposeTransactionAwareSessionFactory) { - this.exposeTransactionAwareSessionFactory = exposeTransactionAwareSessionFactory; - return this.instance; - } - - /** - * Return whether to expose a transaction-aware proxy for the SessionFactory. - */ - protected boolean isExposeTransactionAwareSessionFactory() { - return this.exposeTransactionAwareSessionFactory; - } - - /** - * Set whether to use a transaction-aware DataSource for the SessionFactory, - * i.e. whether to automatically wrap the passed-in DataSource with Spring's - * TransactionAwareDataSourceProxy. - *

Default is "false": SessionFactoryBuilder types are usually used with Spring's - * HibernateTransactionManager or JtaTransactionManager, both of which work nicely - * on a plain JDBC DataSource. Hibernate Sessions and their JDBC Connections are - * fully managed by the Hibernate/JTA transaction infrastructure in such a scenario. - *

If you switch this flag to "true", Spring's Hibernate access will be able to - * participate in JDBC-based transactions managed outside of Hibernate - * (for example, by Spring's DataSourceTransactionManager). This can be convenient - * if you need a different local transaction strategy for another O/R mapping tool, - * for example, but still want Hibernate access to join into those transactions. - *

A further benefit of this option is that plain Sessions opened directly - * via the SessionFactory, outside of Spring's Hibernate support, will still - * participate in active Spring-managed transactions. However, consider using - * Hibernate's getCurrentSession() method instead (see javadoc of - * "exposeTransactionAwareSessionFactory" property). - *

WARNING: When using a transaction-aware JDBC DataSource in combination - * with OpenSessionInViewFilter/Interceptor, whether participating in JTA or - * external JDBC-based transactions, it is strongly recommended to set Hibernate's - * Connection release mode to "after_transaction" or "after_statement", which - * guarantees proper Connection handling in such a scenario. In contrast to that, - * HibernateTransactionManager generally requires release mode "on_close". - *

Note: If you want to use Hibernate's Connection release mode "after_statement" - * with a DataSource specified on this SessionFactoryBuilder (for example, a - * JTA-aware DataSource fetched from JNDI), switch this setting to "true". - * Otherwise, the ConnectionProvider used underneath will vote against aggressive - * release and thus silently switch to release mode "after_transaction". - * @see #setDataSource - * @see #setExposeTransactionAwareSessionFactory - * @see org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy - * @see org.springframework.jdbc.datasource.DataSourceTransactionManager - * @see org.springframework.orm.hibernate3.support.OpenSessionInViewFilter - * @see org.springframework.orm.hibernate3.support.OpenSessionInViewInterceptor - * @see HibernateTransactionManager - * @see org.springframework.transaction.jta.JtaTransactionManager - */ - public This setUseTransactionAwareDataSource(boolean useTransactionAwareDataSource) { - this.useTransactionAwareDataSource = useTransactionAwareDataSource; - return instance; - } - - /** - * Return whether to use a transaction-aware DataSource for the SessionFactory. - */ - protected boolean isUseTransactionAwareDataSource() { - return this.useTransactionAwareDataSource; - } - - /** - * Set the JTA TransactionManager to be used for Hibernate's - * TransactionManagerLookup. Allows for using a Spring-managed - * JTA TransactionManager for Hibernate's cache synchronization. - *

Note: If this is set, the Hibernate settings should not define a - * transaction manager lookup to avoid meaningless double configuration. - * @see LocalTransactionManagerLookup - */ - public This setJtaTransactionManager(TransactionManager jtaTransactionManager) { - this.jtaTransactionManager = jtaTransactionManager; - return instance; - } - - /** - * Set whether to execute a schema update after SessionFactory initialization. - *

For details on how to make schema update scripts work, see the Hibernate - * documentation, as this class leverages the same schema update script support - * in org.hibernate.cfg.Configuration as Hibernate's own SchemaUpdate tool. - * @see org.hibernate.cfg.Configuration#generateSchemaUpdateScript - * @see org.hibernate.tool.hbm2ddl.SchemaUpdate - */ - public This setSchemaUpdate(boolean schemaUpdate) { - this.schemaUpdate = schemaUpdate; - return this.instance; - } - - /** - * Set the beanClassLoader for this instance. Not named {@code setBeanClassLoader} - * to allow subclasses to implement {@code BeanClassLoaderAware} without violating - * this method's signature. Any such implementation should simply delegate to this - * method. - * @see #getBeanClassLoader() - */ - public This setClassLoader(ClassLoader beanClassLoader) { - this.beanClassLoader = beanClassLoader; - return this.instance; - } - - /** - * @see #setClassLoader(ClassLoader) - */ - protected ClassLoader getBeanClassLoader() { - return this.beanClassLoader; - } - - /** - * Set Hibernate mapping resources to be found in the class path, - * like "example.hbm.xml" or "mypackage/example.hbm.xml". - * Analogous to mapping entries in a Hibernate XML config file. - * Alternative to the more generic setMappingLocations method. - *

Can be used to add to mappings from a Hibernate XML config file, - * or to specify all mappings locally. - * @see #setMappingLocations - * @see org.hibernate.cfg.Configuration#addResource - */ - public This setMappingResources(String[] mappingResources) { - this.mappingResources = mappingResources; - return instance; - } - - /** - * Set locations of jar files that contain Hibernate mapping resources, - * like "WEB-INF/lib/example.hbm.jar". - *

Can be used to add to mappings from a Hibernate XML config file, - * or to specify all mappings locally. - * @see org.hibernate.cfg.Configuration#addJar(java.io.File) - */ - public This setMappingJarLocations(Resource[] mappingJarLocations) { - this.mappingJarLocations = mappingJarLocations; - return instance; - } - - /** - * Set locations of directories that contain Hibernate mapping resources, - * like "WEB-INF/mappings". - *

Can be used to add to mappings from a Hibernate XML config file, - * or to specify all mappings locally. - * @see org.hibernate.cfg.Configuration#addDirectory(java.io.File) - */ - public This setMappingDirectoryLocations(Resource[] mappingDirectoryLocations) { - this.mappingDirectoryLocations = mappingDirectoryLocations; - return instance; - } - - /** - * Set locations of Hibernate mapping files, for example as classpath - * resource "classpath:example.hbm.xml". Supports any resource location - * via Spring's resource abstraction, for example relative paths like - * "WEB-INF/mappings/example.hbm.xml" when running in an application context. - *

Can be used to add to mappings from a Hibernate XML config file, - * or to specify all mappings locally. - * @see org.hibernate.cfg.Configuration#addInputStream - */ - public This setMappingLocations(Resource[] mappingLocations) { - this.mappingLocations = mappingLocations; - return instance; - } - - /** - * Set Hibernate properties, such as "hibernate.dialect". - *

Can be used to override values in a Hibernate XML config file, - * or to specify all necessary properties locally. - *

Note: Do not specify a transaction provider here when using - * Spring-driven transactions. It is also advisable to omit connection - * provider settings and use a Spring-set DataSource instead. - * @see #setDataSource - */ - public This setHibernateProperties(Properties hibernateProperties) { - this.hibernateProperties = hibernateProperties; - return instance; - } - - /** - * Set a Hibernate entity interceptor that allows to inspect and change - * property values before writing to and reading from the database. - * Will get applied to any new Session created by this factory. - *

Such an interceptor can either be set at the SessionFactory level, i.e. on - * SessionFactoryBuilder, or at the Session level, i.e. on HibernateTemplate, - * HibernateInterceptor, and HibernateTransactionManager. It's preferable to set - * it on SessionFactoryBuilder or HibernateTransactionManager to avoid repeated - * configuration and guarantee consistent behavior in transactions. - * @see HibernateTemplate#setEntityInterceptor - * @see HibernateInterceptor#setEntityInterceptor - * @see HibernateTransactionManager#setEntityInterceptor - * @see org.hibernate.cfg.Configuration#setInterceptor - */ - public This setEntityInterceptor(Interceptor entityInterceptor) { - this.entityInterceptor = entityInterceptor; - return instance; - } - - /** - * Set a Hibernate NamingStrategy for the SessionFactory, determining the - * physical column and table names given the info in the mapping document. - * @see org.hibernate.cfg.Configuration#setNamingStrategy - */ - public This setNamingStrategy(NamingStrategy namingStrategy) { - this.namingStrategy = namingStrategy; - return instance; - } - - /** - * Specify the cache strategies for entities (persistent classes or named entities). - * This configuration setting corresponds to the {@code } entry - * in the "hibernate.cfg.xml" configuration format. - *

For example: - *

-	 * {@code
-	 * 
-	 *   
-	 *     read-write
-	 *     read-only,myRegion
-	 *   
-	 * }
- * @param entityCacheStrategies properties that define entity cache strategies, - * with class names as keys and cache concurrency strategies as values - * @see org.hibernate.cfg.Configuration#setCacheConcurrencyStrategy(String, String) - */ - public This setEntityCacheStrategies(Properties entityCacheStrategies) { - this.entityCacheStrategies = entityCacheStrategies; - return instance; - } - - /** - * Specify the cache strategies for persistent collections (with specific roles). - * This configuration setting corresponds to the {@code } entry - * in the "hibernate.cfg.xml" configuration format. - *

For example: - *

-	 * {@code
-	 * 
-	 *   
-	 *     read-write
-	 *     read-only,myRegion
-	 *   
-	 * }
- * @param collectionCacheStrategies properties that define collection cache strategies, - * with collection roles as keys and cache concurrency strategies as values - * @see org.hibernate.cfg.Configuration#setCollectionCacheConcurrencyStrategy(String, String) - */ - public This setCollectionCacheStrategies(Properties collectionCacheStrategies) { - this.collectionCacheStrategies = collectionCacheStrategies; - return instance; - } - - /** - * Specify the Hibernate event listeners to register, with listener types - * as keys and listener objects as values. Instead of a single listener object, - * you can also pass in a list or set of listeners objects as value. - *

See the Hibernate documentation for further details on listener types - * and associated listener interfaces. - * @param eventListeners Map with listener type Strings as keys and - * listener objects as values - * @see org.hibernate.cfg.Configuration#setListener(String, Object) - */ - public This setEventListeners(Map eventListeners) { - this.eventListeners = eventListeners; - return this.instance; - } - - /** - * Specify the Hibernate FilterDefinitions to register with the SessionFactory. - * This is an alternative to specifying {@code } elements in - * Hibernate mapping files. - *

Typically, the passed-in FilterDefinition objects will have been defined - * as Spring FilterDefinitionFactoryBeans, probably as inner beans within the - * LocalSessionFactoryBean definition. - * @see FilterDefinitionFactoryBean - * @see org.hibernate.cfg.Configuration#addFilterDefinition - */ - public This setFilterDefinitions(FilterDefinition[] filterDefinitions) { - this.filterDefinitions = filterDefinitions; - return this.instance; - } - - /** - * Specify the Hibernate type definitions to register with the SessionFactory, - * as Spring TypeDefinitionBean instances. This is an alternative to specifying - * {@code } elements in Hibernate mapping files. - *

Unfortunately, Hibernate itself does not define a complete object that - * represents a type definition, hence the need for Spring's TypeDefinitionBean. - * @see TypeDefinitionBean - * @see org.hibernate.cfg.Mappings#addTypeDef(String, String, java.util.Properties) - */ - public This setTypeDefinitions(TypeDefinitionBean[] typeDefinitions) { - this.typeDefinitions = typeDefinitions; - return this.instance; - } - - /** - * Return the DataSource for the currently configured Hibernate SessionFactory, - * to be used by LocalDataSourceConnectionProvoder. - *

This instance will be set before initialization of the corresponding - * SessionFactory, and reset immediately afterwards. It is thus only available - * during configuration. - * @see #setDataSource - * @see LocalDataSourceConnectionProvider - */ - public static DataSource getConfigTimeDataSource() { - return configTimeDataSourceHolder.get(); - } - - /** - * Return the JTA TransactionManager for the currently configured Hibernate - * SessionFactory, to be used by LocalTransactionManagerLookup. - *

This instance will be set before initialization of the corresponding - * SessionFactory, and reset immediately afterwards. It is thus only available - * during configuration. - * @see #setJtaTransactionManager - * @see LocalTransactionManagerLookup - */ - public static TransactionManager getConfigTimeTransactionManager() { - return configTimeTransactionManagerHolder.get(); - } - - /** - * Return the RegionFactory for the currently configured Hibernate SessionFactory, - * to be used by LocalRegionFactoryProxy. - *

This instance will be set before initialization of the corresponding - * SessionFactory, and reset immediately afterwards. It is thus only available - * during configuration. - * @see #setCacheRegionFactory - */ - static Object getConfigTimeRegionFactory() { - return configTimeRegionFactoryHolder.get(); - } - - /** - * Return the LobHandler for the currently configured Hibernate SessionFactory, - * to be used by UserType implementations like ClobStringType. - *

This instance will be set before initialization of the corresponding - * SessionFactory, and reset immediately afterwards. It is thus only available - * during configuration. - * @see #setLobHandler - * @see org.springframework.orm.hibernate3.support.ClobStringType - * @see org.springframework.orm.hibernate3.support.BlobByteArrayType - * @see org.springframework.orm.hibernate3.support.BlobSerializableType - */ - public static LobHandler getConfigTimeLobHandler() { - return configTimeLobHandlerHolder.get(); - } - -} diff --git a/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/SessionFactoryUtils.java b/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/SessionFactoryUtils.java index 2cacab471e..ab6042cc20 100644 --- a/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/SessionFactoryUtils.java +++ b/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/SessionFactoryUtils.java @@ -212,7 +212,7 @@ public abstract class SessionFactoryUtils { *

Supports setting a Session-level Hibernate entity interceptor that allows * to inspect and change property values before writing to and reading from the * database. Such an interceptor can also be set at the SessionFactory level - * (i.e. on SessionFactoryBuilder), on HibernateTransactionManager, or on + * (i.e. on LocalSessionFactoryBean), on HibernateTransactionManager, or on * HibernateInterceptor/HibernateTemplate. * @param sessionFactory Hibernate SessionFactory to create the session with * @param entityInterceptor Hibernate entity interceptor, or null if none @@ -221,7 +221,7 @@ public abstract class SessionFactoryUtils { * when actually registering a transaction synchronization) * @return the Hibernate Session * @throws DataAccessResourceFailureException if the Session couldn't be created - * @see SessionFactoryBuilder#setEntityInterceptor + * @see LocalSessionFactoryBean#setEntityInterceptor * @see HibernateInterceptor#setEntityInterceptor * @see HibernateTemplate#setEntityInterceptor */ diff --git a/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/SpringSessionContext.java b/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/SpringSessionContext.java index 77695e7ea4..e914c19fe4 100644 --- a/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/SpringSessionContext.java +++ b/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/SpringSessionContext.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2011 the original author or authors. + * Copyright 2002-2008 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -26,7 +26,7 @@ import org.hibernate.engine.SessionFactoryImplementor; * that delegates to Spring's SessionFactoryUtils for providing a * Spring-managed current Session. * - *

Used by Spring's {@link SessionFactoryBuilder} when told to expose a + *

Used by Spring's {@link LocalSessionFactoryBean} when told to expose a * transaction-aware SessionFactory. This is the default as of Spring 2.5. * *

This CurrentSessionContext implementation can also be specified in custom @@ -36,9 +36,8 @@ import org.hibernate.engine.SessionFactoryImplementor; * @author Juergen Hoeller * @since 2.0 * @see SessionFactoryUtils#doGetSession - * @see SessionFactoryBuilder#setExposeTransactionAwareSessionFactory + * @see LocalSessionFactoryBean#setExposeTransactionAwareSessionFactory */ -@SuppressWarnings("serial") public class SpringSessionContext implements CurrentSessionContext { private final SessionFactoryImplementor sessionFactory; diff --git a/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/TransactionAwareDataSourceConnectionProvider.java b/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/TransactionAwareDataSourceConnectionProvider.java index a9425c1e78..e8233d2c1e 100644 --- a/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/TransactionAwareDataSourceConnectionProvider.java +++ b/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/TransactionAwareDataSourceConnectionProvider.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2011 the original author or authors. + * Copyright 2002-2007 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -23,11 +23,11 @@ import org.springframework.jdbc.datasource.TransactionAwareDataSourceProxy; /** * Subclass of LocalDataSourceConnectionProvider that returns a * transaction-aware proxy for the exposed DataSource. Used if - * SessionFactoryBuilder's "useTransactionAwareDataSource" flag is on. + * LocalSessionFactoryBean's "useTransactionAwareDataSource" flag is on. * * @author Juergen Hoeller * @since 1.2 - * @see SessionFactoryBuilder#setUseTransactionAwareDataSource + * @see LocalSessionFactoryBean#setUseTransactionAwareDataSource */ public class TransactionAwareDataSourceConnectionProvider extends LocalDataSourceConnectionProvider { diff --git a/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/TypeDefinitionBean.java b/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/TypeDefinitionBean.java index 406c5a70f1..68140afdf8 100644 --- a/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/TypeDefinitionBean.java +++ b/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/TypeDefinitionBean.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2011 the original author or authors. + * Copyright 2002-2005 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -28,20 +28,19 @@ import org.springframework.beans.factory.InitializingBean; * definition, as list element for the "typeDefinitions" bean property. * For example: * - *

- * {@code
- * 
+ * 
+ * <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
  *   ...
- *   
- *     
- *       
- *         
- *         
- *       
- *     
- *   
+ *   <property name="typeDefinitions">
+ *     <list>
+ *       <bean class="org.springframework.orm.hibernate3.TypeDefinitionBean">
+ *         <property name="typeName" value="myType"/>
+ *         <property name="typeClass" value="mypackage.MyTypeClass"/>
+ *       </bean>
+ *     </list>
+ *   </property>
  *   ...
- * }
+ * </bean>
* * Alternatively, specify a bean id (or name) attribute for the inner bean, * instead of the "typeName" property. diff --git a/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/annotation/AnnotationSessionFactoryBean.java b/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/annotation/AnnotationSessionFactoryBean.java index 3ecc5c9423..a4649337ac 100644 --- a/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/annotation/AnnotationSessionFactoryBean.java +++ b/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/annotation/AnnotationSessionFactoryBean.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2011 the original author or authors. + * Copyright 2002-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -16,169 +16,233 @@ package org.springframework.orm.hibernate3.annotation; +import java.io.IOException; +import javax.persistence.Embeddable; +import javax.persistence.Entity; +import javax.persistence.MappedSuperclass; + import org.hibernate.HibernateException; -import org.hibernate.SessionFactory; +import org.hibernate.MappingException; +import org.hibernate.cfg.AnnotationConfiguration; +import org.hibernate.cfg.Configuration; + import org.springframework.context.ResourceLoaderAware; +import org.springframework.core.io.Resource; import org.springframework.core.io.ResourceLoader; +import org.springframework.core.io.support.PathMatchingResourcePatternResolver; +import org.springframework.core.io.support.ResourcePatternResolver; import org.springframework.core.io.support.ResourcePatternUtils; -import org.springframework.dao.DataAccessException; -import org.springframework.jdbc.support.SQLExceptionTranslator; -import org.springframework.orm.hibernate3.HibernateExceptionTranslator; -import org.springframework.orm.hibernate3.SessionFactoryBeanOperations; -import org.springframework.orm.hibernate3.SessionFactoryBeanDelegate; -import org.springframework.orm.hibernate3.SessionFactoryBuilderSupport; +import org.springframework.core.type.classreading.CachingMetadataReaderFactory; +import org.springframework.core.type.classreading.MetadataReader; +import org.springframework.core.type.classreading.MetadataReaderFactory; +import org.springframework.core.type.filter.AnnotationTypeFilter; +import org.springframework.core.type.filter.TypeFilter; +import org.springframework.orm.hibernate3.LocalSessionFactoryBean; +import org.springframework.util.ClassUtils; /** - * Subclass of {@link AnnotationSessionFactoryBuilder} adhering to Spring's - * {@link org.springframework.beans.factory.FactoryBean FactoryBean} contract, - * making it suitable for use in XML configuration. + * Subclass of Spring's standard LocalSessionFactoryBean for Hibernate, + * supporting JDK 1.5+ annotation metadata for mappings. * - *

A typical {@code AnnotationSessionFactoryBean} bean definition: + *

Note: This class requires Hibernate 3.2 or later, with the + * Java Persistence API and the Hibernate Annotations add-on present. + * + *

Example for an AnnotationSessionFactoryBean bean definition: * *

- * {@code
- * 
- *   
- *   
- *     
- *       test.package.Foo
- *       test.package.Bar
- *     
- *   
- * }
+ * <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"> + * <property name="dataSource" ref="dataSource"/> + * <property name="annotatedClasses"> + * <list> + * <value>test.package.Foo</value> + * <value>test.package.Bar</value> + * </list> + * </property> + * </bean> * * Or when using classpath scanning for autodetection of entity classes: * *
- * {@code
- * 
- *   
- *   
- * }
- * - *

Implements the - * {@link org.springframework.dao.support.PersistenceExceptionTranslator - * PersistenceExceptionTranslator} interface, as autodetected by Spring's {@link - * org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor - * PersistenceExceptionTranslationPostProcessor}, for AOP-based translation of - * native Hibernate exceptions to Spring's {@link DataAccessException} hierarchy. - * Hence, the presence of an {@code AnnotationSessionFactoryBean} automatically - * enables a {@code PersistenceExceptionTranslationPostProcessor} to translate - * Hibernate exceptions. + * <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"> + * <property name="dataSource" ref="dataSource"/> + * <property name="packagesToScan" value="test.package"/> + * </bean> * * @author Juergen Hoeller - * @author Chris Beams * @since 1.2.2 - * @see SessionFactoryBuilderSupport - * @see AnnotationSessionFactoryBuilder + * @see #setDataSource + * @see #setHibernateProperties + * @see #setAnnotatedClasses + * @see #setAnnotatedPackages */ -public class AnnotationSessionFactoryBean extends AnnotationSessionFactoryBuilder - implements SessionFactoryBeanOperations, ResourceLoaderAware { +public class AnnotationSessionFactoryBean extends LocalSessionFactoryBean implements ResourceLoaderAware { - private final SessionFactoryBeanDelegate delegate = new SessionFactoryBeanDelegate(this); + private static final String RESOURCE_PATTERN = "/**/*.class"; - @Deprecated - public void setCacheProvider(org.hibernate.cache.CacheProvider cacheProvider) { - delegate.setCacheProvider(cacheProvider); + + private Class[] annotatedClasses; + + private String[] annotatedPackages; + + private String[] packagesToScan; + + private TypeFilter[] entityTypeFilters = new TypeFilter[] { + new AnnotationTypeFilter(Entity.class, false), + new AnnotationTypeFilter(Embeddable.class, false), + new AnnotationTypeFilter(MappedSuperclass.class, false), + new AnnotationTypeFilter(org.hibernate.annotations.Entity.class, false)}; + + private ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver(); + + + public AnnotationSessionFactoryBean() { + setConfigurationClass(AnnotationConfiguration.class); } - @Override - protected void preBuildSessionFactory() { - delegate.preBuildSessionFactory(); - } @Override - protected void postBuildSessionFactory() { - delegate.postBuildSessionFactory(); + public void setConfigurationClass(Class configurationClass) { + if (configurationClass == null || !AnnotationConfiguration.class.isAssignableFrom(configurationClass)) { + throw new IllegalArgumentException( + "AnnotationSessionFactoryBean only supports AnnotationConfiguration or subclasses"); + } + super.setConfigurationClass(configurationClass); + } + + /** + * Specify annotated classes, for which mappings will be read from + * class-level JDK 1.5+ annotation metadata. + * @see org.hibernate.cfg.AnnotationConfiguration#addAnnotatedClass(Class) + */ + public void setAnnotatedClasses(Class[] annotatedClasses) { + this.annotatedClasses = annotatedClasses; + } + + /** + * Specify the names of annotated packages, for which package-level + * JDK 1.5+ annotation metadata will be read. + * @see org.hibernate.cfg.AnnotationConfiguration#addPackage(String) + */ + public void setAnnotatedPackages(String[] annotatedPackages) { + this.annotatedPackages = annotatedPackages; + } + + /** + * Set whether to use Spring-based scanning for entity classes in the classpath + * instead of listing annotated classes explicitly. + *

Default is none. Specify packages to search for autodetection of your entity + * classes in the classpath. This is analogous to Spring's component-scan feature + * ({@link org.springframework.context.annotation.ClassPathBeanDefinitionScanner}). + */ + public void setPackagesToScan(String[] packagesToScan) { + this.packagesToScan = packagesToScan; + } + + /** + * Specify custom type filters for Spring-based scanning for entity classes. + *

Default is to search all specified packages for classes annotated with + * @javax.persistence.Entity, @javax.persistence.Embeddable + * or @javax.persistence.MappedSuperclass, as well as for + * Hibernate's special @org.hibernate.annotations.Entity. + * @see #setPackagesToScan + */ + public void setEntityTypeFilters(TypeFilter[] entityTypeFilters) { + this.entityTypeFilters = entityTypeFilters; } public void setResourceLoader(ResourceLoader resourceLoader) { - this.setResourcePatternResolver(ResourcePatternUtils.getResourcePatternResolver(resourceLoader)); + this.resourcePatternResolver = ResourcePatternUtils.getResourcePatternResolver(resourceLoader); } - public void destroy() throws HibernateException { - delegate.destroy(); - } - public SessionFactory getObject() { - return delegate.getObject(); - } - - public Class getObjectType() { - return delegate.getObjectType(); - } - - public void setBeanClassLoader(ClassLoader beanClassLoader) { - delegate.setBeanClassLoader(beanClassLoader); - } - - public boolean isSingleton() { - return delegate.isSingleton(); - } - - public void afterPropertiesSet() throws Exception { - delegate.afterPropertiesSet(); - } - - public DataAccessException translateExceptionIfPossible(RuntimeException ex) { - return delegate.translateExceptionIfPossible(ex); - } - - public void setJdbcExceptionTranslator( - SQLExceptionTranslator jdbcExceptionTranslator) { - delegate.setJdbcExceptionTranslator(jdbcExceptionTranslator); - } - - public void setPersistenceExceptionTranslator( - HibernateExceptionTranslator hibernateExceptionTranslator) { - delegate.setPersistenceExceptionTranslator(hibernateExceptionTranslator); + /** + * Reads metadata from annotated classes and packages into the + * AnnotationConfiguration instance. + */ + @Override + protected void postProcessMappings(Configuration config) throws HibernateException { + AnnotationConfiguration annConfig = (AnnotationConfiguration) config; + if (this.annotatedClasses != null) { + for (Class annotatedClass : this.annotatedClasses) { + annConfig.addAnnotatedClass(annotatedClass); + } + } + if (this.annotatedPackages != null) { + for (String annotatedPackage : this.annotatedPackages) { + annConfig.addPackage(annotatedPackage); + } + } + scanPackages(annConfig); } /** - * @deprecated as of Spring 3.1 in favor of {@link #scanPackages()} which - * can access the internal {@code AnnotationConfiguration} instance via - * {@link #getConfiguration()}. + * Perform Spring-based scanning for entity classes. + * @see #setPackagesToScan */ - @Deprecated - protected void scanPackages(org.hibernate.cfg.AnnotationConfiguration config) { - this.scanPackages(); + protected void scanPackages(AnnotationConfiguration config) { + if (this.packagesToScan != null) { + try { + for (String pkg : this.packagesToScan) { + String pattern = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + + ClassUtils.convertClassNameToResourcePath(pkg) + RESOURCE_PATTERN; + Resource[] resources = this.resourcePatternResolver.getResources(pattern); + MetadataReaderFactory readerFactory = new CachingMetadataReaderFactory(this.resourcePatternResolver); + for (Resource resource : resources) { + if (resource.isReadable()) { + MetadataReader reader = readerFactory.getMetadataReader(resource); + String className = reader.getClassMetadata().getClassName(); + if (matchesFilter(reader, readerFactory)) { + config.addAnnotatedClass(this.resourcePatternResolver.getClassLoader().loadClass(className)); + } + } + } + } + } + catch (IOException ex) { + throw new MappingException("Failed to scan classpath for unlisted classes", ex); + } + catch (ClassNotFoundException ex) { + throw new MappingException("Failed to load annotated classes from classpath", ex); + } + } } /** - * @deprecated as of Spring 3.1 in favor of {@link #newSessionFactory()} which - * can access the internal {@code Configuration} instance via {@link #getConfiguration()}. + * Check whether any of the configured entity type filters matches + * the current class descriptor contained in the metadata reader. */ - @Deprecated - protected SessionFactory newSessionFactory(org.hibernate.cfg.Configuration config) throws HibernateException { - return this.newSessionFactory(); + private boolean matchesFilter(MetadataReader reader, MetadataReaderFactory readerFactory) throws IOException { + if (this.entityTypeFilters != null) { + for (TypeFilter filter : this.entityTypeFilters) { + if (filter.match(reader, readerFactory)) { + return true; + } + } + } + return false; + } + + + /** + * This default implementation delegates to {@link #postProcessAnnotationConfiguration}. + */ + @Override + protected void postProcessConfiguration(Configuration config) throws HibernateException { + postProcessAnnotationConfiguration((AnnotationConfiguration) config); } /** - * @deprecated as of Spring 3.1 in favor of {@link #postProcessMappings()} which - * can access the internal {@code Configuration} instance via {@link #getConfiguration()}. + * To be implemented by subclasses which want to to perform custom + * post-processing of the AnnotationConfiguration object after this + * FactoryBean performed its default initialization. + *

Note: As of Hibernate 3.6, AnnotationConfiguration's features + * have been rolled into Configuration itself. Simply overriding + * {@link #postProcessConfiguration(org.hibernate.cfg.Configuration)} + * becomes an option as well then. + * @param config the current AnnotationConfiguration object + * @throws HibernateException in case of Hibernate initialization errors */ - @Deprecated - protected void postProcessMappings(org.hibernate.cfg.Configuration config) throws HibernateException { - this.postProcessMappings(); - } - - /** - * @deprecated as of Spring 3.1 in favor of {@link #postProcessConfiguration()} which - * can access the internal {@code Configuration} instance via {@link #getConfiguration()}. - */ - @Deprecated - protected void postProcessConfiguration(org.hibernate.cfg.Configuration config) throws HibernateException { - this.postProcessConfiguration(); - } - - /** - * @deprecated as of Spring 3.1 in favor of {@link #postProcessAnnotationConfiguration()} - * which can access the internal {@code AnnotationConfiguration} instance via - * {@link #getConfiguration()}. - */ - @Deprecated - protected void postProcessAnnotationConfiguration(org.hibernate.cfg.AnnotationConfiguration config) throws HibernateException { - this.postProcessAnnotationConfiguration(); + protected void postProcessAnnotationConfiguration(AnnotationConfiguration config) throws HibernateException { } } diff --git a/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/annotation/AnnotationSessionFactoryBuilder.java b/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/annotation/AnnotationSessionFactoryBuilder.java deleted file mode 100644 index af291fb2d8..0000000000 --- a/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/annotation/AnnotationSessionFactoryBuilder.java +++ /dev/null @@ -1,300 +0,0 @@ -/* - * Copyright 2002-2011 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.orm.hibernate3.annotation; - -import java.io.IOException; -import java.lang.reflect.Method; - -import javax.persistence.Embeddable; -import javax.persistence.Entity; -import javax.persistence.MappedSuperclass; -import javax.sql.DataSource; - -import org.hibernate.HibernateException; -import org.hibernate.MappingException; -import org.hibernate.cfg.AnnotationConfiguration; -import org.hibernate.cfg.Configuration; -import org.springframework.context.annotation.Bean; -import org.springframework.core.io.Resource; -import org.springframework.core.io.support.PathMatchingResourcePatternResolver; -import org.springframework.core.io.support.ResourcePatternResolver; -import org.springframework.core.type.classreading.CachingMetadataReaderFactory; -import org.springframework.core.type.classreading.MetadataReader; -import org.springframework.core.type.classreading.MetadataReaderFactory; -import org.springframework.core.type.filter.AnnotationTypeFilter; -import org.springframework.core.type.filter.TypeFilter; -import org.springframework.orm.hibernate3.SessionFactoryBuilderSupport; -import org.springframework.util.ClassUtils; - -/** - * Hibernate {@link AnnotationConfiguration} builder suitable for use within Spring - * {@link org.springframework.context.annotation.Configuration @Configuration} - * class {@link Bean @Bean} methods. For complete details on features, see the - * JavaDoc for the {@link SessionFactoryBuilderSupport} superclass. For use in - * Spring XML configuration, see the {@link AnnotationSessionFactoryBean} subclass. - * - *

As noted in {@code SessionFactoryBuilderSupport} JavaDoc, this class requires - * Hibernate 3.2 or later; it additionally requires that the Java Persistence API - * and Hibernate Annotations add-ons are present. - * - *

Setter methods return the builder instance in order to facilitate - * a concise and convenient method-chaining style. For example: - *

- * {@code @Configuration}
- * public class DataConfig {
- *     {@code @Bean}
- *     public SessionFactory sessionFactory() {
- *         return new AnnotationSessionFactoryBuilder()
- *             .setDataSource(dataSource())
- *             .setPackagesToScan("com.myco"})
- *             .buildSessionFactory();
- *     }
- * }
- * 
- * - *

Most Hibernate configuration operations can be performed directly against - * this API; however you may also access access and configure the underlying - * {@code AnnotationConfiguration} object by using the {@link #doWithConfiguration} - * method and providing a {@code HibernateConfigurationCallback} as follows: - *

- * SessionFactory sessionFactory =
- *     new AnnotationSessionFactoryBuilder()
- *         // ...
- *         .doWithConfiguration(new HibernateConfigurationCallback<AnnotationConfiguration>() {
- *             public void configure(AnnotationConfiguration cfg) {
- *                 cfg.addAnnotatedClass(Foo.class);
- *             }
- *          })
- *         .buildSessionFactory();
- * 
- * - * @author Juergen Hoeller - * @author Chris Beams - * @since 3.1 - * @see org.springframework.orm.hibernate3.SessionFactoryBuilderSupport - * @see org.springframework.orm.hibernate3.SessionFactoryBuilder - * @see AnnotationSessionFactoryBean - */ -public class AnnotationSessionFactoryBuilder extends SessionFactoryBuilderSupport { - - /** Hibernate 3.6 consolidates Configuration and AnnotationConfiguration operations. */ - private static final boolean hibernate36Present = ClassUtils.hasMethod(Configuration.class, "addAnnotatedClass", Class.class); - - private static final String RESOURCE_PATTERN = "/**/*.class"; - - private Class[] annotatedClasses; - - private String[] annotatedPackages; - - private String[] packagesToScan; - - private ResourcePatternResolver resourcePatternResolver = new PathMatchingResourcePatternResolver(); - - private TypeFilter[] entityTypeFilters = new TypeFilter[] { - new AnnotationTypeFilter(Entity.class, false), - new AnnotationTypeFilter(Embeddable.class, false), - new AnnotationTypeFilter(MappedSuperclass.class, false), - new AnnotationTypeFilter(org.hibernate.annotations.Entity.class, false)}; - - - /** - * Construct a new {@code AnnotationSessionFactoryBuilder} - */ - public AnnotationSessionFactoryBuilder() { - super(); - } - - /** - * Construct a new {@code AnnotationSessionFactoryBuilder} with the given - * Spring-managed {@code DataSource} instance. - * @see #setDataSource - */ - public AnnotationSessionFactoryBuilder(DataSource dataSource) { - super(dataSource); - } - - /** - * {@inheritDoc} - *

This implementation returns {@link org.hibernate.cfg.Configuration} if - * Hibernate 3.6 or greater is available on the runtime classpath, otherwise - * {@link org.hibernate.cfg.AnnotationConfiguration}. This accommodates - * the consolidation of these two types and deprecation of the latter in - * Hibernate 3.6. - * @see #doWithConfiguration - */ - protected Class getDefaultConfigurationClass() { - return hibernate36Present ? Configuration.class : AnnotationConfiguration.class; - } - - /** - * Set whether to use Spring-based scanning for entity classes in the classpath - * instead of listing annotated classes explicitly. - *

Default is none. Specify packages to search for autodetection of your entity - * classes in the classpath. This is analogous to Spring's component-scan feature - * ({@link org.springframework.context.annotation.ClassPathBeanDefinitionScanner}). - */ - public AnnotationSessionFactoryBuilder setPackagesToScan(String... packagesToScan) { - this.packagesToScan = packagesToScan; - return this; - } - - /** - * Specify annotated classes, for which mappings will be read from - * class-level JDK 1.5+ annotation metadata. - * @see org.hibernate.cfg.AnnotationConfiguration#addAnnotatedClass - */ - public AnnotationSessionFactoryBuilder setAnnotatedClasses(Class... annotatedClasses) { - this.annotatedClasses = annotatedClasses; - return this; - } - - /** - * Specify the names of annotated packages, for which package-level - * JDK 1.5+ annotation metadata will be read. - * @see org.hibernate.cfg.AnnotationConfiguration#addPackage - */ - public AnnotationSessionFactoryBuilder setAnnotatedPackages(String[] annotatedPackages) { - this.annotatedPackages = annotatedPackages; - return this; - } - - /** - * Specify custom type filters for Spring-based scanning for entity classes. - *

Default is to search all specified packages for classes annotated with - * @javax.persistence.Entity, @javax.persistence.Embeddable - * or @javax.persistence.MappedSuperclass, as well as for - * Hibernate's special @org.hibernate.annotations.Entity. - * @see #setPackagesToScan - */ - public AnnotationSessionFactoryBuilder setEntityTypeFilters(TypeFilter[] entityTypeFilters) { - this.entityTypeFilters = entityTypeFilters; - return this; - } - - public void setResourcePatternResolver(ResourcePatternResolver resourcePatternResolver) { - this.resourcePatternResolver = resourcePatternResolver; - } - - /** - * Perform Spring-based scanning for entity classes. - * @see #setPackagesToScan - */ - protected void scanPackages() { - if (this.packagesToScan != null) { - try { - for (String pkg : this.packagesToScan) { - String pattern = ResourcePatternResolver.CLASSPATH_ALL_URL_PREFIX + - ClassUtils.convertClassNameToResourcePath(pkg) + RESOURCE_PATTERN; - Resource[] resources = this.resourcePatternResolver.getResources(pattern); - MetadataReaderFactory readerFactory = new CachingMetadataReaderFactory(this.resourcePatternResolver); - for (Resource resource : resources) { - if (resource.isReadable()) { - MetadataReader reader = readerFactory.getMetadataReader(resource); - String className = reader.getClassMetadata().getClassName(); - if (matchesFilter(reader, readerFactory)) { - Class annotatedClass = this.resourcePatternResolver.getClassLoader().loadClass(className); - invokeConfigurationMethod("addAnnotatedClass", Class.class, annotatedClass); - } - } - } - } - } - catch (IOException ex) { - throw new MappingException("Failed to scan classpath for unlisted classes", ex); - } - catch (ClassNotFoundException ex) { - throw new MappingException("Failed to load annotated classes from classpath", ex); - } - } - } - - /** - * Check whether any of the configured entity type filters matches - * the current class descriptor contained in the metadata reader. - */ - private boolean matchesFilter(MetadataReader reader, MetadataReaderFactory readerFactory) throws IOException { - if (this.entityTypeFilters != null) { - for (TypeFilter filter : this.entityTypeFilters) { - if (filter.match(reader, readerFactory)) { - return true; - } - } - } - return false; - } - - /** - * Reads metadata from annotated classes and packages into the - * AnnotationConfiguration instance. - */ - @Override - protected void postProcessMappings() throws HibernateException { - // org.hibernate.cfg.Configuration cfg = getConfiguration(); - if (this.annotatedClasses != null) { - for (Class annotatedClass : this.annotatedClasses) { - invokeConfigurationMethod("addAnnotatedClass", Class.class, annotatedClass); - } - } - if (this.annotatedPackages != null) { - for (String annotatedPackage : this.annotatedPackages) { - invokeConfigurationMethod("addPackage", String.class, annotatedPackage); - } - } - scanPackages(); - } - - /** - * Delegates to {@link #postProcessAnnotationConfiguration}. - */ - @Override - protected void postProcessConfiguration() throws HibernateException { - postProcessAnnotationConfiguration(); - } - - /** - * To be implemented by subclasses which want to to perform custom - * post-processing of the AnnotationConfiguration object after this - * FactoryBean performed its default initialization. - *

Note: As of Hibernate 3.6, AnnotationConfiguration's features - * have been rolled into Configuration itself. Simply overriding - * {@link #postProcessConfiguration(org.hibernate.cfg.Configuration)} - * becomes an option as well then. - * @param config the current AnnotationConfiguration object - * @throws HibernateException in case of Hibernate initialization errors - */ - protected void postProcessAnnotationConfiguration() throws HibernateException { - } - - /** - * Reflectively invoke the given method against the underlying Configuration - * instance. In order to support the consolidation of Hibernate's - * AnnotationConfiguration into Configuration in Hibernate 3.6 while continuing - * to to compile against Hibernate 3.3.x, we must reflectively invoke in order - * to avoid compilation failure. - */ - private void invokeConfigurationMethod(String methodName, Class parameterType, T parameter) { - org.hibernate.cfg.Configuration cfg = getConfiguration(); - try { - Method m = cfg.getClass().getMethod(methodName, parameterType); - m.invoke(cfg, parameter); - } catch (Exception ex) { - throw new IllegalStateException(String.format("Hibernate Configuration class [%s] does not support the '%s(%s)' method.", - cfg.getClass().getSimpleName(), methodName, parameterType.getSimpleName())); - } - } - -} diff --git a/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/support/AbstractLobType.java b/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/support/AbstractLobType.java index 3c8fa4ac54..5ab3c68bbb 100644 --- a/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/support/AbstractLobType.java +++ b/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/support/AbstractLobType.java @@ -22,6 +22,7 @@ import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; +import javax.transaction.Status; import javax.transaction.TransactionManager; import org.apache.commons.logging.Log; @@ -29,18 +30,23 @@ import org.apache.commons.logging.LogFactory; import org.hibernate.HibernateException; import org.hibernate.usertype.UserType; import org.hibernate.util.EqualsHelper; + +import org.springframework.dao.DataAccessResourceFailureException; +import org.springframework.jdbc.support.lob.JtaLobCreatorSynchronization; import org.springframework.jdbc.support.lob.LobCreator; -import org.springframework.jdbc.support.lob.LobCreatorUtils; import org.springframework.jdbc.support.lob.LobHandler; -import org.springframework.orm.hibernate3.SessionFactoryBuilderSupport; +import org.springframework.jdbc.support.lob.SpringLobCreatorSynchronization; +import org.springframework.jdbc.support.lob.LobCreatorUtils; +import org.springframework.orm.hibernate3.LocalSessionFactoryBean; +import org.springframework.transaction.support.TransactionSynchronizationManager; /** * Abstract base class for Hibernate UserType implementations that map to LOBs. - * Retrieves the LobHandler to use from SessionFactoryBuilder at config time. + * Retrieves the LobHandler to use from LocalSessionFactoryBean at config time. * *

For writing LOBs, either an active Spring transaction synchronization * or an active JTA transaction (with "jtaTransactionManager" specified on - * SessionFactoryBuilder or a Hibernate TransactionManagerLookup configured + * LocalSessionFactoryBean or a Hibernate TransactionManagerLookup configured * through the corresponding Hibernate property) is required. * *

Offers template methods for setting parameters and getting result values, @@ -50,8 +56,8 @@ import org.springframework.orm.hibernate3.SessionFactoryBuilderSupport; * @since 1.2 * @see org.springframework.jdbc.support.lob.LobHandler * @see org.springframework.jdbc.support.lob.LobCreator - * @see org.springframework.orm.hibernate3.SessionFactoryBuilder#setLobHandler - * @see org.springframework.orm.hibernate3.SessionFactoryBuilder#setJtaTransactionManager + * @see org.springframework.orm.hibernate3.LocalSessionFactoryBean#setLobHandler + * @see org.springframework.orm.hibernate3.LocalSessionFactoryBean#setJtaTransactionManager */ public abstract class AbstractLobType implements UserType { @@ -64,13 +70,13 @@ public abstract class AbstractLobType implements UserType { /** * Constructor used by Hibernate: fetches config-time LobHandler and - * config-time JTA TransactionManager from the SessionFactory builder. - * @see org.springframework.orm.hibernate3.SessionFactoryBuilderSupport#getConfigTimeLobHandler - * @see org.springframework.orm.hibernate3.SessionFactoryBuilderSupport#getConfigTimeTransactionManager + * config-time JTA TransactionManager from LocalSessionFactoryBean. + * @see org.springframework.orm.hibernate3.LocalSessionFactoryBean#getConfigTimeLobHandler + * @see org.springframework.orm.hibernate3.LocalSessionFactoryBean#getConfigTimeTransactionManager */ protected AbstractLobType() { - this(SessionFactoryBuilderSupport.getConfigTimeLobHandler(), - SessionFactoryBuilderSupport.getConfigTimeTransactionManager()); + this(LocalSessionFactoryBean.getConfigTimeLobHandler(), + LocalSessionFactoryBean.getConfigTimeTransactionManager()); } /** @@ -144,7 +150,7 @@ public abstract class AbstractLobType implements UserType { if (this.lobHandler == null) { throw new IllegalStateException("No LobHandler found for configuration - " + - "lobHandler property must be set on SessionFactoryBuilder"); + "lobHandler property must be set on LocalSessionFactoryBean"); } try { @@ -166,7 +172,7 @@ public abstract class AbstractLobType implements UserType { if (this.lobHandler == null) { throw new IllegalStateException("No LobHandler found for configuration - " + - "lobHandler property must be set on SessionFactoryBuilder"); + "lobHandler property must be set on LocalSessionFactoryBean"); } LobCreator lobCreator = this.lobHandler.getLobCreator(); diff --git a/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/support/BlobByteArrayType.java b/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/support/BlobByteArrayType.java index d26b2c2621..c30f81fdb1 100644 --- a/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/support/BlobByteArrayType.java +++ b/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/support/BlobByteArrayType.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2011 the original author or authors. + * Copyright 2002-2005 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -29,7 +29,7 @@ import org.springframework.jdbc.support.lob.LobHandler; /** * Hibernate UserType implementation for byte arrays that get mapped to BLOBs. - * Retrieves the LobHandler to use from SessionFactoryBuilder at config time. + * Retrieves the LobHandler to use from LocalSessionFactoryBean at config time. * *

Can also be defined in generic Hibernate mappings, as DefaultLobCreator will * work with most JDBC-compliant database drivers. In this case, the field type @@ -38,15 +38,15 @@ import org.springframework.jdbc.support.lob.LobHandler; * * @author Juergen Hoeller * @since 1.2 - * @see org.springframework.orm.hibernate3.SessionFactoryBuilder#setLobHandler + * @see org.springframework.orm.hibernate3.LocalSessionFactoryBean#setLobHandler */ public class BlobByteArrayType extends AbstractLobType { /** * Constructor used by Hibernate: fetches config-time LobHandler and - * config-time JTA TransactionManager from SessionFactoryBuilder. - * @see org.springframework.orm.hibernate3.SessionFactoryBuilder#getConfigTimeLobHandler - * @see org.springframework.orm.hibernate3.SessionFactoryBuilder#getConfigTimeTransactionManager + * config-time JTA TransactionManager from LocalSessionFactoryBean. + * @see org.springframework.orm.hibernate3.LocalSessionFactoryBean#getConfigTimeLobHandler + * @see org.springframework.orm.hibernate3.LocalSessionFactoryBean#getConfigTimeTransactionManager */ public BlobByteArrayType() { super(); @@ -64,7 +64,7 @@ public class BlobByteArrayType extends AbstractLobType { return new int[] {Types.BLOB}; } - public Class returnedClass() { + public Class returnedClass() { return byte[].class; } diff --git a/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/support/BlobSerializableType.java b/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/support/BlobSerializableType.java index ba57c0f778..9334c8db88 100644 --- a/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/support/BlobSerializableType.java +++ b/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/support/BlobSerializableType.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2011 the original author or authors. + * Copyright 2002-2005 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -37,7 +37,7 @@ import org.springframework.jdbc.support.lob.LobHandler; /** * Hibernate UserType implementation for arbitrary objects that get serialized to BLOBs. - * Retrieves the LobHandler to use from SessionFactoryBuilder at config time. + * Retrieves the LobHandler to use from LocalSessionFactoryBean at config time. * *

Can also be defined in generic Hibernate mappings, as DefaultLobCreator will * work with most JDBC-compliant database drivers. In this case, the field type @@ -46,7 +46,7 @@ import org.springframework.jdbc.support.lob.LobHandler; * * @author Juergen Hoeller * @since 1.2 - * @see org.springframework.orm.hibernate3.SessionFactoryBuilder#setLobHandler + * @see org.springframework.orm.hibernate3.LocalSessionFactoryBean#setLobHandler */ public class BlobSerializableType extends AbstractLobType { @@ -60,9 +60,9 @@ public class BlobSerializableType extends AbstractLobType { /** * Constructor used by Hibernate: fetches config-time LobHandler and - * config-time JTA TransactionManager from SessionFactoryBuilder. - * @see org.springframework.orm.hibernate3.SessionFactoryBuilder#getConfigTimeLobHandler - * @see org.springframework.orm.hibernate3.SessionFactoryBuilder#getConfigTimeTransactionManager + * config-time JTA TransactionManager from LocalSessionFactoryBean. + * @see org.springframework.orm.hibernate3.LocalSessionFactoryBean#getConfigTimeLobHandler + * @see org.springframework.orm.hibernate3.LocalSessionFactoryBean#getConfigTimeTransactionManager */ public BlobSerializableType() { super(); @@ -80,7 +80,7 @@ public class BlobSerializableType extends AbstractLobType { return new int[] {Types.BLOB}; } - public Class returnedClass() { + public Class returnedClass() { return Serializable.class; } diff --git a/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/support/BlobStringType.java b/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/support/BlobStringType.java index 9118906cf9..be7ac8f15c 100644 --- a/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/support/BlobStringType.java +++ b/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/support/BlobStringType.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2011 the original author or authors. + * Copyright 2002-2006 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -29,7 +29,7 @@ import org.springframework.jdbc.support.lob.LobHandler; /** * Hibernate UserType implementation for Strings that get mapped to BLOBs. - * Retrieves the LobHandler to use from SessionFactoryBuilder at config time. + * Retrieves the LobHandler to use from LocalSessionFactoryBean at config time. * *

This is intended for the (arguably unnatural, but still common) case * where character data is stored in a binary LOB. This requires encoding @@ -44,15 +44,15 @@ import org.springframework.jdbc.support.lob.LobHandler; * @author Juergen Hoeller * @since 1.2.7 * @see #getCharacterEncoding() - * @see org.springframework.orm.hibernate3.SessionFactoryBuilder#setLobHandler + * @see org.springframework.orm.hibernate3.LocalSessionFactoryBean#setLobHandler */ public class BlobStringType extends AbstractLobType { /** * Constructor used by Hibernate: fetches config-time LobHandler and - * config-time JTA TransactionManager from SessionFactoryBuilder. - * @see org.springframework.orm.hibernate3.SessionFactoryBuilder#getConfigTimeLobHandler - * @see org.springframework.orm.hibernate3.SessionFactoryBuilder#getConfigTimeTransactionManager + * config-time JTA TransactionManager from LocalSessionFactoryBean. + * @see org.springframework.orm.hibernate3.LocalSessionFactoryBean#getConfigTimeLobHandler + * @see org.springframework.orm.hibernate3.LocalSessionFactoryBean#getConfigTimeTransactionManager */ public BlobStringType() { super(); @@ -70,7 +70,7 @@ public class BlobStringType extends AbstractLobType { return new int[] {Types.BLOB}; } - public Class returnedClass() { + public Class returnedClass() { return String.class; } diff --git a/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/support/ClobStringType.java b/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/support/ClobStringType.java index 18ad347860..12435ba890 100644 --- a/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/support/ClobStringType.java +++ b/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/support/ClobStringType.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2011 the original author or authors. + * Copyright 2002-2005 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -28,7 +28,7 @@ import org.springframework.jdbc.support.lob.LobHandler; /** * Hibernate UserType implementation for Strings that get mapped to CLOBs. - * Retrieves the LobHandler to use from SessionFactoryBuilder at config time. + * Retrieves the LobHandler to use from LocalSessionFactoryBean at config time. * *

Particularly useful for storing Strings with more than 4000 characters in an * Oracle database (only possible via CLOBs), in combination with OracleLobHandler. @@ -40,15 +40,15 @@ import org.springframework.jdbc.support.lob.LobHandler; * * @author Juergen Hoeller * @since 1.2 - * @see org.springframework.orm.hibernate3.SessionFactoryBuilder#setLobHandler + * @see org.springframework.orm.hibernate3.LocalSessionFactoryBean#setLobHandler */ public class ClobStringType extends AbstractLobType { /** * Constructor used by Hibernate: fetches config-time LobHandler and - * config-time JTA TransactionManager from SessionFactoryBuilder. - * @see org.springframework.orm.hibernate3.SessionFactoryBuilder#getConfigTimeLobHandler - * @see org.springframework.orm.hibernate3.SessionFactoryBuilder#getConfigTimeTransactionManager + * config-time JTA TransactionManager from LocalSessionFactoryBean. + * @see org.springframework.orm.hibernate3.LocalSessionFactoryBean#getConfigTimeLobHandler + * @see org.springframework.orm.hibernate3.LocalSessionFactoryBean#getConfigTimeTransactionManager */ public ClobStringType() { super(); @@ -66,7 +66,7 @@ public class ClobStringType extends AbstractLobType { return new int[] {Types.CLOB}; } - public Class returnedClass() { + public Class returnedClass() { return String.class; } diff --git a/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/support/IdTransferringMergeEventListener.java b/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/support/IdTransferringMergeEventListener.java index 9052419c7e..4392b39e9f 100644 --- a/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/support/IdTransferringMergeEventListener.java +++ b/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/support/IdTransferringMergeEventListener.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2011 the original author or authors. + * Copyright 2002-2007 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -42,21 +42,19 @@ import org.hibernate.persister.entity.EntityPersister; * calls, with the Hibernate SessionFactory configuration specifying an * IdTransferringMergeEventListener. * - *

Typically specified as entry for SessionFactoryBuilder's "eventListeners" + *

Typically specified as entry for LocalSessionFactoryBean's "eventListeners" * map, with key "merge". * * @author Juergen Hoeller * @since 1.2 - * @see org.springframework.orm.hibernate3.SessionFactoryBuilder#setEventListeners(java.util.Map) + * @see org.springframework.orm.hibernate3.LocalSessionFactoryBean#setEventListeners(java.util.Map) */ -@SuppressWarnings("serial") public class IdTransferringMergeEventListener extends DefaultMergeEventListener { /** * Hibernate 3.1 implementation of ID transferral. */ @Override - @SuppressWarnings("rawtypes") protected void entityIsTransient(MergeEvent event, Map copyCache) { super.entityIsTransient(event, copyCache); SessionImplementor session = event.getSession(); diff --git a/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/support/ScopedBeanInterceptor.java b/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/support/ScopedBeanInterceptor.java index 4f24d13573..e2bc17731f 100644 --- a/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/support/ScopedBeanInterceptor.java +++ b/org.springframework.orm/src/main/java/org/springframework/orm/hibernate3/support/ScopedBeanInterceptor.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2011 the original author or authors. + * Copyright 2002-2007 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -30,20 +30,18 @@ import org.springframework.aop.support.AopUtils; * *

Usage example: * - *

- * {@code
- * 
+ * 
+ * <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
  *   ...
- *   
- *     
- *   
- * }
+ * <property name="entityInterceptor"> + * <bean class="org.springframework.orm.hibernate3.support.ScopedBeanInterceptor"/> + * </property> + * </bean>
* * @author Costin Leau * @author Juergen Hoeller * @since 2.0 */ -@SuppressWarnings("serial") public class ScopedBeanInterceptor extends EmptyInterceptor { @Override diff --git a/org.springframework.orm/src/test/java/org/springframework/orm/hibernate3/HibernateTransactionManagerTests.java b/org.springframework.orm/src/test/java/org/springframework/orm/hibernate3/HibernateTransactionManagerTests.java index 83b5b6771c..81a4bf6ea4 100644 --- a/org.springframework.orm/src/test/java/org/springframework/orm/hibernate3/HibernateTransactionManagerTests.java +++ b/org.springframework.orm/src/test/java/org/springframework/orm/hibernate3/HibernateTransactionManagerTests.java @@ -117,8 +117,7 @@ public class HibernateTransactionManagerTests extends TestCase { queryControl.replay(); LocalSessionFactoryBean lsfb = new LocalSessionFactoryBean() { - @Override - protected SessionFactory newSessionFactory() throws HibernateException { + protected SessionFactory newSessionFactory(Configuration config) throws HibernateException { return sf; } }; @@ -340,8 +339,7 @@ public class HibernateTransactionManagerTests extends TestCase { queryControl.replay(); LocalSessionFactoryBean lsfb = new LocalSessionFactoryBean() { - @Override - protected SessionFactory newSessionFactory() throws HibernateException { + protected SessionFactory newSessionFactory(Configuration config) throws HibernateException { return sf; } }; @@ -418,8 +416,7 @@ public class HibernateTransactionManagerTests extends TestCase { txControl.replay(); LocalSessionFactoryBean lsfb = new LocalSessionFactoryBean() { - @Override - protected SessionFactory newSessionFactory() throws HibernateException { + protected SessionFactory newSessionFactory(Configuration config) throws HibernateException { return sf; } }; @@ -773,8 +770,7 @@ public class HibernateTransactionManagerTests extends TestCase { sessionControl.replay(); LocalSessionFactoryBean lsfb = new LocalSessionFactoryBean() { - @Override - protected SessionFactory newSessionFactory() throws HibernateException { + protected SessionFactory newSessionFactory(Configuration config) throws HibernateException { return sf; } }; @@ -858,8 +854,7 @@ public class HibernateTransactionManagerTests extends TestCase { txControl.replay(); LocalSessionFactoryBean lsfb = new LocalSessionFactoryBean() { - @Override - protected SessionFactory newSessionFactory() throws HibernateException { + protected SessionFactory newSessionFactory(Configuration config) throws HibernateException { return sf; } }; diff --git a/org.springframework.orm/src/test/java/org/springframework/orm/hibernate3/LocalSessionFactoryBeanTests.java b/org.springframework.orm/src/test/java/org/springframework/orm/hibernate3/LocalSessionFactoryBeanTests.java index 115502ad0f..c8e4254046 100644 --- a/org.springframework.orm/src/test/java/org/springframework/orm/hibernate3/LocalSessionFactoryBeanTests.java +++ b/org.springframework.orm/src/test/java/org/springframework/orm/hibernate3/LocalSessionFactoryBeanTests.java @@ -28,11 +28,9 @@ import java.util.List; import java.util.Map; import java.util.Properties; import java.util.Set; - import javax.transaction.TransactionManager; import junit.framework.TestCase; - import org.easymock.MockControl; import org.hibernate.Hibernate; import org.hibernate.HibernateException; @@ -52,6 +50,7 @@ import org.hibernate.engine.FilterDefinition; import org.hibernate.event.MergeEvent; import org.hibernate.event.MergeEventListener; import org.hibernate.mapping.TypeDef; + import org.springframework.beans.factory.xml.XmlBeanFactory; import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.FileSystemResource; @@ -60,17 +59,14 @@ import org.springframework.jdbc.datasource.DriverManagerDataSource; /** * @author Juergen Hoeller - * @author Chris Beams * @since 05.03.2005 */ -@SuppressWarnings("serial") public class LocalSessionFactoryBeanTests extends TestCase { public void testLocalSessionFactoryBeanWithDataSource() throws Exception { final DriverManagerDataSource ds = new DriverManagerDataSource(); final List invocations = new ArrayList(); LocalSessionFactoryBean sfb = new LocalSessionFactoryBean() { - @Override protected Configuration newConfiguration() { return new Configuration() { public Configuration addInputStream(InputStream is) { @@ -84,11 +80,10 @@ public class LocalSessionFactoryBeanTests extends TestCase { } }; } - @Override - protected SessionFactory newSessionFactory() { + protected SessionFactory newSessionFactory(Configuration config) { assertEquals(LocalDataSourceConnectionProvider.class.getName(), - this.getConfiguration().getProperty(Environment.CONNECTION_PROVIDER)); - assertEquals(ds, SessionFactoryBuilderSupport.getConfigTimeDataSource()); + config.getProperty(Environment.CONNECTION_PROVIDER)); + assertEquals(ds, LocalSessionFactoryBean.getConfigTimeDataSource()); invocations.add("newSessionFactory"); return null; } @@ -103,7 +98,6 @@ public class LocalSessionFactoryBeanTests extends TestCase { final RegionFactory regionFactory = new NoCachingRegionFactory(null); final List invocations = new ArrayList(); LocalSessionFactoryBean sfb = new LocalSessionFactoryBean() { - @Override protected Configuration newConfiguration() { return new Configuration() { public Configuration addInputStream(InputStream is) { @@ -117,11 +111,10 @@ public class LocalSessionFactoryBeanTests extends TestCase { } }; } - @Override - protected SessionFactory newSessionFactory() { + protected SessionFactory newSessionFactory(Configuration config) { assertEquals(LocalRegionFactoryProxy.class.getName(), - this.getConfiguration().getProperty(Environment.CACHE_REGION_FACTORY)); - assertSame(regionFactory, SessionFactoryBuilderSupport.getConfigTimeRegionFactory()); + config.getProperty(Environment.CACHE_REGION_FACTORY)); + assertSame(regionFactory, LocalSessionFactoryBean.getConfigTimeRegionFactory()); invocations.add("newSessionFactory"); return null; } @@ -132,13 +125,10 @@ public class LocalSessionFactoryBeanTests extends TestCase { assertEquals("newSessionFactory", invocations.get(0)); } - @SuppressWarnings("deprecation") - // CacheProvider is deprecated in Hibernate 3.3, but LSFB still supports its use public void testLocalSessionFactoryBeanWithCacheProvider() throws Exception { final CacheProvider cacheProvider = new NoCacheProvider(); - final List invocations = new ArrayList(); + final List invocations = new ArrayList(); LocalSessionFactoryBean sfb = new LocalSessionFactoryBean() { - @Override protected Configuration newConfiguration() { return new Configuration() { public Configuration addInputStream(InputStream is) { @@ -153,11 +143,10 @@ public class LocalSessionFactoryBeanTests extends TestCase { }; } - @Override - protected SessionFactory newSessionFactory() { + protected SessionFactory newSessionFactory(Configuration config) { assertEquals(LocalCacheProviderProxy.class.getName(), - this.getConfiguration().getProperty(Environment.CACHE_PROVIDER)); - assertSame(cacheProvider, SessionFactoryBeanDelegate.getConfigTimeCacheProvider()); + config.getProperty(Environment.CACHE_PROVIDER)); + assertSame(cacheProvider, LocalSessionFactoryBean.getConfigTimeCacheProvider()); invocations.add("newSessionFactory"); return null; } @@ -172,7 +161,6 @@ public class LocalSessionFactoryBeanTests extends TestCase { final DriverManagerDataSource ds = new DriverManagerDataSource(); final List invocations = new ArrayList(); LocalSessionFactoryBean sfb = new LocalSessionFactoryBean() { - @Override protected Configuration newConfiguration() { return new Configuration() { public Configuration addInputStream(InputStream is) { @@ -187,11 +175,10 @@ public class LocalSessionFactoryBeanTests extends TestCase { }; } - @Override - protected SessionFactory newSessionFactory() { + protected SessionFactory newSessionFactory(Configuration config) { assertEquals(TransactionAwareDataSourceConnectionProvider.class.getName(), - this.getConfiguration().getProperty(Environment.CONNECTION_PROVIDER)); - assertEquals(ds, SessionFactoryBuilderSupport.getConfigTimeDataSource()); + config.getProperty(Environment.CONNECTION_PROVIDER)); + assertEquals(ds, LocalSessionFactoryBean.getConfigTimeDataSource()); invocations.add("newSessionFactory"); return null; } @@ -209,7 +196,6 @@ public class LocalSessionFactoryBeanTests extends TestCase { final TransactionManager tm = (TransactionManager) tmControl.getMock(); final List invocations = new ArrayList(); LocalSessionFactoryBean sfb = new LocalSessionFactoryBean() { - @Override protected Configuration newConfiguration() { return new Configuration() { public Configuration addInputStream(InputStream is) { @@ -224,14 +210,13 @@ public class LocalSessionFactoryBeanTests extends TestCase { }; } - @Override - protected SessionFactory newSessionFactory() { + protected SessionFactory newSessionFactory(Configuration config) { assertEquals(LocalJtaDataSourceConnectionProvider.class.getName(), - this.getConfiguration().getProperty(Environment.CONNECTION_PROVIDER)); - assertEquals(ds, SessionFactoryBuilderSupport.getConfigTimeDataSource()); + config.getProperty(Environment.CONNECTION_PROVIDER)); + assertEquals(ds, LocalSessionFactoryBean.getConfigTimeDataSource()); assertEquals(LocalTransactionManagerLookup.class.getName(), - this.getConfiguration().getProperty(Environment.TRANSACTION_MANAGER_STRATEGY)); - assertEquals(tm, SessionFactoryBuilderSupport.getConfigTimeTransactionManager()); + config.getProperty(Environment.TRANSACTION_MANAGER_STRATEGY)); + assertEquals(tm, LocalSessionFactoryBean.getConfigTimeTransactionManager()); invocations.add("newSessionFactory"); return null; } @@ -252,7 +237,6 @@ public class LocalSessionFactoryBeanTests extends TestCase { final DriverManagerDataSource ds = new DriverManagerDataSource(); final Set invocations = new HashSet(); LocalSessionFactoryBean sfb = new LocalSessionFactoryBean() { - @Override protected Configuration newConfiguration() { return new Configuration() { public Configuration addJar(File file) { @@ -262,11 +246,10 @@ public class LocalSessionFactoryBeanTests extends TestCase { }; } - @Override - protected SessionFactory newSessionFactory() { + protected SessionFactory newSessionFactory(Configuration config) { assertEquals(LocalDataSourceConnectionProvider.class.getName(), - this.getConfiguration().getProperty(Environment.CONNECTION_PROVIDER)); - assertEquals(ds, SessionFactoryBuilderSupport.getConfigTimeDataSource()); + config.getProperty(Environment.CONNECTION_PROVIDER)); + assertEquals(ds, LocalSessionFactoryBean.getConfigTimeDataSource()); invocations.add("newSessionFactory"); return null; } @@ -285,7 +268,6 @@ public class LocalSessionFactoryBeanTests extends TestCase { final DriverManagerDataSource ds = new DriverManagerDataSource(); final Set invocations = new HashSet(); LocalSessionFactoryBean sfb = new LocalSessionFactoryBean() { - @Override protected Configuration newConfiguration() { return new Configuration() { public Configuration addInputStream(InputStream is) { @@ -300,12 +282,11 @@ public class LocalSessionFactoryBeanTests extends TestCase { }; } - @Override - protected SessionFactory newSessionFactory() { + protected SessionFactory newSessionFactory(Configuration config) { assertEquals(LocalDataSourceConnectionProvider.class.getName(), - this.getConfiguration().getProperty(Environment.CONNECTION_PROVIDER)); - assertEquals(ds, SessionFactoryBuilderSupport.getConfigTimeDataSource()); - assertEquals("myValue", this.getConfiguration().getProperty("myProperty")); + config.getProperty(Environment.CONNECTION_PROVIDER)); + assertEquals(ds, LocalSessionFactoryBean.getConfigTimeDataSource()); + assertEquals("myValue", config.getProperty("myProperty")); invocations.add("newSessionFactory"); return null; } @@ -326,11 +307,10 @@ public class LocalSessionFactoryBeanTests extends TestCase { public void testLocalSessionFactoryBeanWithValidProperties() throws Exception { final Set invocations = new HashSet(); LocalSessionFactoryBean sfb = new LocalSessionFactoryBean() { - @Override - protected SessionFactory newSessionFactory() { + protected SessionFactory newSessionFactory(Configuration config) { assertEquals(UserSuppliedConnectionProvider.class.getName(), - this.getConfiguration().getProperty(Environment.CONNECTION_PROVIDER)); - assertEquals("myValue", this.getConfiguration().getProperty("myProperty")); + config.getProperty(Environment.CONNECTION_PROVIDER)); + assertEquals("myValue", config.getProperty("myProperty")); invocations.add("newSessionFactory"); return null; } @@ -376,8 +356,7 @@ public class LocalSessionFactoryBeanTests extends TestCase { factoryControl.setVoidCallable(1); factoryControl.replay(); LocalSessionFactoryBean sfb = new LocalSessionFactoryBean() { - @Override - protected SessionFactory newSessionFactory() { + protected SessionFactory newSessionFactory(Configuration config) { return sessionFactory; } }; @@ -392,7 +371,6 @@ public class LocalSessionFactoryBeanTests extends TestCase { public void testLocalSessionFactoryBeanWithEntityInterceptor() throws Exception { LocalSessionFactoryBean sfb = new LocalSessionFactoryBean() { - @Override protected Configuration newConfiguration() { return new Configuration() { public Configuration setInterceptor(Interceptor interceptor) { @@ -419,7 +397,6 @@ public class LocalSessionFactoryBeanTests extends TestCase { public void testLocalSessionFactoryBeanWithNamingStrategy() throws Exception { LocalSessionFactoryBean sfb = new LocalSessionFactoryBean() { - @Override protected Configuration newConfiguration() { return new Configuration() { public Configuration setNamingStrategy(NamingStrategy namingStrategy) { @@ -445,7 +422,6 @@ public class LocalSessionFactoryBeanTests extends TestCase { final Properties registeredClassCache = new Properties(); final Properties registeredCollectionCache = new Properties(); LocalSessionFactoryBean sfb = new LocalSessionFactoryBean() { - @Override protected Configuration newConfiguration() { return new Configuration() { public Configuration setCacheConcurrencyStrategy(String clazz, String concurrencyStrategy) { @@ -458,8 +434,7 @@ public class LocalSessionFactoryBeanTests extends TestCase { } }; } - @Override - protected SessionFactory newSessionFactory() { + protected SessionFactory newSessionFactory(Configuration config) { return null; } }; @@ -482,7 +457,6 @@ public class LocalSessionFactoryBeanTests extends TestCase { final Properties registeredClassCache = new Properties(); final Properties registeredCollectionCache = new Properties(); LocalSessionFactoryBean sfb = new LocalSessionFactoryBean() { - @Override protected Configuration newConfiguration() { return new Configuration() { // changed from return type 'void' to 'Configuration' in Hibernate 3.6 @@ -494,8 +468,7 @@ public class LocalSessionFactoryBeanTests extends TestCase { } }; } - @Override - protected SessionFactory newSessionFactory() { + protected SessionFactory newSessionFactory(Configuration config) { return null; } }; @@ -517,7 +490,6 @@ public class LocalSessionFactoryBeanTests extends TestCase { public void testLocalSessionFactoryBeanWithEventListeners() throws Exception { final Map registeredListeners = new HashMap(); LocalSessionFactoryBean sfb = new LocalSessionFactoryBean() { - @Override protected Configuration newConfiguration() { return new Configuration() { public void setListener(String type, Object listener) { @@ -525,8 +497,7 @@ public class LocalSessionFactoryBeanTests extends TestCase { } }; } - @Override - protected SessionFactory newSessionFactory() { + protected SessionFactory newSessionFactory(Configuration config) { return null; } }; @@ -543,7 +514,6 @@ public class LocalSessionFactoryBeanTests extends TestCase { public void testLocalSessionFactoryBeanWithEventListenerSet() throws Exception { final Map registeredListeners = new HashMap(); LocalSessionFactoryBean sfb = new LocalSessionFactoryBean() { - @Override protected Configuration newConfiguration() { return new Configuration() { public void setListeners(String type, Object[] listeners) { @@ -552,8 +522,7 @@ public class LocalSessionFactoryBeanTests extends TestCase { } }; } - @Override - protected SessionFactory newSessionFactory() { + protected SessionFactory newSessionFactory(Configuration config) { return null; } }; @@ -610,7 +579,6 @@ public class LocalSessionFactoryBeanTests extends TestCase { public List registeredFilterDefinitions = new LinkedList(); - @Override protected Configuration newConfiguration() throws HibernateException { return new Configuration() { public void addFilterDefinition(FilterDefinition definition) { @@ -619,8 +587,7 @@ public class LocalSessionFactoryBeanTests extends TestCase { }; } - @Override - protected SessionFactory newSessionFactory() { + protected SessionFactory newSessionFactory(Configuration config) { return null; } } @@ -630,9 +597,8 @@ public class LocalSessionFactoryBeanTests extends TestCase { public Mappings mappings; - @Override - protected SessionFactory newSessionFactory() { - this.mappings = this.getConfiguration().createMappings(); + protected SessionFactory newSessionFactory(Configuration config) { + this.mappings = config.createMappings(); return null; } }