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

2019-11-28  本文已影响0人  Memory_2e2e

参考了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);
    }
}
上一篇 下一篇

猜你喜欢

热点阅读