My application has two MYSQL databases which contains same schema but the data is unique(distributed) in both of them. Like if consider the order number is even it will go to first database else will go to the second.
# 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);
}
}
If the entityManagers have there own jpa repositories it would have worked.But in my case both entityManagers have same jpa repositories. Can someone help me is there any way to achieve this or any alternative ways to support my requirement?
I think you can create a base repository (not annotated with @Repository
) like that:
public interface UserRepository extends JpaRepository<User, Integer> {
}
Then you can two repositories that extends the base repository interface
@Repository
public interface User1Repository extends UserRepository {
}
@Repository
public interface User2Repository extends UserRepository {
}
The base repository will allow you to define all methods in one place. And in service, you have to combine both repositories like that:
@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());
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.