版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/vcshcn/article/details/17678409
对于mysql,可以使用一主多从模式,主从之间实现同步
如果mybatis sql是select,自动选择从库查询,如果是insert, update, delete,自动选择主库操作。
首先在spring定义数据源,主库数据源:
<bean id="MasterDataSource" ........>
<property name="driverClassName" value="${master.jdbc.driverClassName}"/>
<property name="url" value="${master.jdbc.url}"/>
<property name="username" value="${master.jdbc.username}"/>
<property name="password" value="${master.jdbc.password}"/>
</bean>
主库增加事物:
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="MasterDataSource"/>
</bean>
从库数据源如下,只定义了一个:
<bean id="Slave1DataSource" ......>
<property name="driverClassName" value="${slave1.jdbc.driverClassName}"/>
<property name="url" value="${slave1.jdbc.url}"/>
<property name="username" value="${slave1.jdbc.username}"/>
<property name="password" value="${slave1.jdbc.password}"/>
</bean>
其中type包含两种:一个是master,另一个slave定义好数据源好,利用spring做动态数据源:
<bean id="dataSource" class="net.xway.base.database.source.impl.DynamicDataSource" >
<property name="dataSources">
<list>
<ref bean="MasterDataSource"/>
<ref bean="Slave1DataSource"/>
</list>
</property>
<property name="defaultTargetDataSource" ref="MasterDataSource" />
</bean>
并增加对dao的拦截
<bean id="DAOMethodAdvice" class="net.xway.base.database.source.DAOMethodAdvice">
<property name="dataSource" ref="dataSource" />
<property name="factory" ref="SqlSessionFactory" />
</bean>
<bean class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
<property name="beanNames">
<list>
<value>*DAO</value>
</list>
</property>
<property name="interceptorNames">
<list>
<value>DAOMethodAdvice</value>
</list>
</property>
</bean>
其中DAOMethodAdvice中的factory定义为:
<bean id="SqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="configLocation" value="classpath:sqlMapConfig.xml" />
<property name="mapperLocations" value="classpath:/net/xway/**/mysql-*.xml" />
<property name="dataSource" ref="dataSource" />
<property name="plugins">
<list>
<ref bean="PagingInterceptor"/>
</list>
</property>
</bean>
net.xway.base.database.source.impl.DynamicDataSource类中主要方法为determineCurrentLookupKey:
@Override
protected Object determineCurrentLookupKey() {
DAOMethodType type = local.get();
if (type == null) {
return null;
}
String key = null;
if (type.getId() != null && type.getId().length() > 0) {
key = type.getId();
}
else if (type.getType() != null && type.getType().length()>0) {
key = master.equals(type.getType()) ? master : randomSlaveKey();
}
else if (type.getMethod() != null) {
key = SqlCommandType.SELECT.equals(type.getMethod() ) ? randomSlaveKey() : master;
}
removeDAOMethodType();
return key;
}
private String randomSlaveKey() {
switch (slaves.size()) {
case 0:
return master;
case 1:
return slaves.get(0);
default:
int c = r.nextInt(slaves.size());
return slaves.get(c);
}
}
net.xway.base.database.source.DAOMethodAdvice用于拦截dao方法,拦截方法如下
@Override
public void before(Method method, Object[] params, Object object) throws Throwable {
String type = null;
String id = null;
Annotation[] as = method.getAnnotations();
for (Annotation a : as) {
if (a instanceof DataSourceTarget) {
type = ((DataSourceTarget) a).type();
id = ((DataSourceTarget) a).id();
break ;
}
}
DAOMethodType dsType = null;
if (type != null || id != null) {
dsType = new DAOMethodType(id, type, null);
}
else {
MappedStatement statement = factory.getConfiguration().getMappedStatement(method.getName());
dsType = new DAOMethodType(null, null, statement.getSqlCommandType());
}
if (dsType != null) {
dataSource.setDAOMethodType(dsType);
}
}
至此完成了拦截操作,并可为dao方法利用注释指定数据源:
@Retention(RetentionPolicy.RUNTIME)
@Target( ElementType.METHOD)
public @interface DataSourceTarget {
String id() default "";
String type() default "";
}
DAOMethodType定义如下:
public class DAOMethodType {
private final String id;
private final String type;
private final SqlCommandType method;
get................... set ...........}
下一步可根据需要在advice里增加缓存