美文网首页
SpringBoot整合Mybatis多数据源 (AOP+注解)

SpringBoot整合Mybatis多数据源 (AOP+注解)

作者: Memory_2e2e | 来源:发表于2019-11-28 11:35 被阅读0次

    参考了https://www.cnblogs.com/yi1036943655/p/9251425.html

    1.pom.xml

            <dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter</artifactId>
                <version>1.3.0</version>
            </dependency>
            <!-- oracle驱动 -->
            <dependency>
                <groupId>com.oracle</groupId>
                <artifactId>ojdbc6</artifactId>
                <version>11.2.0.3</version>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
                <exclusions>
                    <exclusion>
                        <groupId>org.junit.vintage</groupId>
                        <artifactId>junit-vintage-engine</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-aop</artifactId>
            </dependency>
            <dependency>
                <groupId>org.aspectj</groupId>
                <artifactId>aspectjweaver</artifactId>
            </dependency>
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>druid</artifactId>
                <version>1.1.10</version>
            </dependency>
            <!--AbstractRoutingDataSource-->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-jdbc</artifactId>
            </dependency>
    

    2.application.properties

    server.port=8181
    spring.datasource.read-db.jdbc-url=jdbc:oracle:thin:@127.0.0.1:1521:orcl
    spring.datasource.read-db.username=orcl1
    spring.datasource.read-db.password=1
    spring.datasource.read-db.type=com.alibaba.druid.pool.DruidDataSource
    spring.datasource.read-db.driver-class-name=oracle.jdbc.driver.OracleDriver
    spring.datasource.write-db.jdbc-url=jdbc:oracle:thin:@127.0.0.1:1521:orcl
    spring.datasource.write-db.username=orcl2
    spring.datasource.write-db.password=1
    spring.datasource.write-db.type=com.alibaba.druid.pool.DruidDataSource
    spring.datasource.write-db.driver-class-name=oracle.jdbc.driver.OracleDriver
    mybatis.type-aliases-package=com.yudu.db.pojo
    

    3.多数据源配置类

    package com.yudu.db.config;
    
    import org.springframework.boot.context.properties.ConfigurationProperties;
    import org.springframework.boot.jdbc.DataSourceBuilder;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.Primary;
    import org.springframework.jdbc.datasource.DataSourceTransactionManager;
    import org.springframework.transaction.PlatformTransactionManager;
    
    import javax.sql.DataSource;
    import java.util.HashMap;
    import java.util.Map;
    
    @Configuration
    public class DataSourceConfig {
        @ConfigurationProperties(prefix = "spring.datasource.read-db")
        @Bean(name="readDb")
        public DataSource readDb(){
            return DataSourceBuilder.create().build();
        }
        @ConfigurationProperties(prefix = "spring.datasource.write-db")
        @Bean(name="writeDb")
        public DataSource writeDb(){
            return  DataSourceBuilder.create().build();
        }
        /**
         * 动态数据源: 通过AOP在不同数据源之间动态切换
         * @return
         */
        @Primary
        @Bean(name = "dynamicDataSource")
        public DataSource dynamicDataSource(){
            DynamicDataSource dynamicDataSource = new DynamicDataSource();
            // 默认数据源
            dynamicDataSource.setDefaultTargetDataSource(readDb());
            // 配置多数据源
            Map<Object, Object> dsMap = new HashMap<Object, Object>();
            dsMap.put("readDb", readDb());
            dsMap.put("writeDb", writeDb());
    
            dynamicDataSource.setTargetDataSources(dsMap);
            return dynamicDataSource;
        }
    
        /**
         * 配置@Transactional注解事物
         * @return
         */
        @Bean
        public PlatformTransactionManager transactionManager() {
            return new DataSourceTransactionManager(dynamicDataSource());
        }
    }
    

    4.数据源切换读取类

    package com.yudu.db.config;
    
    public class DataSourceContextHolder {
        /**
         * 默认数据源
         */
        public static final String DEFAULT_DS = "readDb";
    
        private static final ThreadLocal<String> contextHolder = new ThreadLocal<>();
    
        // 设置数据源名
        public static void setDB(String dbType) {
            //System.out.println("切换到{"+dbType+"}数据源");
            contextHolder.set(dbType);
        }
    
        // 获取数据源名
        public static String getDB() {
            return (contextHolder.get());
        }
    
        // 清除数据源名
        public static void clearDB() {
            contextHolder.remove();
        }
    }
    

    5.注解类(注意:要和配置类放在同一个包下,否则会抛出找不到注解异常)

    package com.yudu.db.config;
    
    import java.lang.annotation.*;
    
    @Retention(RetentionPolicy.RUNTIME)
    @Target({ElementType.METHOD})
    @Documented
    public @interface DS {
        String value() default "readDb";
    }
    

    6.动态数据源(设置数据源自动调用该类方法)

    package com.yudu.db.config;
    
    import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
    
    public class DynamicDataSource extends AbstractRoutingDataSource {
        @Override
        protected Object determineCurrentLookupKey() {
            //System.out.println("数据源为"+DataSourceContextHolder.getDB());
            return  DataSourceContextHolder.getDB();
        }
    }
    

    7.AOP

    package com.yudu.db.config;
    
    import org.aspectj.lang.JoinPoint;
    import org.aspectj.lang.annotation.After;
    import org.aspectj.lang.annotation.Aspect;
    import org.aspectj.lang.annotation.Before;
    import org.aspectj.lang.reflect.MethodSignature;
    import org.springframework.stereotype.Component;
    
    import java.lang.reflect.Method;
    
    @Aspect
    @Component
    public class DynamicDataSourceAspect {
        @Before("@annotation(DS)")
        @SuppressWarnings("rawtypes")
        public void beforeSwitchDS(JoinPoint point){
            //获得当前访问的class
            Class<?> className = point.getTarget().getClass();
            //获得访问的方法名
            String methodName = point.getSignature().getName();
            //得到方法的参数的类型
            Class[] argClass = ((MethodSignature)point.getSignature()).getParameterTypes();
            String dataSource = DataSourceContextHolder.DEFAULT_DS;
            try {
                // 得到访问的方法对象
                Method method = className.getMethod(methodName, argClass);
                // 判断是否存在@DS注解
                if (method.isAnnotationPresent(DS.class)) {
                    DS annotation = method.getAnnotation(DS.class);
                    // 取出注解中的数据源名
                    dataSource = annotation.value();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
            // 切换数据源
            DataSourceContextHolder.setDB(dataSource);
        }
    
        @After("@annotation(DS)")
        public void afterSwitchDS(JoinPoint point){
            DataSourceContextHolder.clearDB();
        }
    }
    

    8.repository

    package com.yudu.db.repository;
    
    import com.yudu.db.pojo.XtFile;
    import org.apache.ibatis.annotations.*;
    
    import java.util.List;
    @Mapper
    public interface XtFileRepository {
        @Select("select * from XT_FILE where ID = #{id}")
        @Results({
                @Result(property = "id",  column = "ID"),
                @Result(property = "bid", column = "BID"),
                @Result(property = "name", column = "NAME"),
                @Result(property = "attachId", column = "ATTACHID"),
                @Result(property = "path", column = "PATH"),
                @Result(property = "fileType", column = "FILE_TYPE"),
                @Result(property = "fileSize", column = "FILE_SIZE"),
                @Result(property = "memo", column = "MEMO"),
                @Result(property = "upLoadTime", column = "UPLOAD_TIME"),
                @Result(property = "uploadStepId",  column = "UPLOAD_STEPID"),
                @Result(property = "uploadUserName", column = "UPDATED_USERNAME"),
                @Result(property = "uploadUserId", column = "UPDATED_USERID"),
                @Result(property = "fileSort", column = "FILE_SORT"),
                @Result(property = "state", column = "STATE"),
                @Result(property = "version", column = "VERSION"),
                @Result(property = "data", column = "DATA"),
                @Result(property = "transferId", column = "TRANSFERID"),
                @Result(property = "noticeId", column = "NOTICEID"),
                @Result(property = "draftType", column = "DRAFT_TYPE"),
        })
        XtFile selectById(String id);
    }
    

    9.serviceImpl

    package com.yudu.db.service.impl;
    
    import com.yudu.db.config.DS;
    import com.yudu.db.pojo.XtFile;
    import com.yudu.db.repository.XtFileRepository;
    import com.yudu.db.service.XtFileService;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Service;
    
    import java.util.List;
    @Service
    public class XtFileServiceImpl implements XtFileService {
        @Autowired
        private XtFileRepository xtFileRepository;
        @Override
        @DS("readDb")
        public XtFile selectById(String id) {
            return xtFileRepository.selectById(id);
        }
    
        @Override
        @DS("writeDb")
        public XtFile getById(String id) {
            return xtFileRepository.selectById(id);
        }
    }
    

    10.单元测试

    package com.yudu.db;
    
    import com.yudu.db.config.DS;
    import com.yudu.db.pojo.XtFile;
    import com.yudu.db.repository.XtFileRepository;
    import com.yudu.db.service.XtFileService;
    import org.junit.jupiter.api.Test;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    
    @SpringBootTest
    public class DbTest {
        @Autowired
        private XtFileService xtFileService;
    
        @Test
        public void test(){
            XtFile m_xtFile = xtFileService.selectById("14FA331700F74EB29BA75499FFC41251");
            String m_name = m_xtFile.getName();
            System.out.println(m_name);
            XtFile s_xtFile = xtFileService.getById("14FA331700F74EB29BA75499FFC41251");
            String s_name = s_xtFile.getName();
            System.out.println(s_name);
        }
    }
    

    相关文章

      网友评论

          本文标题:SpringBoot整合Mybatis多数据源 (AOP+注解)

          本文链接:https://www.haomeiwen.com/subject/cenvwctx.html