Источник данных Dynami c не сохраняет данные при переключении - PullRequest
0 голосов
/ 04 апреля 2020

У меня есть приложение Spring, я хочу динамически изменять источник данных, расширяя AbstractRoutingDataSource и переопределяя метод determineCurrentLookupKey. Источник данных настраивается ниже:

    @Bean
    @Primary
    public DataSource getMasterDataSource() {
        return DataSourceBuilder.create()
                                .driverClassName("com.mysql.cj.jdbc.Driver")
                                .url("jdbc:mysql://localhost:3306/master")
                                .username("root")
                                .password("r00t")
                                .build();
    }

    @Bean
    public DataSource getSlaveDataSource() {
        return DataSourceBuilder.create()
                                .driverClassName("com.mysql.cj.jdbc.Driver")
                                .url("jdbc:mysql://localhost:3306/slave")
                                .username("root")
                                .password("r00t")
                                .build();
    }


    @Bean(name = "dynamicDataSource")
    public DataSource dynamicDataSource() {
        DynamicDataSource dynamicDataSource = new DynamicDataSource();
        Map<Object, Object> dataSourceMap = new HashMap<>(2);

        dataSourceMap.put(DBType.master.getName(), getMasterDataSource());
        dataSourceMap.put(DBType.slave.getName(), getSlaveDataSource());

        dynamicDataSource.setDefaultTargetDataSource(getMasterDataSource());
        dynamicDataSource.setTargetDataSources(dataSourceMap);

        DataSourceKeyThreadHolder.setDataSourceKey(DBType.master);

        return dynamicDataSource;
    }


    @Bean
    public SqlSessionFactory sqlSessionFactory(@Qualifier("dynamicDataSource") DataSource dataSource)
            throws Exception {
        SqlSessionFactoryBean sqlSessionFactoryBean = new SqlSessionFactoryBean();
        sqlSessionFactoryBean.setDataSource(dataSource);
        return sqlSessionFactoryBean.getObject();
    }

И я использую AOP для переключения источника данных:

    @Pointcut("@annotation(com.gitlab.thamvannguyen.annotation.DataSourceKey)")
    public void dynamicDataSource() {
    }

    @Before("dynamicDataSource()")
    public void doBeforeCreateUser(JoinPoint joinpoint) {
        Method method = ((MethodSignature) joinpoint.getSignature()).getMethod();
        DataSourceKey dataSourceKey = method.getAnnotation(DataSourceKey.class);

        if (dataSourceKey == null) {
            dataSourceKey = joinpoint.getTarget().getClass().getAnnotation(DataSourceKey.class);
            if (dataSourceKey == null) {
                return;
            }
        }

        DBType dbType = dataSourceKey.value();
        DataSourceKeyThreadHolder.setDataSourceKey(dbType);
        LOG.info("Dynamically switch data source, className " + joinpoint.getTarget().getClass()
                         + ", methodName " + method.getName() + ", dataSourceKey " + dbType);
    }

    @After("dynamicDataSource()")
    public void doAfterCreateUser(JoinPoint point) {
        DataSourceKeyThreadHolder.clearDataSourceKey();
    }

Тип БД:

public enum DBType {
    master("master"), slave("slave");

    private String name;

    DBType(final String name) {
        this.name = name;
    }

    public String getName() {
        return name;
    }
}
public class DynamicDataSource
        extends AbstractRoutingDataSource {
    @Override
    protected Object determineCurrentLookupKey() {
        return DataSourceKeyThreadHolder.getDataSourceKey();
    }
}
public class DataSourceKeyThreadHolder {
    private static final Logger LOG = LoggerFactory.getLogger(DataSourceKeyThreadHolder.class);

    private static final ThreadLocal<DBType> dataSourcesKeyHolder = new ThreadLocal<>();

    public static String getDataSourceKey() {
        LOG.info("Get data source key");
        DBType type = dataSourcesKeyHolder.get();
        if (type == null) {
            type = DBType.master;
            dataSourcesKeyHolder.set(type);
        }

        return type.getName();
    }

    public static void setDataSourceKey(DBType databaseType) {
        Assert.notNull(databaseType, "DBType can not be null");
        LOG.info("Set data source key");
        dataSourcesKeyHolder.set(databaseType);
    }

    public static void clearDataSourceKey() {
        LOG.info("Clear data source key");
    }
}

My Service:

    @DataSourceKey(value = DBType.master)
    public User saveUser() {
        User user = new User();
        user.setName("Username");
        return userRepository.save(user);
    }

При сохранении данных в БД master , это успешно, но я пытаюсь переключиться на DB slave с аннотацией @DataSourceKey(value = DBType.slave) в saveUser метод. Он все еще сохраняет данные в db master . Любой может помочь!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...