转自:
Spring+Hibernate框架下MySql读写分离,主从数据库配置
介绍下mysql数据库读写分离在spring,hibernate框架下的配置。
1.mysql连接配置文件jdbc.properties
master.*.*表示主数据库连接参数,负责增,删,改;
slave.*.*表示从数据库连接参数,只负责读取;
jdbc.properties
-
master.jdbc.driverClassName=com.mysql.jdbc.Driver
-
master.jdbc.url=********
-
master.jdbc.username=********
-
master.jdbc.password=********
-
-
slave.jdbc.driverClassName=com.mysql.jdbc.Driver
-
slave.jdbc.url=********
-
slave.jdbc.username=********
-
slave.jdbc.password=********
把**改成你所需的连接参数;
2.配置AOP切面类 DataSourceAdvice.java
-
import
java.lang.reflect.Method;
-
import
org.springframework.aop.AfterReturningAdvice;
-
import
org.springframework.aop.MethodBeforeAdvice;
-
import
org.springframework.aop.ThrowsAdvice;
-
-
import
com.company.datasource.DataSourceSwitcher;
-
-
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”
);
-
}
-
-
}
数据源选择类 DataSourceSwitcher.java
-
package
com.company.datasource;
-
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();
-
}
-
}
DynamicDataSource.java数据源动态切换类
-
package
com.company.datasource;
-
-
import
org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
-
-
public
class
DynamicDataSource
extends
AbstractRoutingDataSource {
-
-
@Override
-
protected
Object determineCurrentLookupKey() {
-
return
DataSourceSwitcher.getDataSource();
-
}
-
-
}
下面配置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: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/tx
-
http://www.springframework.org/schema/tx/spring-tx-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/context
-
http://www.springframework.org/schema/context/spring-context-3.0.xsd”
>
-
-
<
context:annotation-config
/>
-
<!– 自动加载SERVICE DAO ACTION –>
-
<
context:component-scan
base-package
=
“cn.com.company.dao.*”
/>
-
<
context:component-scan
base-package
=
“cn.com.company.service.*”
/>
-
<
context:component-scan
base-package
=
“cn.com.company.action”
/>
-
-
<!– 加载properties配置文件 –>
-
<
bean
id
=
“propertyConfigurer”
-
class
=
“org.springframework.beans.factory.config.PropertyPlaceholderConfigurer”
>
-
<
property
name
=
“locations”
>
-
<
list
>
-
<
value
>
classpath:jdbc.properties
</
value
>
-
</
list
>
-
</
property
>
-
</
bean
>
-
-
<
bean
id
=
“parentDataSource”
class
=
“com.mchange.v2.c3p0.ComboPooledDataSource”
>
-
//***c3p0配置
-
</
bean
>
-
<!– 主数据源–>
-
<
bean
id
=
“masterDataSource”
parent
=
“parentDataSource”
>
-
<
property
name
=
“driverClass”
value
=
“${master.jdbc.driverClassName}”
/>
-
<
property
name
=
“jdbcUrl”
value
=
“${master.jdbc.url}”
/>
-
<
property
name
=
“user”
value
=
“${master.jdbc.username}”
/>
-
<
property
name
=
“password”
value
=
“${master.jdbc.password}”
/>
-
</
bean
>
-
<!– 从数据源–>
-
<
bean
id
=
“slaveDataSource”
parent
=
“parentDataSource”
>
-
<
property
name
=
“driverClass”
value
=
“${slave.jdbc.driverClassName}”
/>
-
<
property
name
=
“jdbcUrl”
value
=
“${slave.jdbc.url}”
/>
-
<
property
name
=
“user”
value
=
“${slave.jdbc.username}”
/>
-
<
property
name
=
“password”
value
=
“${slave.jdbc.password}”
/>
-
</
bean
>
-
-
<
bean
id
=
“dataSource”
class
=
“com.company.datasource.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.annotation.AnnotationSessionFactoryBean”
>
-
<
property
name
=
“dataSource”
ref
=
“dataSource”
>
</
property
>
-
<
property
name
=
“packagesToScan”
value
=
“cn.com.company.entity”
/>
-
<
property
name
=
“hibernateProperties”
>
-
<
props
>
-
-
<
prop
>
//***hibernate一些参数这里不写了
</
prop
>
-
</
props
>
-
</
property
>
-
</
bean
>
-
-
<!– 切换数据源 –>
-
<
bean
id
=
“dataSourceAdvice”
class
=
“com.company.aop.DataSourceAdvice”
/>
-
<
aop:config
>
-
<
aop:advisor
-
pointcut
=
“execution(* cn.com.company.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
=
“loadByUsername*”
propagation
=
“SUPPORTS”
read-only
=
“true”
/>
-
<!– 对其它方法进行只读事务 –>
-
<
tx:method
name
=
“*”
propagation
=
“SUPPORTS”
read-only
=
“true”
/>
-
</
tx:attributes
>
-
</
tx:advice
>
-
<!–那些类的哪些方法参与事务 –>
-
<
aop:config
>
-
<
aop:advisor
-
pointcut
=
“execution(* cn.com.company.service..*Service.*(..))”
-
advice-ref
=
“txAdvice”
/>
-
<
aop:advisor
-
pointcut
=
“execution(* cn.com.company.service..*ServiceImpl.*(..))”
-
advice-ref
=
“txAdvice”
/>
-
</
aop:config
>
-
-
-
</
beans
>
!注 applicationContenxt.xml中
<!– 切换数据源 –>
<bean id=”dataSourceAdvice” class=”com.company.aop.DataSourceAdvice” />
<aop:config>
<aop:advisor
pointcut=”execution(* cn.com.company.service..*Service.*(..))”
advice-ref=”dataSourceAdvice” />
</aop:config>
一定要配置在事务AOP之上