Предотвращение повторения кода в базе данных мультисхемы

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

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

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

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

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

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

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

Всего 1 ответ


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

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


Есть идеи?

10000