spring和mybatis自动判断dao操作类型分库查询

版权声明:本文为博主原创文章,未经博主允许不得转载。 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里增加缓存

猜你喜欢

转载自blog.csdn.net/vcshcn/article/details/17678409
今日推荐