【问题标题】:How to create a dynamic datasource using SpringBoot如何使用 Spring Boot 创建动态数据源
【发布时间】:2017-04-12 13:26:04
【问题描述】:

我有一个 springboot 应用程序,它在属性上设置了自己的数据源(我们称之为 DB1),工作正常。

但是这个应用程序需要配置一个新的数据源(DB2),使用用户之前通知并存储在DB1中的一些参数。

我的想法是创建一个命名 bean,以便我的应用程序的特定部分可以用来访问 DB2 表。我认为可以通过重新启动应用程序来做到这一点,但我想避免它。

此外,我需要我的部分代码使用新的数据源(spring data jpa、mappings 等)。我不知道这是否重要,但它是一个 Web 应用程序,所以我不能只为请求线程创建数据源。

你能帮帮我吗?

提前致谢。

【问题讨论】:

  • 我找到了一个解决方案,注入第一个EntityManager 以获取连接参数,并使用@PostConstruct 注释创建第二个数据源。这种方法唯一的问题是,如果参数不正确,我需要重新启动应用程序。

标签: spring spring-boot spring-data datasource spring-data-jpa


【解决方案1】:

Spring 具有动态数据源路由,如果这是您要去的地方。就我而言,它是相同的架构(WR/RO)

public class RoutingDataSource extends AbstractRoutingDataSource {

  @Autowired
  private DataSourceConfig dataSourceConfig;

  @Override
  protected Object determineCurrentLookupKey() {
    return DbContextHolder.getDbType();
  }

  public enum DbType {
    MASTER, WRITE, READONLY,  
  }

那么你需要一个自定义注解和一个切面

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface ReadOnlyConnection {
}

@Aspect 
@Component
@Order(1)
public class ReadOnlyConnectionInterceptor {

  Pointcut(value = "execution(public * *(..))")
  public void anyPublicMethod() {}

  @Around("@annotation(readOnlyConnection)")
  public Object proceed(ProceedingJoinPoint proceedingJoinPoint, ReadOnlyConnection readOnlyConnection) throws Throwable           {
    Object result = null;
    try {
      DbContextHolder.setDbType(DbType.READONLY);
      result = proceedingJoinPoint.proceed();
      DbContextHolder.clearDbType();
      return result;
    } finally {
      DbContextHolder.clearDbType();
    }
  }
}

然后您可以使用标签@ReadOnlyConnection 对您的数据库进行操作

@Override
@Transactional(readOnly = true)
@ReadOnlyConnection
public UnitDTO getUnitById(Long id) {
  return unitRepository.findOne(id);
}

可以在此处找到示例:https://github.com/afedulov/routing-data-source

我把它作为我工作的基础,尽管它仍在进行中,因为我仍然需要解决运行时依赖关系(即休眠分片)。

【讨论】:

  • 请不要提供仅链接的答案,链接可能会损坏并且答案变得无关紧要。将最重要的部分直接放到您的帖子中。
  • 同意。添加了带有完整源链接的示例行为
最近更新 更多