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