前面写了一篇关于动态切换Hibernate SessionFactory的文章,原文地址:http://tangyanbo.iteye.com/admin/blogs/1717402
发现存在一些问题:
需要配置多个HibernateTransactionManager和多个Spring 切面
这样带来两个问题
1. 程序效率降低,因为Spring进行多次Advice的拦截
2. 如果其中一个SessionFactory连接出现问题,会导致整个系统无法工作
今天研究出一种新的方法来解决此类问题
1. 数据源及Hibernate SessionFactory配置:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx" xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd">
<!-- FOR SqlServer-->
<bean id="SqlServer_DataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="com.microsoft.sqlserver.jdbc.SQLServerDriver" />
<property name="url"
value="url" />
<property name="username" value="username" />
<property name="password" value="password" />
</bean>
<bean id="SqlServer_SessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"
p:mappingLocations="classpath:/com/entity/*.hbm.xml">
<property name="dataSource" ref="SqlServer_DataSource" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.query.factory_class">org.hibernate.hql.ast.ASTQueryTranslatorFactory</prop>
<prop key="hibernate.dialect">org.hibernate.dialect.SQLServer2008Dialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.format_sql">true</prop>
</props>
</property>
</bean>
<!-- FOR Oracle -->
<bean id="Oracle _DataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="oracle.jdbc.OracleDriver" />
<property name="url" value="jdbc:oracle:thin:@localhost:1521/orcl" />
<property name="username" value="username" />
<property name="password" value="password" />
</bean>
<bean id="Oracle_SessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"
p:mappingLocations="classpath:/com/entity/*.hbm.xml">
<property name="dataSource" ref="Oracle_DataSource" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.query.factory_class">org.hibernate.hql.ast.ASTQueryTranslatorFactory</prop>
<prop key="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</prop>
<prop key="hibernate.show_sql">true</prop>
<prop key="hibernate.format_sql">true</prop>
</props>
</property>
</bean>
</beans>
2. 定义扩展接口DynamicSessionFactoryInf继承SessionFactory
- import org.hibernate.SessionFactory;
- public interface DynamicSessionFactoryInf extends SessionFactory {
- public SessionFactory getHibernateSessionFactory();
- }
3. 定义DynamicSessionFactory实现DynamicSessionFactoryInf
- public class DynamicSessionFactory implements DynamicSessionFactoryInf ,ApplicationContextAware{
- private static final long serialVersionUID = 1L;
- private ApplicationContext applicationContext;
- //动态调用SessionFactory
- private SessionFactory getHibernateSessionFactory(String name) {
- return (SessionFactory) applicationContext.getBean(name);
- }
- //实现DynamicSessionFactoryInf 接口的方法
- public SessionFactory getHibernateSessionFactory() {
- return getHibernateSessionFactory(ThreadLocalUtil.getCurrentITAsset()
- .getSessionFactoryName());
- }
- //以下是实现SessionFactory接口的方法,并对当前的SessionFactory实体进行代理
- public Reference getReference() throws NamingException {
- return getHibernateSessionFactory().getReference();
- }
- public Session openSession() throws HibernateException {
- return getHibernateSessionFactory().openSession();
- }
- public Session openSession(Interceptor interceptor)
- throws HibernateException {
- return getHibernateSessionFactory().openSession(interceptor);
- }
- public Session openSession(Connection connection) {
- return getHibernateSessionFactory().openSession(connection);
- }
- public Session openSession(Connection connection, Interceptor interceptor) {
- return getHibernateSessionFactory().openSession(connection,interceptor);
- }
- public Session getCurrentSession() throws HibernateException {
- return getHibernateSessionFactory().getCurrentSession();
- }
- public StatelessSession openStatelessSession() {
- return getHibernateSessionFactory().openStatelessSession();
- }
- public StatelessSession openStatelessSession(Connection connection) {
- return getHibernateSessionFactory().openStatelessSession(connection);
- }
- public ClassMetadata getClassMetadata(Class entityClass) {
- return getHibernateSessionFactory().getClassMetadata(entityClass);
- }
- public ClassMetadata getClassMetadata(String entityName) {
- return getHibernateSessionFactory().getClassMetadata(entityName);
- }
- public CollectionMetadata getCollectionMetadata(String roleName) {
- return getHibernateSessionFactory().getCollectionMetadata(roleName);
- }
- public Map getAllClassMetadata() {
- return getHibernateSessionFactory().getAllClassMetadata();
- }
- public Map getAllCollectionMetadata() {
- return getHibernateSessionFactory().getAllCollectionMetadata();
- }
- public Statistics getStatistics() {
- return getHibernateSessionFactory().getStatistics();
- }
- public void close() throws HibernateException {
- getHibernateSessionFactory().close();
- }
- public boolean isClosed() {
- return getHibernateSessionFactory().isClosed();
- }
- public Cache getCache() {
- return getHibernateSessionFactory().getCache();
- }
- public void evict(Class persistentClass) throws HibernateException {
- getHibernateSessionFactory().evict(persistentClass);
- }
- public void evict(Class persistentClass, Serializable id)
- throws HibernateException {
- getHibernateSessionFactory().evict(persistentClass, id);
- }
- public void evictEntity(String entityName) throws HibernateException {
- getHibernateSessionFactory().evictEntity(entityName);
- }
- public void evictEntity(String entityName, Serializable id)
- throws HibernateException {
- getHibernateSessionFactory().evictEntity(entityName, id);
- }
- public void evictCollection(String roleName) throws HibernateException {
- getHibernateSessionFactory().evictCollection(roleName);
- }
- public void evictCollection(String roleName, Serializable id)
- throws HibernateException {
- getHibernateSessionFactory().evictCollection(roleName, id);
- }
- public void evictQueries(String cacheRegion) throws HibernateException {
- getHibernateSessionFactory().evictQueries(cacheRegion);
- }
- public void evictQueries() throws HibernateException {
- getHibernateSessionFactory().evictQueries();
- }
- public Set getDefinedFilterNames() {
- return getHibernateSessionFactory().getDefinedFilterNames();
- }
- public FilterDefinition getFilterDefinition(String filterName)
- throws HibernateException {
- return getHibernateSessionFactory().getFilterDefinition(filterName);
- }
- public boolean containsFetchProfileDefinition(String name) {
- return getHibernateSessionFactory().containsFetchProfileDefinition(name);
- }
- @Override
- public void setApplicationContext(ApplicationContext applicationContext)
- throws BeansException {
- this .applicationContext = applicationContext;
- }
- }
4. 配置动态SessionFactory
- < bean id = "sessionFactory" class = "com.hp.it.qdpadmin.common.DynamicSessionFactory" />
5. 定义DynamicTransactionManager继承HibernateTransactionManager
- public class DynamicTransactionManager extends HibernateTransactionManager {
- private static final long serialVersionUID = 1047039346475978451L;
- //重写getDataSource方法,实现动态获取
- public DataSource getDataSource() {
- DataSource sfds = SessionFactoryUtils.getDataSource(getSessionFactory());
- return sfds;
- }
- //重写getSessionFactory方法,实现动态获取SessionFactory
- public SessionFactory getSessionFactory() {
- DynamicSessionFactoryInf dynamicSessionFactory = (DynamicSessionFactoryInf) super
- .getSessionFactory();
- SessionFactory hibernateSessionFactory = dynamicSessionFactory
- .getHibernateSessionFactory();
- return hibernateSessionFactory;
- }
- //重写afterPropertiesSet,跳过数据源的初始化等操作
- public void afterPropertiesSet() {
- return ;
- }
- }
6. 配置dynamicTransactionManager
<bean id="dynamicTransactionManager" class="com.hp.it.qdpadmin.common.DynamicTransactionManager"> <property name="sessionFactory" ref="sessionFactory"/> </bean>
7. 为SessionFactory配置事务切面
<tx:advice id="dynamicTxAdvice" transaction-manager="dynamicTransactionManager"> <tx:attributes> <tx:method name="get*" read-only="true" /> <tx:method name="find*" read-only="true" /> <tx:method name="*" propagation="REQUIRED" rollback-for="Exception" /> </tx:attributes> </tx:advice> <aop:config proxy-target-class="true"> <aop:pointcut id="txPointcut" expression="execution(* com.service.*.*(..))"/> <aop:advisor advice-ref="dynamicTxAdvice" pointcut-ref="txPointcut" /> </aop:config>