0

У меня есть приложение springboot со своим собственным источником данных (давайте называть DB1), установленным на свойствах, работающих нормально.Как создать динамический источник данных с помощью SpringBoot

Но это приложение необходимо настроить новый источник данных (DB2), используя некоторые параметры, которые пользователь сообщил ранее и сохранил в DB1.

Моя идея - создать именованный компонент, поэтому конкретная часть моего приложения может использовать для доступа к таблицам DB2. Я думаю, что это можно сделать, перезапустив приложение, но я бы хотел его избежать.

Кроме того, мне нужно, чтобы часть моего кода использовала новый источник данных (данные весны jpa, сопоставления и т. Д.). Я не знаю, имеет ли это значение, но это веб-приложение, поэтому я не могу создать источник данных только для потока запросов.

Вы можете мне помочь?

Заранее спасибо.

+0

Я нашел решение, впрыскивающее первый 'EntityManager', чтобы получить параметры соединения и используя аннотацию' @ PostConstruct' для создания второго источника данных. Единственная проблема с этим подходом заключается в том, что мне нужно перезапустить приложение, если параметры неверны. –

ответ

1

Весна имеет динамическую маршрутизацию данных, если это то, куда вы направляетесь. В моем случае это та же схема (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.

Я использовал это как основу для своей работы, хотя она все еще выполняется, потому что мне все еще нужно разрешать зависимости во время выполнения (т. Е. Спящий режим).

+0

Пожалуйста, не предоставляйте ссылки только на ответы, ссылки могут быть сломаны, и ответ становится неактуальным. Поместите наиболее важные бит в свой пост напрямую. – YakovL

+0

Согласовано. Добавлено поведение примера с полным исходным кодом – Oberst