Предотвращение повторения кода в базе данных мультисхемы - PullRequest
2 голосов
/ 17 мая 2019

У меня есть устаревшее приложение с базой данных, которое разделяет данные на несколько схем в одной физической базе данных. Схемы идентичны по структуре.

Я использую микросервис с использованием Spring Boot Data JPA для работы с одной схемой. Затем, чтобы избежать повторения кода, я создал службу маршрутизатора, которая перенаправляет запрос в одну реплику микросервиса схемы, каждая из которых имеет свое подключение к базе данных. Но я обнаружил, что немного излишним (но работает)

Я пытаюсь свести его к одному микросервису. Я пока не добился успеха, но я настроил таблицы со свойством schema.

@Table(
    name = "alerts",
    schema = "ca"
)

Однако, это сбивает с толку, когда я пытаюсь сделать наследование и @MappedSuperclass, чтобы уменьшить дублирование кода.

Кроме того, @OneToMany разрывается из-за ошибок наследования, подобных X references an unknown entity: Y

По сути, есть способ использования наследования в JPA, который использует ту же структуру таблиц, с той разницей, что это просто схема без копирования и вставки слишком большого количества кода. В идеале я хотел бы просто передать параметр "схемы" в DAO, и он каким-то образом сделал это для меня.

1 Ответ

0 голосов
/ 18 мая 2019

В конце концов, нам просто нужен источник данных, который будет маршрутизироваться в соответствии с ситуацией.Для этого используется @Component, который расширяет AbstractRoutingDataSource, и ThreadLocal для хранения контекста запроса.

ThreadLocal будет выглядеть примерно так (примеры используют Lombok)

@AllArgsConstructor
public class UserContext {
    private static final ThreadLocal<UserContext> context =
        new ThreadLocal<>();
    private final String schema;

    public static String getSchema() {
        return context.get().schema;
    }

    public static void setFromXXX(...) {
        context.set(new UserContext(
            ...
        ));
    }
}

Потребуется источник данных:

@Configuration
public class DataSources {

    @Bean
    public DataSource schema1() {
        return build("schema1");
    }

    @Bean
    public DataSource schema2() {
        return build("schema2");
    }

    private DataSource buildDataSource(String schema) {
        ...
        return new DriverManagerDataSource(url, username, password);
    }
}

И, наконец, маршрутизатор, помеченный как источник данных @Primary, чтобы убедиться, что он используется JPA..

@Component
@Primary
public class RoutingDatasource extends AbstractRoutingDataSource {
    @Autowired
    @Qualifier("schema1")
    private DataSource schema1;

    @Autowired
    @Qualifier("schema2")
    private DataSource schema2;

    @Override
    public void afterPropertiesSet() {
        setTargetDataSources(
            Map.of(
                "schema1", schema1,
                "schema2", schema2
            )
        );
        super.afterPropertiesSet();
    }

    @Override
    protected Object determineCurrentLookupKey() {
        return UserContext.getSchema();
    }
}

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

...