繁体   English   中英

Spring数据jpa在两个互斥的数据源上

[英]Spring data jpa on two mutually exclusive datasources

我的应用程序有两个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());
    }

}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM