黑马程序员技术交流社区

标题: 【上海校区】spring和mybatis分库查询 [打印本页]

作者: yuchengmin    时间: 2018-9-27 18:04
标题: 【上海校区】spring和mybatis分库查询
spring和mybatis分库查询


    对于mysql,可以使用一主多从模式,主从之间实现同步,如果mybatis sql是select,自动选择从库查询,如果是insert, update, delete,自动选择主库操作。首先在spring定义数据源,主库数据源:

[Java] 纯文本查看 复制代码
<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>

主库增加事物:

[Java] 纯文本查看 复制代码
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">                     <property name="dataSource" ref="MasterDataSource"/>         </bean>

从库数据源如下,只定义了一个:

[Java] 纯文本查看 复制代码
<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做动态数据源:

[Java] 纯文本查看 复制代码
        <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的拦截

[Java] 纯文本查看 复制代码
        <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定义为:

[Java] 纯文本查看 复制代码
        <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:

[Java] 纯文本查看 复制代码
        @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方法,拦截方法如下:

[Java] 纯文本查看 复制代码
        @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方法利用注释指定数据源:

[Java] 纯文本查看 复制代码
@Retention(RetentionPolicy.RUNTIME)
@Target( ElementType.METHOD)
public @interface DataSourceTarget {

        String id() default "";
       
        String type() default "";
}

DAOMethodType定义如下:

[Java] 纯文本查看 复制代码
public class DAOMethodType {
       

        private final String id;
        private final String type;
        private final SqlCommandType method;
get................... set ...........}





作者: 不二晨    时间: 2018-10-10 11:28
奈斯




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2