Browse Source
Large refactoring of existing *SessionFactoryBean hierarchy designed to support configuration of Hibernate SessionFactory objects within @Configuration class @Bean methods without forcing use of a FactoryBean type, which is generally discouraged due to awkwardness of programming model and lifecycle issues. Refactored and new types include: * Removal of AbstractSessionFactoryBean, replacing it with SessionFactoryBeanSupport abstract base class * Introduction of SessionFactoryBuilder and AnnotationSessionFactoryBuilder types, both direct subclasses of SessionFactoryBuilderSupport. These types are intended for direct use within @Bean methods. They expose method-chainable set* methods allowing for concise and convenient use. See JavaDoc on both types for usage examples. * LocalSessionFactoryBean and AnnotationSessionFactoryBean types are now subclasses, respectively, of the *Builder types above. LSFB and ASFB backward-compatibility has been maintained almost entirely. The one exception is that there is no longer a protected convertHibernateAccessException() method available in the hierarchy. This method was not likely often used anyway and has been replaced by the new (and public) setPersistenceExceptionTranslator() which accepts instances of type HibernateExceptionTranslator as introduced in SPR-8076. LSFB and ASFB setter method signatures have changed. They no longer return void in standard JavaBeans style but rather, and due to extending the *Builder types above, return the 'this' reference. This posed a problem because the Spring container has to date been unable to detect and provide dependency injection against non-void returning setter methods. This limitation was due to the way that the default JavaBeans Introspector class and its getBeanInfo() method works, and prompted the introduction and intergration of ExtendedBeanInfo, already completed in SPR-8079. So have no concern if you notice this signature change - it all works. Certain deprecations have been made: * All LSFB/ASFB methods related to Hibernate's CacheProvider SPI, reflecting its deprecation in Hibernate 3.3 in favor of the new RegionFactory SPI. Note these methods have been preserved only on the FactoryBean types. The new *SessionFactoryBuilder supertypes do not expose CacheProvider services at all. * All protected LSFB/ASFB methods that accept a Hibernate Configuration parameter, such as newSessionFactory(Configuration), postProcessMappings(Configuration) and postProcessConfiguration(Configuation), in favor of no-arg methods with the same names. Due to the nature of the hierarchy refactoring mentioned above, the Configuration instance is always available when these methods are called, thus no need to pass it in as a parameter. In the process, our approach to automatic detection of Hibernate dialect has been improved (it was in fact broken before). Thanks to James Roper for his suggestion in SPR-7936 as to how to fix this. See HibernateSessionFactoryConfigurationTests as a starting point for understanding the new builder-style approach to SessionFactory creation. Note especially use of the SessionFactoryBuilder#doWithConfiguration method which allows for direct programmatic configuration of the Native Hibernate (Annotation)Configuration API. As a final note, AnnotationConfiguration has been deprecated in Hibernate 3.6, and great pains have been taken to ensure that users of any supported Hibernate version (3.2 -> 3.6) will never need to (a) cast from Configuration to AnnotationConfiguration or (b) experience deprecation warnings due to being forced to use the AnnotationConfiguration API. Explore the JavaDoc around the doWithConfiguration() method and HibernateConfigurationCallback type for complete details. Issue: SPR-8066, SPR-7936, SPR-8076, SPR-8098 git-svn-id: https://src.springframework.org/svn/spring-framework/trunk@4147 50f2f4bb-b051-0410-bef5-90022cba6387pull/1/merge
40 changed files with 3039 additions and 1746 deletions
@ -0,0 +1,352 @@
@@ -0,0 +1,352 @@
|
||||
/* |
||||
* 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.Feature; |
||||
import org.springframework.context.annotation.FeatureConfiguration; |
||||
import org.springframework.context.annotation.Import; |
||||
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.Transactional; |
||||
import org.springframework.transaction.config.TxAnnotationDriven; |
||||
|
||||
/** |
||||
* 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<Foo> findAll(); |
||||
} |
||||
|
||||
@Repository |
||||
public static class HibernateFooRepository implements FooRepository { |
||||
private final SessionFactory sessionFactory; |
||||
public HibernateFooRepository(SessionFactory sessionFactory) { |
||||
this.sessionFactory = sessionFactory; |
||||
} |
||||
@Transactional |
||||
@SuppressWarnings("unchecked") |
||||
public List<Foo> findAll() { |
||||
return sessionFactory.getCurrentSession().createQuery("from Bogus").list(); |
||||
} |
||||
} |
||||
|
||||
|
||||
@Configuration |
||||
@Import(TxConfig.class) |
||||
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(); |
||||
} |
||||
} |
||||
|
||||
|
||||
@FeatureConfiguration |
||||
static class TxConfig { |
||||
@Feature |
||||
TxAnnotationDriven tx(PlatformTransactionManager txManager) { |
||||
return new TxAnnotationDriven(txManager); |
||||
} |
||||
} |
||||
|
||||
|
||||
@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<AnnotationConfiguration>() { |
||||
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<AnnotationConfiguration>() { |
||||
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<org.hibernate.cfg.Configuration>() { |
||||
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<org.hibernate.cfg.Configuration>() { |
||||
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<org.hibernate.cfg.Configuration>() { |
||||
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 { |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,36 @@
@@ -0,0 +1,36 @@
|
||||
/* |
||||
* 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; |
||||
} |
||||
} |
||||
@ -0,0 +1,12 @@
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<beans xmlns="http://www.springframework.org/schema/beans" |
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd"> |
||||
|
||||
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"> |
||||
<property name="annotatedClasses" value="org.springframework.orm.hibernate3.scannable.Foo"/> |
||||
<property name="dataSource" ref="dataSource"/> |
||||
<property name="schemaUpdate" value="true"/> |
||||
</bean> |
||||
|
||||
</beans> |
||||
@ -0,0 +1,18 @@
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<beans xmlns="http://www.springframework.org/schema/beans" |
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd"> |
||||
|
||||
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"> |
||||
<!--<property name="annotatedClasses" value="org.springframework.orm.hibernate3.scannable.Foo"/>--> |
||||
<property name="mappingLocations" value="classpath:org/springframework/orm/hibernate3/scannable/FooMapping.hbm.xml"/> |
||||
<property name="dataSource" ref="dataSource"/> |
||||
<property name="schemaUpdate" value="true"/> |
||||
<property name="hibernateProperties"> |
||||
<value> |
||||
hibernate.dialect=org.hibernate.dialect.HSQLDialect |
||||
</value> |
||||
</property> |
||||
</bean> |
||||
|
||||
</beans> |
||||
@ -0,0 +1,12 @@
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD//EN" |
||||
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> |
||||
|
||||
<hibernate-mapping> |
||||
|
||||
<class name="org.springframework.orm.hibernate3.scannable.Foo" table="foo"> |
||||
<id name="id" column="id" access="field"/> |
||||
<property name="name" column="name" /> |
||||
</class> |
||||
|
||||
</hibernate-mapping> |
||||
@ -1,336 +0,0 @@
@@ -1,336 +0,0 @@
|
||||
/* |
||||
* 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. |
||||
* |
||||
* <p>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. |
||||
* |
||||
* <p>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<SessionFactory>, 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. |
||||
* <p>If this is set, the Hibernate settings should not define |
||||
* a connection provider to avoid meaningless double configuration. |
||||
* <p>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. |
||||
* <p>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. |
||||
* <p>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. |
||||
* <p>If you switch this flag to "true", Spring's Hibernate access will be able to |
||||
* <i>participate in JDBC-based transactions managed outside of Hibernate</i> |
||||
* (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. |
||||
* <p>A further benefit of this option is that <i>plain Sessions opened directly |
||||
* via the SessionFactory</i>, outside of Spring's Hibernate support, will still |
||||
* participate in active Spring-managed transactions. However, consider using |
||||
* Hibernate's <code>getCurrentSession()</code> method instead (see javadoc of |
||||
* "exposeTransactionAwareSessionFactory" property). |
||||
* <p><b>WARNING:</b> 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". |
||||
* <p>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 <code>getCurrentSession()</code> method, returning the |
||||
* Session that's associated with the current Spring-managed transaction, if any. |
||||
* <p>Default is "true", letting data access code work with the plain |
||||
* Hibernate SessionFactory and its <code>getCurrentSession()</code> 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()</code> will also seamlessly work with |
||||
* a request-scoped Session managed by OpenSessionInViewFilter/Interceptor. |
||||
* <p>Turn this flag off to expose the plain Hibernate SessionFactory with |
||||
* Hibernate's default <code>getCurrentSession()</code> 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. |
||||
* <p>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. |
||||
* <p>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 <code>null</code>) |
||||
* @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<? extends SessionFactory> 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. |
||||
* <p>Converts the exception if it is a HibernateException; |
||||
* else returns <code>null</code> 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 |
||||
* <code>org.springframework.dao</code> hierarchy. |
||||
* <p>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 |
||||
* <code>getSessionFactory()</code> at this point. |
||||
* <p>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 |
||||
* <code>getSessionFactory()</code> at this point. |
||||
* <p>This implementation is empty. |
||||
* @see #getSessionFactory() |
||||
*/ |
||||
protected void beforeSessionFactoryDestruction() { |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,41 @@
@@ -0,0 +1,41 @@
|
||||
/* |
||||
* 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<C extends Configuration> { |
||||
|
||||
/** |
||||
* 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; |
||||
|
||||
} |
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,198 @@
@@ -0,0 +1,198 @@
|
||||
/* |
||||
* 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. |
||||
* |
||||
* <p>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<org.hibernate.cache.CacheProvider> configTimeCacheProviderHolder = |
||||
new ThreadLocal<org.hibernate.cache.CacheProvider>(); |
||||
|
||||
/** |
||||
* 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. |
||||
* <p>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<? extends SessionFactory> 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); |
||||
} |
||||
} |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,128 @@
@@ -0,0 +1,128 @@
|
||||
/* |
||||
* 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<SessionFactory>, |
||||
InitializingBean, DisposableBean, PersistenceExceptionTranslator { |
||||
|
||||
/** |
||||
* <b>Deprecated.</b> <i>as of Spring 3.0 in favor of {@code setCacheRegionFactory} |
||||
* following Hibernate 3.3's deprecation of the {@code CacheProvider} SPI.</i> |
||||
* <p>Set the Hibernate {@code CacheProvider} to use for the {@code SessionFactory}. |
||||
* Allows for using a Spring-managed {@code CacheProvider} instance. |
||||
* <p>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<? extends SessionFactory> 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}. |
||||
* <p>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. |
||||
* <p>Converts the exception if it is a HibernateException; |
||||
* else returns <code>null</code> to indicate an unknown exception. |
||||
* @see org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor |
||||
* @see #convertHibernateAccessException |
||||
*/ |
||||
DataAccessException translateExceptionIfPossible(RuntimeException ex); |
||||
|
||||
} |
||||
@ -0,0 +1,101 @@
@@ -0,0 +1,101 @@
|
||||
/* |
||||
* 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. |
||||
* |
||||
* <p>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. |
||||
* |
||||
* <p>Setter methods return the builder instance in order to facilitate |
||||
* a concise and convenient method-chaining style. For example: |
||||
* <pre class="code"> |
||||
* {@code @Configuration} |
||||
* public class DataConfig { |
||||
* {@code @Bean} |
||||
* public SessionFactory sessionFactory() { |
||||
* return new SessionFactoryBean() |
||||
* .setDataSource(dataSource()) |
||||
* .setMappingLocations("classpath:com/myco/*.hbm.xml"}) |
||||
* .buildSessionFactory(); |
||||
* } |
||||
* } |
||||
* </pre> |
||||
* |
||||
* <p>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: |
||||
* <pre class="code"> |
||||
* SessionFactory sessionFactory = |
||||
* new SessionFactoryBuilder() |
||||
* // ...
|
||||
* .doWithConfiguration(new HibernateConfigurationCallback<Configuration>() { |
||||
* public void configure(Configuration cfg) { |
||||
* cfg.setNamingStrategy(MyNamingStrategy.class); |
||||
* } |
||||
* }) |
||||
* .buildSessionFactory(); |
||||
* </pre> |
||||
* |
||||
* @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<SessionFactoryBuilder> { |
||||
|
||||
/** |
||||
* 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} |
||||
* <p>This implementation returns {@code org.hibernate.cfg.Configuration} |
||||
*/ |
||||
@Override |
||||
protected Class<? extends Configuration> getDefaultConfigurationClass() { |
||||
return Configuration.class; |
||||
} |
||||
|
||||
} |
||||
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,300 @@
@@ -0,0 +1,300 @@
|
||||
/* |
||||
* 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. |
||||
* |
||||
* <p>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. |
||||
* |
||||
* <p>Setter methods return the builder instance in order to facilitate |
||||
* a concise and convenient method-chaining style. For example: |
||||
* <pre class="code"> |
||||
* {@code @Configuration} |
||||
* public class DataConfig { |
||||
* {@code @Bean} |
||||
* public SessionFactory sessionFactory() { |
||||
* return new AnnotationSessionFactoryBuilder() |
||||
* .setDataSource(dataSource()) |
||||
* .setPackagesToScan("com.myco"}) |
||||
* .buildSessionFactory(); |
||||
* } |
||||
* } |
||||
* </pre> |
||||
* |
||||
* <p>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: |
||||
* <pre class="code"> |
||||
* SessionFactory sessionFactory = |
||||
* new AnnotationSessionFactoryBuilder() |
||||
* // ...
|
||||
* .doWithConfiguration(new HibernateConfigurationCallback<AnnotationConfiguration>() { |
||||
* public void configure(AnnotationConfiguration cfg) { |
||||
* cfg.addAnnotatedClass(Foo.class); |
||||
* } |
||||
* }) |
||||
* .buildSessionFactory(); |
||||
* </pre> |
||||
* |
||||
* @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<AnnotationSessionFactoryBuilder> { |
||||
|
||||
/** 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} |
||||
* <p>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<? extends Configuration> 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. |
||||
* <p>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. |
||||
* <p>Default is to search all specified packages for classes annotated with |
||||
* <code>@javax.persistence.Entity</code>, <code>@javax.persistence.Embeddable</code> |
||||
* or <code>@javax.persistence.MappedSuperclass</code>, as well as for |
||||
* Hibernate's special <code>@org.hibernate.annotations.Entity</code>. |
||||
* @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. |
||||
* <p>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 <T> void invokeConfigurationMethod(String methodName, Class<T> 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())); |
||||
} |
||||
} |
||||
|
||||
} |
||||
Loading…
Reference in new issue