springMVC项目-hibernate框架多数据源(切换数据库)配置
2017-03-27 00:00
615 查看
一个项目中需要用到多个数据库,那么此时关于粘合操作A数据库,操作B数据库时,就需要用到切换数据库了;
在此之前,特意百度搜索关于spring切换数据源的,主要为三个结果
1.JTA事务配置切换数据源(可保障切换数据源操作数据库不一致问题,但题主没有找到好的方法)
2.AOP拦截切换数据源(本次采用这种,事务一致的问题,头大,也在探索中)
这里说明下,有一篇文章也是基于AOP拦截,但其实采用注解的方式,可实现自动配置切换数据源的
有兴趣的可以看文章: http://www.cnblogs.com/liujiduo/p/5004691.html ,亲测可用;
因为注解与我自身的项目不太符合,所以没有采用;
以下是我的方式: aop拦截指定模块切换数据源;
切换原理的话,看下图(图片源于网络)
单个数据源绑定给sessionFactory,再在Dao层操作,若多个数据源的话,那不是就成了下图:
可见,sessionFactory都写死在了Dao层,若我再添加个数据源的话,则又得添加一个sessionFactory。衍生出下图:
好了,下面是具体实现方式:
1.SpringApplication.xml配置(仅dataSourceBean)
sessFactory及事务和往常一样,照样注入bean
aop切入,切换数据源(这里是,扫描了user模块下切换数据库2)
4.DataSourceChoose.java 切换数据源
temp2 :即xml>dataSource的key
DatabaseContextHolder.java
好了,总结完毕,其实内心还是倾向于JTA事务的配置方法,但JTA事务配置,网络各种问题,没有成功案例,基于项目进度紧,待后期有时间,在去切换; 毕竟以上的实现方式一般并发性不是很大,出现错误的概率很小;
在此之前,特意百度搜索关于spring切换数据源的,主要为三个结果
1.JTA事务配置切换数据源(可保障切换数据源操作数据库不一致问题,但题主没有找到好的方法)
2.AOP拦截切换数据源(本次采用这种,事务一致的问题,头大,也在探索中)
这里说明下,有一篇文章也是基于AOP拦截,但其实采用注解的方式,可实现自动配置切换数据源的
@DataSource("dataSource2")
有兴趣的可以看文章: http://www.cnblogs.com/liujiduo/p/5004691.html ,亲测可用;
因为注解与我自身的项目不太符合,所以没有采用;
以下是我的方式: aop拦截指定模块切换数据源;
切换原理的话,看下图(图片源于网络)
单个数据源绑定给sessionFactory,再在Dao层操作,若多个数据源的话,那不是就成了下图:
可见,sessionFactory都写死在了Dao层,若我再添加个数据源的话,则又得添加一个sessionFactory。衍生出下图:
好了,下面是具体实现方式:
1.SpringApplication.xml配置(仅dataSourceBean)
<!-- 数据源公用属性 --> <bean id="commDataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close" > <!--连接池中保留的最小连接数。 --> <property name="minPoolSize"> <value>${jdbc.pool.minPoolSize}</value> </property> <!--连接池中保留的最大连接数。Default: 15 --> <property name="maxPoolSize"> <value>${jdbc.pool.maxPoolSize}</value> </property> <!--初始化时获取的连接数,取值应在minPoolSize与maxPoolSize之间。Default: 3 --> <property name="initialPoolSize"> <value>${jdbc.pool.initialPoolSize}</value> </property> <!--最大空闲时间,60秒内未使用则连接被丢弃。若为0则永不丢弃。Default: 0 --> <property name="maxIdleTime"> <value>60</value> </property> <!--当连接池中的连接耗尽的时候c3p0一次同时获取的连接数。Default: 3 --> <property name="acquireIncrement"> <value>5</value> </property> <!-- JDBC的标准参数,用以控制数据源内加载的PreparedStatements数量。但由于预缓存的statements 属于单个connection而不是整个连接池。所以设置这个参数需要考虑到多方面的因素。 如果maxStatements与maxStatementsPerConnection均为0,则缓存被关闭。Default: 0 --> <property name="maxStatements"> <value>0</value> </property> <!--每60秒检查所有连接池中的空闲连接。Default: 0 --> <property name="idleConnectionTestPeriod"> <value>60</value> </property> <!--定义在从数据库获取新连接失败后重复尝试的次数。Default: 30 --> <property name="acquireRetryAttempts"> <value>10</value> </property> <!--重新尝试的时间间隔,默认为:1000毫秒--> <property name="acquireRetryDelay" value="1000" /> <!-- 获取连接失败将会引起所有等待连接池来获取连接的线程抛出异常。但是数据源仍有效 保留,并在下次调用getConnection()的时候继续尝试获取连接。如果设为true,那么在尝试 获取连接失败后该数据源将申明已断开并永久关闭。Default: false --> <property name="breakAfterAcquireFailure"> <value>false</value> </property> <!-- 因性能消耗大请只在需要的时候使用它。如果设为true那么在每个connection提交的 时候都将校验其有效性。建议使用idleConnectionTestPeriod或automaticTestTable 等方法来提升连接测试的性能。Default: false --> <property name="testConnectionOnCheckout"> <value>false</value> </property> <!-- 将连接放回池时异步检测连接有效性如无效则重连 --> <property name="testConnectionOnCheckin"> <value>true</value> </property> </bean> <!-- 配置数据源 --> <bean id="dataSource1" parent="commDataSource"> <property name="driverClass"> <value>${jdbc.driverClassName}</value> </property> <property name="jdbcUrl"> <value>${jdbc.url}</value> </property> <property name="user"> <value>${jdbc.username}</value> </property> <property name="password"> <value>${jdbc.password}</value> </property> </bean> <bean id="dataSource2" parent="commDataSource"> <property name="driverClass"> <value>${jdbc.driverClassName2}</value> </property> <property name="jdbcUrl"> <value>${jdbc.url2}</value> </property> <property name="user"> <value>${jdbc.username2}</value> </property> <property name="password"> <value>${jdbc.password2}</value> </property> </bean> <bean id="dataSource" class="cn.XXX.XXX.base.datasource.DynamicDataSource"> <property name="targetDataSources"> <map key-type="java.lang.String"> <entry value-ref="dataSource1" key="temp1"></entry> <entry value-ref="dataSource2" key="temp2"></entry> </map> </property> <property name="defaultTargetDataSource" ref="dataSource1"> </property> </bean>
sessFactory及事务和往常一样,照样注入bean
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> <property name="packagesToScan" value="cn.*.*.*.beans,cn.*.*.*.beans.po,cn.*.*.*.model" /> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop> <prop key="hibernate.show_sql">true</prop> <prop key="hibernate.autoReconnect">true</prop> <prop key="javax.persistence.validation.mode">none</prop> <!-- <prop key="hibernate.connection.autocommit">false</prop> --> <!--<prop key="hibernate.current_session_context_class">thread</prop> --></props> </property> </bean> <!-- 事务管理器(在service层面上实现事务管理) --> <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory" /> </bean> <!-- 事物模板 --> <bean id="transactionTemplate" class="org.springframework.transaction.support.TransactionTemplate"> <property name="transactionManager" ref="transactionManager" /> </bean> <bean id="hibernateTemplate" class="org.springframework.orm.hibernate3.HibernateTemplate"> <property name="sessionFactory" ref="sessionFactory" /> </bean> <aop:aspectj-autoproxy proxy-target-class="true"/> <!-- 注解事务支持 --> <tx:annotation-driven transaction-manager="transactionManager"/> <!-- 事务通知 --> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="save*" propagation="REQUIRED" isolation="DEFAULT"/> <tx:method name="add*" propagation="REQUIRED" isolation="DEFAULT"/> <tx:method name="edit*" propagation="REQUIRED" isolation="DEFAULT"/> <tx:method name="remove*" propagation="REQUIRED" isolation="DEFAULT"/> <tx:method name="*Tran" propagation="REQUIRED" isolation="DEFAULT" /> <tx:method name="*" propagation="REQUIRED" isolation="DEFAULT" /> </tx:attributes> </tx:advice>
aop切入,切换数据源(这里是,扫描了user模块下切换数据库2)
<!-- 配置事务拦截器拦截哪些类的哪些方法,一般设置成拦截Service --> <aop:config proxy-target-class="true"> <aop:pointcut id="serviceMethod" expression=" execution(* cn.*.*.*.service..*.*(..)) or execution(* cn.*.*.*.*.impl..*.*(..))" /> <aop:advisor pointcut-ref="serviceMethod" advice-ref="txAdvice" /> </aop:config> <!-- 数据源切换类 --> <bean id="dataSourceChoose" class="cn.XXX.XXXX.datasource.DataSourceChoose" /> <aop:config proxy-target-class="true"> <!-- usermanager 下的方法: 指定扫码in,注入数据源yuntu --> <aop:pointcut id="userServiceMethod" expression=" execution(* cn.*.*.user.service..*.*(..)) or execution(* cn.*.*.*.user.impl..*.*(..))" /> <aop:aspect ref="dataSourceChoose" order="1"> <aop:before method="before" pointcut-ref="userServiceMethod" /> <aop:after method="after" pointcut-ref="userServiceMethod" /> </aop:aspect> </aop:config>
4.DataSourceChoose.java 切换数据源
temp2 :即xml>dataSource的key
import org.aspectj.lang.JoinPoint; import org.springframework.stereotype.Component; @Component public class DataSourceChoose { public void before(JoinPoint jp){ String methodName = jp.getSignature().getName(); System.out.println("(扫描指定模块方法,切入user数据源):"+methodName); DatabaseContextHolder.setCustomerType("temp2"); } public void after(){ DatabaseContextHolder.clearCustomerType(); System.out.println("切换user数据源完毕,清除数据源,重新绑定回默认数据源"); } }
DatabaseContextHolder.java
public class DatabaseContextHolder{ 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(); } }
好了,总结完毕,其实内心还是倾向于JTA事务的配置方法,但JTA事务配置,网络各种问题,没有成功案例,基于项目进度紧,待后期有时间,在去切换; 毕竟以上的实现方式一般并发性不是很大,出现错误的概率很小;
相关文章推荐
- SpringMVC配置双数据源,一个java项目同时连接两个数据库
- 一个项目中hibernate框架下配置多个数据库
- springMVC框架的搭建最简单项目(没有数据库的配置)
- SpringMVC配置双数据源,一个java项目同时连接两个数据库
- springMvc-Mybatis 实现主从数据库/多数据源切换配置
- 项目总结SpringMVC+hibernate框架 原理(MVC) 模块配置文件(4)
- IntelliJ IDEA 13操作-- 3.项目集成spring、springMVC、hibernate等框架
- Spring3.3 整合 Hibernate3、MyBatis3.2 配置多数据源/动态切换数据源 方法
- Spring3.3 整合 Hibernate3、MyBatis3.2 配置多数据源/动态切换数据源 方法
- UserDao找不到,框架集成,springMVC和hibernate和Spring 保错。tomcat保错。。UserDao 找不到在spring-servlet.xml配置
- Spring3.3 整合 Hibernate3、MyBatis3.2 配置多数据源/动态切换数据源 方法
- Spring3.3 整合 Hibernate3、MyBatis3.2 配置多数据源/动态切换数据源 方法(转)
- 项目总结SpringMVC+hibernate框架 原理(MVC) applicationContext.xml 文件(3)
- Spring+Hibernate框架下MySql读写分离,主从数据库配置
- Spring3.3 整合 Hibernate3、MyBatis3.2 配置多数据源/动态切换数据源方法
- 流行Java开源数据库框架项目 - Hibernate快速简单入门
- 在spring配置DataSource数据源进行数据库操作及spring结合hibernate操作
- Spring3.3 整合 Hibernate3、MyBatis3.2 配置多数据源/动态切换数据源 方法
- 项目总结SpringMVC+hibernate框架 web.xml 分析(2)
- Spring3.3 整合 Hibernate3、MyBatis3.2 配置多数据源/动态切换数据源 方法