java - 两个互斥数据源上的 Spring data jpa
问题描述
我的应用程序有两个 MYSQL 数据库,它们包含相同的模式,但数据在它们中都是唯一的(分布式)。就像如果考虑订单号一样,它将进入第一个数据库,否则将进入第二个数据库。
# DataSource1
spring.first.datasource.jdbcUrl=jdbc:mysql://localhost:3306/mysqlone?autoReconnect=true&useSSL=false
spring.first.datasource.username=root
spring.first.datasource.password=password
spring.first.datasource.driver-class-name=com.mysql.jdbc.Driver
# DataSource2
spring.second.datasource.jdbcUrl=jdbc:mysql://localhost:3306/mysqltwo?autoReconnect=true&useSSL=false
spring.second.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.second.datasource.username=root
spring.second.datasource.password=password
# JPA / HIBERNATE
spring.first.jpa.show-sql=true
spring.first.jpa.hibernate.ddl-auto=none
spring.first.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQLDialect
spring.second.jpa.show-sql=true
spring.second.jpa.hibernate.ddl-auto=none
spring.second.jpa.properties.hibernate.dialect=org.hibernate.dialect.MySQLDialect
@Entity
@Table(name="USER_TB")
public class User {
@Id
private int id;
private String name;
}
@Repository
public interface UserRepository extends JpaRepository<User, Integer>{
}
@Configuration
@EnableJpaRepositories(basePackages = {"com.multi.ds.api.repo"},
entityManagerFactoryRef = "ds1EntityManager",
transactionManagerRef = "ds1TransactionManager")
public class DatabaseOne {
@Autowired
private Environment env;
@Bean
public DataSource ds1Datasource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(env.getProperty("spring.first.datasource.driver-class-name"));
dataSource.setUrl(env.getProperty("spring.first.datasource.jdbcUrl"));
dataSource.setUsername(env.getProperty("spring.first.datasource.username"));
dataSource.setPassword(env.getProperty("spring.first.datasource.password"));
return dataSource;
}
@Bean
public LocalContainerEntityManagerFactoryBean ds1EntityManager() {
LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(ds1Datasource());
em.setPackagesToScan(new String[] { "com.multi.ds.api.model" });
em.setPersistenceUnitName("ds1EntityManager");
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
em.setJpaVendorAdapter(vendorAdapter);
HashMap<String, Object> properties = new HashMap<>();
properties.put("hibernate.dialect", env.getProperty("spring.first.jpa.properties.hibernate.dialect"));
properties.put("hibernate.show-sql", env.getProperty("spring.first.jpa.show-sql"));
em.setJpaPropertyMap(properties);
em.afterPropertiesSet();
return em;
}
@Bean
public PlatformTransactionManager ds1TransactionManager() {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(ds1EntityManager().getObject());
return transactionManager;
}
}
@EnableJpaRepositories(basePackages = {"com.multi.ds.api.repo"},
entityManagerFactoryRef = "ds2EntityManager",
transactionManagerRef = "ds2TransactionManager")
public class DatabaseTwo {
@Autowired
private Environment env;
@Bean
public DataSource ds2Datasource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName(env.getProperty("spring.second.datasource.driver-class-name"));
dataSource.setUrl(env.getProperty("spring.second.datasource.jdbcUrl"));
dataSource.setUsername(env.getProperty("spring.second.datasource.username"));
dataSource.setPassword(env.getProperty("spring.second.datasource.password"));
return dataSource;
}
@Bean
public LocalContainerEntityManagerFactoryBean ds2EntityManager() {
LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
em.setDataSource(ds2Datasource());
em.setPackagesToScan(new String[] { "com.multi.ds.api.model" });
em.setPersistenceUnitName("ds2EntityManager");
HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
em.setJpaVendorAdapter(vendorAdapter);
HashMap<String, Object> properties = new HashMap<>();
properties.put("hibernate.dialect", env.getProperty("spring.second.jpa.properties.hibernate.dialect"));
properties.put("hibernate.show-sql", env.getProperty("spring.second.jpa.show-sql"));
em.setJpaPropertyMap(properties);
em.afterPropertiesSet();
return em;
}
@Bean
public PlatformTransactionManager ds2TransactionManager() {
JpaTransactionManager transactionManager = new JpaTransactionManager();
transactionManager.setEntityManagerFactory(ds2EntityManager().getObject());
return transactionManager;
}
}
@Service
public class UserService {
@Autowired
private UserRepository userRepository;
@Transactional("${txManager}")
public List<User> getAll(){
return userRepository.findAll();
}
}
@SpringBootApplication
@EnableAutoConfiguration(exclude = {
DataSourceAutoConfiguration.class,
DataSourceTransactionManagerAutoConfiguration.class,
HibernateJpaAutoConfiguration.class })
@RestController
public class SpringBootMultiDs1Application {
@Autowired
UserService userService;
@RequestMapping(value = "/all", method = RequestMethod.GET)
public List<User> getAll(Long orderNumber){
//if orderNumber is even I need Users from Datasource1 else from Datasource2 USER_TB table
return userService.getAll();
}
public static void main(String[] args) {
SpringApplication.run(SpringBootMultiDs1Application.class, args);
}
}
如果 entityManagers 有自己的 jpa 存储库,它会起作用。但在我的情况下,两个 entityManagers 都具有相同的 jpa 存储库。有人可以帮助我有什么方法可以实现这一目标或任何替代方法来支持我的要求吗?
解决方案
我认为您可以像这样创建一个基本存储库(未使用 注释@Repository
):
public interface UserRepository extends JpaRepository<User, Integer> {
}
然后你可以扩展基本存储库接口的两个存储库
@Repository
public interface User1Repository extends UserRepository {
}
@Repository
public interface User2Repository extends UserRepository {
}
基本存储库将允许您在一处定义所有方法。在服务中,您必须像这样组合两个存储库:
@Service
public class UserService {
private final User1Repository user1Repository;
private final User2Repository user2Repository;
@Autowired
public UserService(User1Repository user1Repository, User2Repository user2Repository) {
this.user1Repository = user1Repository;
this.user2Repository = user2Repository;
}
@Transactional(readOnly = true)
public List<User> getAll(){
return Stream.concat(user1Repository.findAll().stream(), user2Repository.findAll().stream()).collect(Collectors.toList());
}
}
推荐阅读
- dspace - 注册新用户的问题,dspace
- ios - 我们可以通过快速编程来禁用应用程序级别的权限吗?
- postgresql - 使用递归 cte 时 Postgres '输入结束时的语法错误'
- mysql - RAILS - 连接三个表以根据计数获取关联记录
- python - 难以在不同列中的 csv 文件中写入数据
- java - 我应该如何保存和加载具有所有属性的 JTable?
- azure-active-directory - 在 AzureAD SCIM 中强制发送删除请求
- reactjs - 如何正确编写 Redux ReactJS 模态组件?
- auth0 - 将 auth0 与 react-native 集成
- android-studio - Android Studio Designer Preview 在实现 Material Components 库后变黑了