Spring+Hibernate框架下Mysql读写分离、主从数据库配置

1. 配置AOP切面类 DataSourceAdvice.java

package until;
import java.lang.reflect.Method;
import org.springframework.aop.AfterReturningAdvice;
import org.springframework.aop.MethodBeforeAdvice;
import org.springframework.aop.ThrowsAdvice;
public class DataSourceAdvice implements MethodBeforeAdvice, AfterReturningAdvice, ThrowsAdvice {
// service方法执行之前被调用
public void before(Method method, Object[] args, Object target) throws Throwable {
System.out.println("切入点: " + target.getClass().getName() + "类中" + method.getName() + "方法");
if(method.getName().startsWith("add")
|| method.getName().startsWith("create")
|| method.getName().startsWith("save")
|| method.getName().startsWith("edit")
|| method.getName().startsWith("update")
|| method.getName().startsWith("delete")
|| method.getName().startsWith("remove")){
System.out.println("切换到: master");
DataSourceSwitcher.setMaster();
}
else {
System.out.println("切换到: slave");
DataSourceSwitcher.setSlave();
}
}
// service方法执行完之后被调用
public void afterReturning(Object arg0, Method method, Object[] args, Object target) throws Throwable {
}
// 抛出Exception之后被调用
public void afterThrowing(Method method, Object[] args, Object target, Exception ex) throws Throwable {
DataSourceSwitcher.setSlave();
System.out.println("出现异常,切换到: slave");
}
}
2.数据源选择类 DataSourceSwitcher.java
package until;
import org.springframework.util.Assert;
public class DataSourceSwitcher {
@SuppressWarnings("rawtypes")
private static final ThreadLocal contextHolder = new ThreadLocal();
@SuppressWarnings("unchecked")
public static void setDataSource(String dataSource) {
Assert.notNull(dataSource, "dataSource cannot be null");
contextHolder.set(dataSource);
}
public static void setMaster(){
clearDataSource();
}
public static void setSlave() {
setDataSource("slave");
}
public static String getDataSource() {
return (String) contextHolder.get();
}
public static void clearDataSource() {
contextHolder.remove();
}
}

3. DynamicDataSource.java数据源动态切换类

package until;
import java.sql.SQLFeatureNotSupportedException;
import java.util.logging.Logger;
import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
public class DynamicDataSource extends AbstractRoutingDataSource {
@Override
protected Object determineCurrentLookupKey() {
return DataSourceSwitcher.getDataSource();
}
}

4. 下面配置spring applicationContext.xml文件

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:aop="http://www.springframework.org/schema/aop"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-2.5.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-2.5.xsd">

<!-- dbcp数据源 -->
<bean id="parentDataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<!--
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://127.0.0.1:3306/readandwrite_test" />
<property name="username" value="root" />
<property name="password" value="root" />
-->
<property name="initialSize" value="10"/><!-- 初始化连接 -->
<property name="maxIdle" value="50"/><!-- 最大空闲连接 -->
<property name="minIdle" value="10"/><!-- 最小空闲连接 -->
<property name="maxActive" value="300"/><!-- 最大连接数量 -->
<property name="logAbandoned" value="true"/><!-- 是否在自动回收超时连接的时候打印连接的超时错误 -->
<property name="removeAbandoned" value="true"/><!-- 是否自动回收超时连接 -->
<property name="removeAbandonedTimeout" value="180"/><!-- 超时时间(以秒数为单位) -->
<property name="maxWait" value="1000"/> <!--超时等待时间以毫秒为单位 -->

<property name="testOnBorrow" value="false"/> <!-- 数据库连接池中取得连接时,对其的有效性进行检查 ,会影响一定性能-->
<property name="testWhileIdle" value="true"/> <!--异步Evict的TimerTask定时线程进行控制 定时对线程池中的链接进行validateObject校验-->
<property name="timeBetweenEvictionRunsMillis" value="25200000"/><!--失效检查线程运行时间间隔 大于0才会开启evict检查线程-->
<property name="validationQuery" value="select 1"/> <!-- 校验sql-->
</bean>
<!-- 主数据源-->
<bean id="masterDataSource" parent="parentDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://127.0.0.1:3306/readandwrite_test" />
<property name="username" value="root" />
<property name="password" value="root" />
</bean>
<!-- 从数据源-->
<bean id="slaveDataSource" parent="parentDataSource">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://127.0.0.1:3306/readandwrite_test" />
<property name="username" value="root" />
<property name="password" value="root" />
</bean>

<!-- 数据源动态切换 -->
<bean id="dataSource" class="until.DynamicDataSource">
<property name="targetDataSources">
<map key-type="java.lang.String">
<entry key="slave" value-ref="slaveDataSource" />
</map>
</property>
<property name="defaultTargetDataSource" ref="masterDataSource" />
</bean>

<!-- 配置sessionFactory -->
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"></property>
<property name="mappingResources">
<list>
<value>hbm/User.hbm.xml</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.show_sql">true</prop>
</props>
</property>
</bean>

<!-- 切换数据源 -->
<bean id="dataSourceAdvice" class="until.DataSourceAdvice" />
<aop:config>
<aop:advisor
pointcut="execution(* service..*Service.*(..))"
advice-ref="dataSourceAdvice" />
</aop:config>

<!-- 配置事务管理器 -->
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory">
<ref bean="sessionFactory" />
</property>
</bean>
<!--配置事务的传播特性 -->
<tx:advice id="txAdvice" transaction-manager="transactionManager">
<tx:attributes>
<!-- 对增、删、改方法进行事务支持 -->
<tx:method name="add*" propagation="REQUIRED" />
<tx:method name="create*" propagation="REQUIRED" />
<tx:method name="save*" propagation="REQUIRED" />
<tx:method name="edit*" propagation="REQUIRED" />
<tx:method name="update*" propagation="REQUIRED" />
<tx:method name="delete*" propagation="REQUIRED" />
<tx:method name="remove*" propagation="REQUIRED" />
<!-- 对查找方法进行只读事务 -->
<tx:method name="load*" propagation="SUPPORTS" read-only="true" />
<!-- 对其它方法进行只读事务 -->
<tx:method name="*" propagation="SUPPORTS" read-only="true" />
</tx:attributes>
</tx:advice>
<!--那些类的哪些方法参与事务 -->
<aop:config>
<aop:advisor
pointcut="execution(* service..*Service.*(..))"
advice-ref="txAdvice" />
<aop:advisor
pointcut="execution(* service..*ServiceImpl.*(..))"
advice-ref="txAdvice" />
</aop:config>
</beans>
时间: 2024-08-03 19:32:48

Spring+Hibernate框架下Mysql读写分离、主从数据库配置的相关文章

用Maven整合SpringMVC+Spring+Hibernate 框架,实现简单的插入数据库数据功能(二)

前一篇写的有些多,大家先看前一篇,传送门 具体的资源已将上传到资源了. 附地址:MySQL.zip启动 用Maven整合SpringMVC+Spring+Hibernate 框架 上文我们直接搭建前的准备和资源配置都写好了,下面进入具体代码编写.承接上文的小3 3.我习惯建立接口,这样对整个项目感觉更合理. (1.)建立IBaseService(业务逻辑层,有的习惯写成BaseServiceI)都可以,都是标注接口的,我只是简单的贴下代码 package com.jesus.sshframewo

使用Atlas实现MySQL读写分离+MySQL-(Master-Slave)配置

参考博文: MySQL-(Master-Slave)配置  本人按照博友北在北方的配置已成功  我使用的是 mysql5.6.27版本. 使用Atlas实现MySQL读写分离

spring学习笔记(19)mysql读写分离后端AOP控制实例

在这里,我们接上一篇文章,利用JNDI访问应用服务器配置的两个数据源来模拟同时操作不同的数据库如同时操作mysql和oracle等.实际上,上个例子可能用来模拟mysql数据库主从配置读写分离更贴切些.既然如此,在本例中,我们就完成读写分离的模拟在web端的配置实例. 续上次的例子,关于JNDI数据源的配置和spring datasource的配置这里不再重复.下面着重加入AOP实现DAO层动态分库调用.可先看上篇文章<spring学习笔记(18)使用JNDI模拟访问应用服务器多数据源实例 >

mysql读写分离-mysql-proxy的配置

读写分离介绍 读写分离适合于读特别多的场景,一台只写,一台只读,提高读的效率. 实现的思路 前提: 读写分离建立在两台机器上,并且这两台机器是做了主从复制的,主库只写,从库只读,从而实现的. 实现: 第一种: 在主库创建一个只写的用户,而从库创建一个只写的用户,让程序去连接不同的服务器可达到读写分离的效果. 第二种: 通过代理软件,这种的好处是程序不需要关心写和读的操作分别连接的哪台服务器,只管往代理机器发即可,代理软件进行判断发往不同的mysql服务器. 通过代理实现的软件有:mysql-pr

用Maven整合SpringMVC+Spring+Hibernate 框架

用Maven整合SpringMVC+Spring+Hibernate 框架, 实现简单的插入数据库数据 一.搭建开始前的准备 1.打开MyEclipse新建Maven项目.File>New>Other(或Ctrl+N)>Maven Project:然后我们用default Workspace就行了(注意Location的路径,区分目录名和项目名):然后再Filter中输入webapp,我们选择org.apache.maven.archetypes 下的maven-archetype-we

详解MySQL读写分离

主从复制的原理MySQL的主从复制和读写分离两者有着紧密的联系,首先要部署主从复制,只有主从复制完成了才能在此基础上进行数据的读写分离. 读写分离的原理简单来说,读写分离就是只在主服务器上写,只在从服务器上读.基本原理是让主数据库处理事务性查询,而从服务器处理select查询.数据库复制被用来把事务性查询导致的变更同步到从数据库中. 基于中间代理层实现:代理一般位于客户端和服务器之间,代理服务器接到客户段的请求通过判断后转发到后端数据库. 实验环境1 一台centos7作为客户端测试IP为192

使用Spring实现MySQL读写分离

1. 为什么要进行读写分离 大量的JavaWeb应用做的是IO密集型任务, 数据库的压力较大, 需要分流 大量的应用场景, 是读多写少, 数据库读取的压力更大 一个很自然的思路是使用一主多从的数据库集群: 一个是主库,负责写入数据:其它都是从库,负责读取数据. 主从库数据同步. mysql原生支持主从复制 mysql主(称master)从(称slave)复制的原理:1.master将数据改变记录到二进制日志(bin log)中,  这些记录叫binary log events2.slave将ma

《Mycat学习笔记》 第二篇. MySql 读写分离与日志分析——主从多结点

1    环境说明 接上篇环境   <Mycat学习笔记> 第一篇. MySql 读写分离与日志分析——主从单结点 http://www.cnblogs.com/kaye0110/p/5134588.html 增加一套 mysql 实例,端口为3308 ,通过Binlog方式同步主机情况 localhost : 3306 主机,    在mycat 中配置为 writehost 1 localhost : 3307 从机 a ,在mycat 中配置为 readhost localhost :

搭建MySQL代理服务器实现读写分离+主从同步

实验需求: 1.配置2台MySQL服务器(192.168.100.2,192.168.100.3)+1台代理服务器(192.168.100.1),实现MySQL代理的读写分离. 2.用户只需要访问MySQL代理服务器,实际的SQL查询.写入操作交给后台的2台MySQL服务器来完成. 3.2台MySQL服务器实现主从同步,其中Master服务器允许SQL查询.写入,Slave服务器只允许SQL查询. 一 .MASTER数据库服务器(192.168.100.2)的配置 1.安装软件包(本实验采用My