2 u010791853 u010791853 于 2017.01.16 11:00 提问

struts2+spring+hibernate 实现读写分离问题

数据库动态切换类:

public class DynamicDataSource extends AbstractRoutingDataSource {
    @Override
    protected Object determineCurrentLookupKey() {
        System.out.println("===================切换数据源:" + DataSourceSwitcher.getDataSource());
        return DataSourceSwitcher.getDataSource();
    }

    @Override
    public Logger getParentLogger() throws SQLFeatureNotSupportedException {
        return null;
    }
}

AOP切面类,设置数据源:

 @Component
@Aspect
@Order(0)
public class DataSourceAdvice {

    private static Logger logger = Logger.getLogger(DataSourceAdvice.class);

    @Before(("@annotation(com.lot.common.dataSource.DynamicDataSourceAnnotation)"))
    public void before(JoinPoint point) {
        try {
            // 获取数据源
            String dataSource = getDataSource(point);

            // 设置数据源
            logger.info("切换数据源到" + dataSource);
            DataSourceSwitcher.setDataSource(dataSource);
        } catch (Exception e) {
            logger.error("切换数据源失败...");
            logger.error(StringHandleUtils.getExceptionInfo(e));
        }
    }

    @After("@annotation(com.lot.common.dataSource.DynamicDataSourceAnnotation)")   //后置通知
    public void testAfter(JoinPoint point){
        try {
            // 获取数据源
            String dataSource = getDataSource(point);

            // 若数据源不是主库,则清空
            if(!DataSourceSwitcher.DATA_SOURCE_MASTER.equals(dataSource)) {
                logger.error("删除数据源" + dataSource + "成功...");
                DataSourceSwitcher.removeDataSource();
            }
        } catch (Exception e) {
            logger.error("删除数据源失败...");
            logger.error(StringHandleUtils.getExceptionInfo(e));
        }
    }

    @SuppressWarnings("rawtypes")
    private String getDataSource(JoinPoint point) {
        String dataSource = DataSourceSwitcher.DATA_SOURCE_MASTER;
        try{
            Class<?> className = point.getTarget().getClass();
            String methodName = point.getSignature().getName();
            Class[] argClass = ((MethodSignature)point.getSignature()).getParameterTypes();
            Method method = className.getMethod(methodName, argClass);
            if (method.isAnnotationPresent(DynamicDataSourceAnnotation.class)) {
                DynamicDataSourceAnnotation annotation = method.getAnnotation(DynamicDataSourceAnnotation.class);
                dataSource = annotation.dataSource();
            }
        }catch(Exception e) {
            logger.error("获取数据源失败...");
            logger.error(StringHandleUtils.getExceptionInfo(e));
        }

        return dataSource;
    }
}

spring配置:

 <!-- master -->
    <bean id="master" class="com.lot.common.dataSource.DataSource" parent="commC3p0">
         <property name="driver" value="${master.datasource.driverClassName}" /> 
         <property name="driverUrl" value="${master.datasource.url}" /> 
         <property name="user" value="${master.datasource.username}"/> 
         <property name="password" value="${master.datasource.password}"/> 
     </bean>

    <!-- slave -->
    <bean id="slave" class="com.lot.common.dataSource.DataSource" parent="commC3p0">
        <property name="driver" value="${slave.datasource.driverClassName}" /> 
        <property name="driverUrl" value="${slave.datasource.url}" /> 
        <property name="user" value="${slave.datasource.username}"/> 
        <property name="password" value="${slave.datasource.password}"/> 
    </bean>

    <!-- 配置动态数据源 -->
    <bean id="dataSource" class="com.lot.common.dataSource.DynamicDataSource">  
        <property name="defaultTargetDataSource" ref="master"></property>
        <property name="targetDataSources">  
            <map key-type="java.lang.Object">  
                <entry value-ref="master" key="master"></entry>  
                <entry value-ref="slave" key="slave"></entry>
            </map>  
        </property>  
    </bean>

        <bean id="sessionFactory"
        class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
        <property name="dataSource">
            <ref bean="dataSource" />
        </property>
        <property name="hibernateProperties">
            <props>
                <prop key="hibernate.dialect">${hibernate.dialect}</prop>  
                <prop key="hibernate.show_sql">${hibernate.show_sql}</prop>  
                <prop key="hibernate.format_sql">${hibernate.format_sql}</prop>  
                <prop key="hibernate.use_sql_comments">${hibernate.use_sql_comments}</prop>  
                <prop key="hibernate.jdbc.batch_size">${hibernate.jdbc.batch_size}</prop>  
                <prop key="hibernate.max_fetch_depth">${hibernate.max_fetch_depth}</prop>  
                <prop key="hibernate.jdbc.fetch_size">${hibernate.jdbc.fetch_size}</prop>  
                <prop key="hibernate.cache.use_second_level_cache">${hibernate.cache.use_second_level_cache}</prop>  
                <prop key="hibernate.cache.use_query_cache">${hibernate.cache.use_query_cache}</prop>  
                <prop key="hibernate.cache.provider_class">${hibernate.cache.provider_class}</prop>  
                <prop key="hibernate.order_updates">${hibernate.order_updates}</prop>  
                <prop key="hibernate.query.factory_class">${hibernate.query.factory_class}</prop>  
                <prop key="hibernate.connection.isolation">${hibernate.connection.isolation}</prop> 

                <!-- 解决与weblogic的冲突 -->
                <prop key="hibernate.query.factory_class">${hibernate.query.factory_class}</prop>

                <prop key="hibernate.jdbc.batch_size">0</prop>   
            </props>
        </property>
        <property name="packagesToScan" value="com.entity"/>
    </bean>

    <!-- 定义事务管理器(声明式的事务)   -->
    <bean id="transactionManager"
        class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory" />
    </bean>

    <!-- 注解方式配置事务 -->
    <aop:aspectj-autoproxy proxy-target-class="true" />
    <tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="false" />

数据源切换时在AOP之前执行了,导致数据源未切换。
图片说明

1个回答

JE_GE
JE_GE   2017.01.16 11:04

现在一般使用中间件mycat了吧

u010791853
u010791853 项目现在不需要用中间件,简单的实现就行了。
11 个月之前 回复
Csdn user default icon
上传中...
上传图片
插入图片
准确详细的回答,更有利于被提问者采纳,从而获得C币。复制、灌水、广告等回答会被删除,是时候展现真正的技术了!