开发者社区> 问答> 正文

spring 声明式事务aop mysql读写库的配置 问题,数据库报错

原来项目用的spring声明式事务处理   现在需要加上mysql的读写库  应用层使用的是aop切换数据库连接 但是读的时候有时候是读库 有时候是写库  不知道是否和声明式事务处理有关  各位大大帮忙看看

applicationContext.xml

<!-- 主库数据源 -->

<bean id="writeDataSource" class="org.apache.commons.dbcp.BasicDataSource"  destroy-method="close">  
<property name="driverClassName" value="${slave.jdbc.driver}" /><.....省略配置>
</bean>  
  
<!-- 从库数据源 -->  
<bean id="readDataSource" class="org.apache.commons.dbcp.BasicDataSource"  destroy-method="close">  
<property name="driverClassName" value="${slave.jdbc.driver}" /><.....省略配置>
</bean>

<bean id="dataSource" class="(这里省略).ChooseDataSource">  
   <property name="targetDataSources">    
         <map key-type="java.lang.String">    
             <!-- write -->  
            <entry key="write" value-ref="writeDataSource"/>    
            <!-- read -->  
            <entry key="read" value-ref="readDataSource"/>    
         </map>    
   </property>    
   <property name="defaultTargetDataSource" ref="writeDataSource"/>  
</bean>

<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">  
    <property name="dataSource" ref="dataSource" />  
</bean>  

<!-- Mybatis's sqlSessionFactory config -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="configLocation" value="classpath:/mapper/Configuration.xml" />
<property name="mapperLocations" value="classpath:/mapper/*Mapper.xml" />
</bean>
<bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">
<constructor-arg name="sqlSessionFactory" ref="sqlSessionFactory" />
</bean>

<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="(这边省略).*.dao.mapper" />
<property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />
</bean>

<!--事务管理器 -->
<bean name="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>

<!-- 配置事务通知 -->
<tx:advice id="txAdvice" transaction-manager="txManager">
<tx:attributes>
<tx:method name="save*" propagation="REQUIRED" isolation="DEFAULT" />
<!-- <tx:method name="set*" propagation="REQUIRED" isolation="DEFAULT" /> -->
<...省略...>
<tx:method name="find*" propagation="REQUIRED" isolation="DEFAULT" read-only="true" />
<tx:method name="select*" propagation="REQUIRED" isolation="DEFAULT" read-only="true" />
<tx:method name="*" read-only="true" />
</tx:attributes>
</tx:advice>

<bean id="dataSourceAspect" class="(这边省略).aspect.DataSourceAspect"></bean>
<!-- aop事务配置 -->
<aop:config>
  <aop:pointcut id="txPointcut" expression="execution(* *..*Service.*(..))" />
<aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut"/>
<aop:aspect id="c" ref="dataSourceAspect">  
       <aop:pointcut id="changeData" expression="execution(* *..*Service.*(..))"/>  
       <aop:before pointcut-ref="changeData" method="before"/>  
   </aop:aspect>
</aop:config>


spring aop 动态选取

@Retention(RetentionPolicy.RUNTIME)  
@Target(ElementType.METHOD)  
public @interface DataSource {  
    String value();  
}  

多数据源

 public class ChooseDataSource extends AbstractRoutingDataSource {  
  
     @Override  
     protected Object determineCurrentLookupKey() {  
         return HandleDataSource.getDataSource();  
     }  
       
 } 


ThreadLocal

public class HandleDataSource {  
    public static final ThreadLocal<String> holder = new ThreadLocal<String>();  
    public static void putDataSource(String datasource) {  
        holder.set(datasource);  
    }  
      
    public static String getDataSource() {  
        return holder.get();  
    }      
}  

切面类

public class DataSourceAspect {     
    public void pointCut(){};    
      
     public void before(JoinPoint point)  
        {  
            Object target = point.getTarget();  
            System.out.println(target.toString());  
            String method = point.getSignature().getName();  
            System.out.println(method);  
            Class<?>[] classz = target.getClass().getInterfaces();  
            Class<?>[] parameterTypes = ((MethodSignature) point.getSignature())  
                    .getMethod().getParameterTypes();  
            try {  
                Method m = classz[0].getMethod(method, parameterTypes);  
                System.out.println(m.getName());  
                if (m != null && m.isAnnotationPresent(DataSource.class)) {  
                    DataSource data = m.getAnnotation(DataSource.class);  
                    HandleDataSource.putDataSource(data.value());  
                }  
                  
            } catch (Exception e) {  
                e.printStackTrace();  
            }  
        }  
}  


接着在service的接口类上


@DataSource("read")
    public List<Page>findForIndex();

结果有时候是用read有时候用write   有没有人给点建议  谢谢了

展开
收起
python小菜菜 2020-06-01 10:17:49 737 0
1 条回答
写回答
取消 提交回答
  • 原来项目用的spring声明式事务处理   现在需要加上mysql的读写库  应用层使用的是aop切换数据库连接 但是读的时候有时候是读库 有时候是写库  不知道是否和声明式事务处理有关  各位大大帮忙看看

    applicationContext.xml

    <!-- 主库数据源 -->

    <bean id="writeDataSource" class="org.apache.commons.dbcp.BasicDataSource"  destroy-method="close">  
    <property name="driverClassName" value="${slave.jdbc.driver}" /><.....省略配置>
    </bean>  
      
    <!-- 从库数据源 -->  
    <bean id="readDataSource" class="org.apache.commons.dbcp.BasicDataSource"  destroy-method="close">  
    <property name="driverClassName" value="${slave.jdbc.driver}" /><.....省略配置>
    </bean>

    <bean id="dataSource" class="(这里省略).ChooseDataSource">  
       <property name="targetDataSources">    
             <map key-type="java.lang.String">    
                 <!-- write -->  
                <entry key="write" value-ref="writeDataSource"/>    
                <!-- read -->  
                <entry key="read" value-ref="readDataSource"/>    
             </map>    
       </property>    
       <property name="defaultTargetDataSource" ref="writeDataSource"/>  
    </bean>

    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">  
        <property name="dataSource" ref="dataSource" />  
    </bean>  

    <!-- Mybatis's sqlSessionFactory config -->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
    <property name="dataSource" ref="dataSource" />
    <property name="configLocation" value="classpath:/mapper/Configuration.xml" />
    <property name="mapperLocations" value="classpath:/mapper/*Mapper.xml" />
    </bean>
    <bean id="sqlSessionTemplate" class="org.mybatis.spring.SqlSessionTemplate">
    <constructor-arg name="sqlSessionFactory" ref="sqlSessionFactory" />
    </bean>

    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
    <property name="basePackage" value="(这边省略).*.dao.mapper" />
    <property name="sqlSessionFactoryBeanName" value="sqlSessionFactory" />
    </bean>

    <!--事务管理器 -->
    <bean name="txManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
    <property name="dataSource" ref="dataSource"></property>
    </bean>

    <!-- 配置事务通知 -->
    <tx:advice id="txAdvice" transaction-manager="txManager">
    <tx:attributes>
    <tx:method name="save*" propagation="REQUIRED" isolation="DEFAULT" />
    <!-- <tx:method name="set*" propagation="REQUIRED" isolation="DEFAULT" /> -->
    <...省略...>
    <tx:method name="find*" propagation="REQUIRED" isolation="DEFAULT" read-only="true" />
    <tx:method name="select*" propagation="REQUIRED" isolation="DEFAULT" read-only="true" />
    <tx:method name="*" read-only="true" />
    </tx:attributes>
    </tx:advice>

    <bean id="dataSourceAspect" class="(这边省略).aspect.DataSourceAspect"></bean>
    <!-- aop事务配置 -->
    <aop:config>
      <aop:pointcut id="txPointcut" expression="execution(* *..*Service.*(..))" />
    <aop:advisor advice-ref="txAdvice" pointcut-ref="txPointcut"/>
    <aop:aspect id="c" ref="dataSourceAspect">  
           <aop:pointcut id="changeData" expression="execution(* *..*Service.*(..))"/>  
           <aop:before pointcut-ref="changeData" method="before"/>  
       </aop:aspect>
    </aop:config>


    spring aop 动态选取

    @Retention(RetentionPolicy.RUNTIME)  
    @Target(ElementType.METHOD)  
    public @interface DataSource {  
        String value();  
    }  

    多数据源

     public class ChooseDataSource extends AbstractRoutingDataSource {  
      
         @Override  
         protected Object determineCurrentLookupKey() {  
             return HandleDataSource.getDataSource();  
         }  
           
     } 


    ThreadLocal

    public class HandleDataSource {  
        public static final ThreadLocal<String> holder = new ThreadLocal<String>();  
        public static void putDataSource(String datasource) {  
            holder.set(datasource);  
        }  
          
        public static String getDataSource() {  
            return holder.get();  
        }      
    }  

    切面类

    public class DataSourceAspect {     
        public void pointCut(){};    
          
         public void before(JoinPoint point)  
            {  
                Object target = point.getTarget();  
                System.out.println(target.toString());  
                String method = point.getSignature().getName();  
                System.out.println(method);  
                Class<?>[] classz = target.getClass().getInterfaces();  
                Class<?>[] parameterTypes = ((MethodSignature) point.getSignature())  
                        .getMethod().getParameterTypes();  
                try {  
                    Method m = classz[0].getMethod(method, parameterTypes);  
                    System.out.println(m.getName());  
                    if (m != null && m.isAnnotationPresent(DataSource.class)) {  
                        DataSource data = m.getAnnotation(DataSource.class);  
                        HandleDataSource.putDataSource(data.value());  
                    }  
                      
                } catch (Exception e) {  
                    e.printStackTrace();  
                }  
            }  
    }  


    接着在service的接口类上


    @DataSource("read")
        public List<Page>findForIndex();

    结果有时候是用read有时候用write   有没有人给点建议  谢谢了

    2020-06-01 10:22:30
    赞同 展开评论 打赏
问答排行榜
最热
最新

相关电子书

更多
云栖社区特邀专家徐雷Java Spring Boot开发实战系列课程(第20讲):经典面试题与阿里等名企内部招聘求职面试技巧 立即下载
微服务架构模式与原理Spring Cloud开发实战 立即下载
阿里特邀专家徐雷Java Spring Boot开发实战系列课程(第18讲):制作Java Docker镜像与推送到DockerHub和阿里云Docker仓库 立即下载

相关镜像