随笔-57  评论-117  文章-1  trackbacks-0

一、缘由

上一篇文章Spring3.3 整合 Hibernate3、MyBatis3.2 配置多数据源/动态切换数据源 方法介绍到了怎么样在Sping、MyBatis、Hibernate整合的应用中动态切换DataSource数据源的方法,但最终遗留下一个问题:不能切换数据库方言。数据库方言可能在当前应用的架构中意义不是很大,但是如果单纯用MyBatis或Hibernate做数据库持久化操作,还是要处理这一问题。

 

那么下面将介绍怎么样动态切换SessionFactory,为什么要切换SessionFactory?

因为这里切换SessionFactory就可以实现多数据源和多个SessionFactory,每个SessionFactory有自己独立的数据库配置和SessionFactory的相关配置。我们的数据库方言就配置在SessionFactory这里,所以实现了切换SessionFactory也就实现了切换数据库方言的问题。这个主要是针对Hibernate来操作的,而MyBatis则需要动态切换SqlSessionFactory才行。

 

二、实现代码

1、定义全局切换SessionFactory的工具

package com.hoo.framework.spring.support;
 
/**
 * <b>function:</b> 多数据源
 * @author hoojo
 * @createDate 2013-9-27 上午11:36:57
 * @file CustomerContextHolder.java
 * @package com.hoo.framework.spring.support
 * @project SHMB
 * @blog http://blog.csdn.net/IBM_hoojo
 * @email hoojo_@126.com
 * @version 1.0
 */
public abstract class CustomerContextHolder {
 
    public final static String SESSION_FACTORY_MYSQL = "mysql";
    public final static String SESSION_FACTORY_ORACLE = "oracle";
    
    private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>();  
    
    public static void setCustomerType(String customerType) {  
        contextHolder.set(customerType);  
    }  
      
    public static String getCustomerType() {  
        return contextHolder.get();  
    }  
      
    public static void clearCustomerType() {  
        contextHolder.remove();  
    }  
}

同样上面的静态变量和前一文章中介绍的一致,它需要和下面配置文件中的SessionFactory的key对应。

2、实现自己的SessionFactory

定义好接口

package com.hoo.framework.spring.support.core;
 
import org.hibernate.SessionFactory;
 
/**
 * <b>function:</b> 动态SessionFactory接口
 * @author hoojo
 * @createDate 2013-10-12 下午03:29:52
 * @file DynamicSessionFactory.java
 * @package com.hoo.framework.spring.support.core
 * @project SHMB
 * @blog http://blog.csdn.net/IBM_hoojo
 * @email hoojo_@126.com
 * @version 1.0
 */
public interface DynamicSessionFactory extends SessionFactory {
    
    public SessionFactory getHibernateSessionFactory();
}

 

实现接口

package com.hoo.framework.spring.support.core;
 
import java.io.Serializable;
import java.sql.Connection;
import java.util.Map;
import java.util.Set;
import javax.naming.NamingException;
import javax.naming.Reference;
import org.hibernate.Cache;
import org.hibernate.HibernateException;
import org.hibernate.Interceptor;
import org.hibernate.SessionFactory;
import org.hibernate.StatelessSession;
import org.hibernate.TypeHelper;
import org.hibernate.classic.Session;
import org.hibernate.engine.FilterDefinition;
import org.hibernate.metadata.ClassMetadata;
import org.hibernate.metadata.CollectionMetadata;
import org.hibernate.stat.Statistics;
import com.hoo.framework.spring.support.CustomerContextHolder;
 
/**
 * <b>function:</b> 动态数据源实现
 * @author hoojo
 * @createDate 2013-10-12 下午03:31:31
 * @file DynamicSessionFactoryImpl.java
 * @package com.hoo.framework.spring.support.core
 * @project SHMB
 * @blog http://blog.csdn.net/IBM_hoojo
 * @email hoojo_@126.com
 * @version 1.0
 */
@SuppressWarnings({ "unchecked", "deprecation" })
public class DynamicSessionFactoryImpl implements DynamicSessionFactory {
 
    private static final long serialVersionUID = 5384069312247414885L;
    
    private Map<Object, SessionFactory> targetSessionFactorys;  
    private SessionFactory defaultTargetSessionFactory; 
    
    /**
     * @see com.hoo.framework.spring.support.core.DynamicSessionFactory#getHibernateSessionFactory()
     * <b>function:</b> 重写这个方法,这里最关键
     * @author hoojo
     * @createDate 2013-10-18 上午10:45:25
     */
    @Override
    public SessionFactory getHibernateSessionFactory() {
        SessionFactory targetSessionFactory = targetSessionFactorys.get(CustomerContextHolder.getCustomerType());  
        if (targetSessionFactory != null) {  
            return targetSessionFactory;  
        } else if (defaultTargetSessionFactory != null) {  
            return defaultTargetSessionFactory;  
        }  
        return null;
    }
 
 
    @Override
    public void close() throws HibernateException {
        this.getHibernateSessionFactory().close();
    }
 
    @Override
    public boolean containsFetchProfileDefinition(String s) {
        return this.getHibernateSessionFactory().containsFetchProfileDefinition(s);
    }
 
    @Override
    public void evict(Class clazz) throws HibernateException {
        this.getHibernateSessionFactory().evict(clazz);
    }
 
    @Override
    public void evict(Class clazz, Serializable serializable) throws HibernateException {
        this.getHibernateSessionFactory().evict(clazz, serializable);
    }
 
    @Override
    public void evictCollection(String s) throws HibernateException {
        this.getHibernateSessionFactory().evictCollection(s);
    }
 
    @Override
    public void evictCollection(String s, Serializable serializable) throws HibernateException {
        this.getHibernateSessionFactory().evictCollection(s, serializable);
    }
 
    @Override
    public void evictEntity(String entity) throws HibernateException {
        this.getHibernateSessionFactory().evictEntity(entity);
    }
 
    @Override
    public void evictEntity(String entity, Serializable serializable) throws HibernateException {
        this.getHibernateSessionFactory().evictEntity(entity, serializable);
    }
 
    @Override
    public void evictQueries() throws HibernateException {
        this.getHibernateSessionFactory().evictQueries();        
    }
 
    @Override
    public void evictQueries(String queries) throws HibernateException {
        this.getHibernateSessionFactory().evictQueries(queries);        
    }
 
    @Override
    public Map<String, ClassMetadata> getAllClassMetadata() {
        return this.getHibernateSessionFactory().getAllClassMetadata();
    }
 
    @Override
    public Map getAllCollectionMetadata() {
        return this.getHibernateSessionFactory().getAllClassMetadata();
    }
 
    @Override
    public Cache getCache() {
        return this.getHibernateSessionFactory().getCache();
    }
 
    @Override
    public ClassMetadata getClassMetadata(Class clazz) {
        return this.getHibernateSessionFactory().getClassMetadata(clazz);
    }
 
    @Override
    public ClassMetadata getClassMetadata(String classMetadata) {
        return this.getHibernateSessionFactory().getClassMetadata(classMetadata);
    }
 
    @Override
    public CollectionMetadata getCollectionMetadata(String collectionMetadata) {
        return this.getHibernateSessionFactory().getCollectionMetadata(collectionMetadata);
    }
 
    @Override
    public Session getCurrentSession() throws HibernateException {
        return this.getHibernateSessionFactory().getCurrentSession();
    }
 
    @Override
    public Set getDefinedFilterNames() {
        return this.getHibernateSessionFactory().getDefinedFilterNames();
    }
 
    @Override
    public FilterDefinition getFilterDefinition(String definition) throws HibernateException {
        return this.getHibernateSessionFactory().getFilterDefinition(definition);
    }
 
    @Override
    public Statistics getStatistics() {
        return this.getHibernateSessionFactory().getStatistics();
    }
 
    @Override
    public TypeHelper getTypeHelper() {
        return this.getHibernateSessionFactory().getTypeHelper();
    }
 
    @Override
    public boolean isClosed() {
        return this.getHibernateSessionFactory().isClosed();
    }
 
    @Override
    public Session openSession() throws HibernateException {
        return this.getHibernateSessionFactory().openSession();
    }
 
    @Override
    public Session openSession(Interceptor interceptor) throws HibernateException {
        return this.getHibernateSessionFactory().openSession(interceptor);
    }
 
    @Override
    public Session openSession(Connection connection) {
        return this.getHibernateSessionFactory().openSession(connection);
    }
 
    @Override
    public Session openSession(Connection connection, Interceptor interceptor) {
        return this.getHibernateSessionFactory().openSession(connection, interceptor);
    }
 
    @Override
    public StatelessSession openStatelessSession() {
        return this.getHibernateSessionFactory().openStatelessSession();
    }
 
    @Override
    public StatelessSession openStatelessSession(Connection connection) {
        return this.getHibernateSessionFactory().openStatelessSession(connection);
    }
 
    @Override
    public Reference getReference() throws NamingException {
        return this.getHibernateSessionFactory().getReference();
    }
 
    public void setTargetSessionFactorys(Map<Object, SessionFactory> targetSessionFactorys) {
        this.targetSessionFactorys = targetSessionFactorys;
    }
 
    public void setDefaultTargetSessionFactory(SessionFactory defaultTargetSessionFactory) {
        this.defaultTargetSessionFactory = defaultTargetSessionFactory;
    }
 
}

上面最重要的就是getHibernateSessionFactory重写这个方法,其他方法和原来实现的无异。重写这个方法后利用CustomerContextHolder动态设置SessionFactory类型就可以动态的切换SessionFactory。

3、动态的事务管理器,因为我们这里是动态切换SessionFactory,所以事务这块也需要动态切换SessionFactory来完成事务的操作。

package com.hoo.framework.spring.support.tx;
 
import javax.sql.DataSource;
import org.hibernate.SessionFactory;
import org.springframework.orm.hibernate3.HibernateTransactionManager;
import org.springframework.orm.hibernate3.SessionFactoryUtils;
import com.hoo.framework.spring.support.core.DynamicSessionFactory;
 
/**
 * <b>function:</b> 重写HibernateTransactionManager事务管理器,实现自己的动态的事务管理器
 * @author hoojo
 * @createDate 2013-10-12 下午03:54:02
 * @file DynamicTransactionManager.java
 * @package com.hoo.framework.spring.support.tx
 * @project SHMB
 * @blog http://blog.csdn.net/IBM_hoojo
 * @email hoojo_@126.com
 * @version 1.0
 */
public class DynamicTransactionManager extends HibernateTransactionManager {
 
    private static final long serialVersionUID = -4655721479296819154L;
    
    /** 
     * @see org.springframework.orm.hibernate4.HibernateTransactionManager#getDataSource()
     * <b>function:</b> 重写
     * @author hoojo
     * @createDate 2013-10-12 下午03:55:24
     */
    @Override
    public DataSource getDataSource() {
        return SessionFactoryUtils.getDataSource(getSessionFactory());
    }
 
    /** 
     * @see org.springframework.orm.hibernate4.HibernateTransactionManager#getSessionFactory()
     * <b>function:</b> 重写
     * @author hoojo
     * @createDate 2013-10-12 下午03:55:24
     */
    @Override
    public SessionFactory getSessionFactory() {
        DynamicSessionFactory dynamicSessionFactory = (DynamicSessionFactory) super.getSessionFactory();  
        SessionFactory hibernateSessionFactory = dynamicSessionFactory.getHibernateSessionFactory();  
        return hibernateSessionFactory;  
    }
}

这里主要重写getDataSource()/getSessionFactory()这两个方法,getSessionFactory方法是利用我们上面定义的接口来动态获取我们在上下文(CustomerContextHolder)中定义切换的SessionFactory对象。而getDataSource则是获得动态SessionFactory的DataSource,这里也不难理解。

4、至此,重写的接口和实现都完成,下面开始配置相关的代码

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:aop="http://www.springframework.org/schema/aop" 
    xmlns:tx="http://www.springframework.org/schema/tx"
    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.2.xsd 
    http://www.springframework.org/schema/aop 
    http://www.springframework.org/schema/aop/spring-aop-3.2.xsd 
    http://www.springframework.org/schema/tx  
    http://www.springframework.org/schema/tx/spring-tx-3.2.xsd ">
    
    <!-- 配置c3p0数据源 -->
    <bean id="dataSourceOracle" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
        <property name="driverClass" value="${datasource.driver}"/>
        <property name="jdbcUrl" value="${datasource.url}"/>
        <property name="user" value="${datasource.username}"/>
        <property name="password" value="${datasource.password}"/>
                
        <property name="acquireIncrement" value="${c3p0.acquireIncrement}"/>
        <property name="initialPoolSize" value="${c3p0.initialPoolSize}"/>
        <property name="minPoolSize" value="${c3p0.minPoolSize}"/>
        <property name="maxPoolSize" value="${c3p0.maxPoolSize}"/>
        <property name="maxIdleTime" value="${c3p0.maxIdleTime}"/>
        <property name="idleConnectionTestPeriod" value="${c3p0.idleConnectionTestPeriod}"/>
        <property name="maxStatements" value="${c3p0.maxStatements}"/>
        <property name="numHelperThreads" value="${c3p0.numHelperThreads}"/>
        <property name="preferredTestQuery" value="${c3p0.preferredTestQuery}"/>
        <property name="testConnectionOnCheckout" value="${c3p0.testConnectionOnCheckout}"/>
    </bean>
    
    <bean id="dataSourceMySQL" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
        <property name="driverClass" value="com.mysql.jdbc.Driver"/>
        <property name="jdbcUrl" value="jdbc:mysql://172.31.108.178:3306/world?useUnicode=true&amp;characterEncoding=UTF-8&amp;zeroDateTimeBehavior=convertToNull"/>
        <property name="user" value="root"/>
        <property name="password" value="jp2011"/>
                
        <property name="acquireIncrement" value="${c3p0.acquireIncrement}"/>
        <property name="initialPoolSize" value="${c3p0.initialPoolSize}"/>
        <property name="minPoolSize" value="${c3p0.minPoolSize}"/>
        <property name="maxPoolSize" value="${c3p0.maxPoolSize}"/>
        <property name="maxIdleTime" value="${c3p0.maxIdleTime}"/>
        <property name="idleConnectionTestPeriod" value="${c3p0.idleConnectionTestPeriod}"/>
        <property name="maxStatements" value="${c3p0.maxStatements}"/>
        <property name="numHelperThreads" value="${c3p0.numHelperThreads}"/>
        <property name="preferredTestQuery" value="${c3p0.preferredTestQuery}"/>
        <property name="testConnectionOnCheckout" value="${c3p0.testConnectionOnCheckout}"/>
    </bean>
    
    <!-- Annotation 配置sessionFactory,配置数据库连接,注入hibernate数据库配置 -->
    <bean id="mySQLSessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
        <property name="dataSource" ref="dataSourceMySQL"/>
        <property name="packagesToScan" value="com.hoo.**.mysqlentity"/>
        <property name="annotatedClasses">
            <array>
                <value>com.hoo.common.entity.IDGenerator</value>
            </array>
        </property>
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
                <!-- 链接释放策略 on_close | after_transaction | after_statement | auto  -->
                <prop key="hibernate.connection.release_mode">after_transaction</prop>
                <prop key="hibernate.show_sql">true</prop>
                <prop key="hibernate.format_sql">true</prop>
            </props>
        </property>
    </bean>
    
    <!-- Annotation 配置sessionFactory,配置数据库连接,注入hibernate数据库配置 -->
    <bean id="oracleSessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
        <property name="dataSource" ref="dataSourceOracle"/>
        <property name="packagesToScan" value="com.hoo.**.entity"/>
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">org.hibernate.dialect.OracleDialect</prop>
                <prop key="hibernate.connection.release_mode">after_transaction</prop>
                <prop key="hibernate.show_sql">true</prop>
                <prop key="hibernate.format_sql">true</prop>
                <!--prop key="hibernate.hbm2ddl.auto">update</prop-->
            </props>
        </property>
    </bean>
    
    <!-- 动态SessionFactory -->
    <bean id="sessionFactory" class="com.hoo.framework.spring.support.core.DynamicSessionFactoryImpl">
        <property name="defaultTargetSessionFactory" ref="oracleSessionFactory"/>
        <property name="targetSessionFactorys">
            <map>     
                <entry value-ref="oracleSessionFactory" key="oracle"/>
                <entry value-ref="mySQLSessionFactory" key="mysql"/>
            </map> 
        </property>
    </bean>
 
    <!-- 自定义动态切换SessionFactory事务管理器,注入sessionFactory  -->
    <bean id="transactionManager" class="com.hoo.framework.spring.support.tx.DynamicTransactionManager">
        <property name="sessionFactory" ref="sessionFactory" />
    </bean>
    
    <!-- 配置事务的传播特性 -->
    <tx:advice id="txAdvice" transaction-manager="transactionManager">
        <tx:attributes>
            <tx:method name="add*" propagation="REQUIRED" rollback-for="java.lang.Exception"/>
            <tx:method name="edit*" propagation="REQUIRED" rollback-for="java.lang.Exception"/>
            <tx:method name="remove*" propagation="REQUIRED" rollback-for="java.lang.Exception"/>
            <tx:method name="execute*" propagation="REQUIRED" rollback-for="java.lang.Exception"/>
            <tx:method name="*" read-only="true" />
        </tx:attributes>
    </tx:advice>
    
    <!-- 配置那些类、方法纳入到事务的管理 -->
    <aop:config>
        <aop:pointcut expression="execution(* com.hoo.**.service.impl.*.*(..))" id="transactionManagerMethod"/>
        <aop:advisor advice-ref="txAdvice" pointcut-ref="transactionManagerMethod" />
    </aop:config>
</beans>

配置也和我们之前的配置差不多,就是事务管理器部分注入的SessionFactory是我们自己定义的。

5、简单测试

@Test
public void testAdd() {
    // 主要就是这行代码 它才是完成SessionFactory的切换
    CustomerContextHolder.setCustomerType(CustomerContextHolder.SESSION_FACTORY_MYSQL);
    
    DeviceInfo entity = new DeviceInfo();
    entity.setSbbh(System.currentTimeMillis() + "");
    entity.setIpdz("my ip address2");
    entity.setJd(1234);
    try {
        service.add(entity);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

经过测试发现可以查询数据,利用hibernate查询分页也可以生成对应数据库的分页语句。同样在服务层的方法中添加完操作后,特意抛出一个异常,数据也能正常回滚操作,所以DynamicTransactionManager也是起到了该有的作用!

这里我的测试用例是手动切换CustomerContextHolder.setCustomerType的,但实际开发中我们还是得用Spring的Aop中的Interceptor进行切面编程,完成动态切换SessionFactory。上一篇文章Spring3.3 整合 Hibernate3、MyBatis3.2 配置多数据源/动态切换数据源 方法已经提到了(读者可以参考该篇博文中的第二节的3、7小节DataSourceMethodInterceptor MultipleDataSourceInterceptor),这里就不再赘述!

 

三、引发的问题

上述的实现如果在使用不当的情况下,在实际开发中很可能存在一些问题!

问题1是这样的,通常事务是在Service这层完成,这个应该是没有异议。倘若是这样的话,问题便出现了。而通常我们在MVC中的视图层中仅仅会调用Service中一个方法来完成所有当前业务的处理。如果这个Service中同时操作dbA、dbB两个数据库,事务提交的时候是用哪个数据库的事务呢?所以我们把不同数据库的操作放在一个方法,就会出现事务的问题的,除非两个数据库的事务能够同时回滚!

大致情景是:Service中的add4Oracle操作Oracle数据库,Service中的add4MySQL操作MySQL数据库,最后把Service中的add4Oracle、add4MySQL方法放到一个operation方法中,MVC视图层的业务控制调用Service中的operation。像这样的情况,如果add4Oracle或add4MySQL方法中的某一个方法出现异常,就需要把两个数据库事务都回滚。

解决办法就是在Service或Dao中的一个方法中同时操作两个数据库,手动完成事务控制。出现异常就全部回滚,没有异常就全部提交,只能这样牺牲下。

 

问题2是利用拦截器不能同时切换一个方法操作两个数据库的可能,例如一个service中的query方法即需要用query MySQL,也需要query Oracle。那么解决办法就是在query方法中调用当前service的query4Oracle和query4Oracle,那样绕过去还是能利用拦截器进行动态切换的。

 

四、总结

要完成数据库方言的切换,我们就需要配置多个SessionFactory利用自己实现的DynamicSessionFactory和CustomerContextHolder完成SessionFactory的切换。利用DynamicTransactionManager完成当前Session的事务操作。通过对这些对象的操作和配置,最终可以完成SessionFactory的动态切换。实际使用中虽然有些问题出现,但是最终还是有解决方案,尽管有些不完美。所谓的完美的东西总有它不完美的地方,这样才算完美,比如断臂的维纳斯女神~!



作者:hoojo
出处:
blog:http://blog.csdn.net/IBM_hoojo
         http://hoojo.cnblogs.com
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。


版权所有,转载请注明出处 本文出自:
分享道版权所有,欢迎转载,转载请注明出处,谢谢
posted on 2013-10-18 12:13 hoojo 阅读(8040) 评论(8)  编辑  收藏 所属分类: FrameWork IntegrationHibernateJavaEEOthersRIA 【富互联网程序】Spring

评论:
# re: Spring3 整合Hibernate3.5 动态切换SessionFactory (切换数据库方言) 2013-10-19 11:20 | 魏五锁业
这个主要是针对Hibernate来操作的  回复  更多评论
  
# re: Spring3 整合Hibernate3.5 动态切换SessionFactory (切换数据库方言) 2013-10-23 14:48 | kuitos
可以采用分布式事务的方式解决一个service多数据源操作的问题  回复  更多评论
  
# re: Spring3 整合Hibernate3.5 动态切换SessionFactory (切换数据库方言) 2013-10-23 14:50 | kuitos
如atomikos @kuitos  回复  更多评论
  
# re: Spring3 整合Hibernate3.5 动态切换SessionFactory (切换数据库方言) 2013-10-28 03:56 | creation
Many thanks for making the truthful effort to explain this. I feel very strong about it and would like to read more. If you
can, as you find out more in depth knowledge, would you mind posting more posts similar to this one with more information.
http://www.qu.edu.sa  回复  更多评论
  
# re: Spring3 整合Hibernate3.5 动态切换SessionFactory (切换数据库方言) 2013-11-30 00:05 | gen
按照作者的顺序写了一遍,但遇到查询<may-to-one>or<one-to-may>且@ManyToOne(fetch = FetchType.LAZY)时抛出异常:
org.hibernate.LazyInitializationException: could not initialize proxy - no Session
at org.hibernate.proxy.AbstractLazyInitializer.initialize(AbstractLazyInitializer.java:164)
at org.hibernate.proxy.AbstractLazyInitializer.getImplementation(AbstractLazyInitializer.java:285)
at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:185)
at jeecg.system.pojo.base.TSDepart_$$_javassist_18.getDepartname(TSDepart_$$_javassist_18.java)
at jeecg.system.controller.core.LoginController.checkuser(LoginController.java:113)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
at java.lang.reflect.Method.invoke(Method.java:597)
at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.invokeHandlerMethod(HandlerMethodInvoker.java:176)
at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.java:436)
at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(AnnotationMethodHandlerAdapter.java:424)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:923)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:852)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:882)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:789)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:710)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:803)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at com.alibaba.druid.support.http.WebStatFilter.doFilter(WebStatFilter.java:140)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:88)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.springframework.orm.hibernate4.support.OpenSessionInViewFilter.doFilterInternal(OpenSessionInViewFilter.java:119)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:230)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:104)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:261)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:844)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:581)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:447)
at java.lang.Thread.run(Thread.java:662)
  回复  更多评论
  
# re: Spring3 整合Hibernate3.5 动态切换SessionFactory (切换数据库方言)[未登录] 2014-04-10 14:16 | sea
楼主您好,用上面的方法,我的sessionfactory老不能自动切换,只第一次访问时候切换成功,后面再访问都是用defaultTargetSessionFactory,请问楼主遇到过吗,谢谢!方便的话加q:15901182  回复  更多评论
  
# re: Spring3 整合Hibernate3.5 动态切换SessionFactory (切换数据库方言)[未登录] 2015-04-28 17:11 | david
@kuitos
可以聚个例子么  回复  更多评论
  
# re: Spring3 整合Hibernate3.5 动态切换SessionFactory (切换数据库方言) 2016-04-18 22:53 | landray
楼主能提供下代码下载地址不  回复  更多评论
  

只有注册用户登录后才能发表评论。


网站导航: