spring 声明式事务aop mysql读写库的配置 问题,数据库报错 -问答-阿里云开发者社区-阿里云

开发者社区> 问答> 正文

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

2020-06-01 10:17:49 127 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   有没有人给点建议  谢谢了

取消 提交回答
全部回答(1)
  • python小菜菜
    2020-06-01 10:22:30

    原来项目用的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   有没有人给点建议  谢谢了

    0 0
相关问答

17

回答

【大咖问答】对话PostgreSQL 中国社区发起人之一,阿里云数据库高级专家 德哥

阿里ACE 彭飞 2019-07-10 09:36:10 1037764浏览量 回答数 17

162

回答

惊喜翻倍:免费ECS+免费环境配置~!(ECS免费体验6个月活动3月31日结束)

豆妹 2014-10-29 17:52:21 226125浏览量 回答数 162

145

回答

【新手入门】云服务器linux使用手册

fanyue88888 2012-11-26 17:14:18 157679浏览量 回答数 145

8

回答

OceanBase 使用动画(持续更新)

mq4096 2019-02-20 17:16:36 336992浏览量 回答数 8

110

回答

OSS存储服务-客户端工具

newegg11 2012-05-17 15:37:18 295524浏览量 回答数 110

18

回答

阿里云开放端口权限

xcxx 2016-07-20 15:03:33 646758浏览量 回答数 18

38

回答

安全组详解,新手必看教程

我的中国 2017-11-30 15:23:46 259823浏览量 回答数 38

21

回答

请教一下数据量有100万条左右要什么配置?

易网网络 2013-03-27 15:18:02 192635浏览量 回答数 21

249

回答

阿里云LNAMP(Linux + Nginx + Apache + MySQL + PHP)环境一键安装脚本

云代维 2014-02-14 15:26:06 305619浏览量 回答数 249

2

回答

区域选择帮助

fanyue88888 2012-12-07 15:54:30 204383浏览量 回答数 2
3
文章
302
问答
问答排行榜
最热
最新
相关电子书
更多
《2021云上架构与运维峰会演讲合集》
立即下载
《零基础CSS入门教程》
立即下载
《零基础HTML入门教程》
立即下载