1. 需求
要实现一个MES系统的web-API接口,MES系统是购买的商业软件,厂商的接口报价过高,因此由内部IT团队开发实现这个接口。考虑到系统的追溯性,因此设计一个中间库,第三方报工系统传过来的数据同时存放在中间库和MES系统里。
2. 设计实现
搜索查阅了很多博文及实验后,终于实现了多数据库的访问,调试时遇到了几个问题,在搜索后也找到了解决方案并修正。
实现思路是采用JavaConfig配合项目目录的方式,通过@EnableJpaRepositories注解的basePackages来指定对应的数据源
2 1. 项目目录结构如下
--src\项目基础目录
----JPA (对应数据库的Entities与Repositories)
------config
------DB1 (数据源1)
--------config
--------entities
--------repositories
------DB2 (数据源2)
--------config
--------entities
--------repositories
2.2. application.yml 或 application.properties
Spring:
datasource:
db1:
jdbc-url: <数据源url>
user: <数据库用户>
password: <数据库密码>
driver-class-name: <数据库驱动类名>
db2:
jdbc-url: <数据源url>
user: <数据库用户>
password: <数据库密码>
driver-class-name: <数据库驱动类名>
2.3. 在jpa\config目录下新建一个配置类,用于配置多数据源映射,用@Configuration声明
@Configuration
public class DataSourceConfig {
@Bean(name = "DataSource1")
@Qualifier("DataSource1")
@ConfigurationProperties(prefix = "spring.datasource.db1")
@Primary
public DataSource DataSource1() {
return DataSourceBuilder.create().build();
}
@Bean(name = "DataSource2")
@Qualifier("DataSource2")
@ConfigurationProperties(prefix = "spring.datasource.db2")
public DataSource DataSource2() {
return DataSourceBuilder.create().build();
}
}
2.4. 在jpa\db1\config目录创建一个JavaConfig类,用于配置db1
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(entityManagerFactoryRef = "entityManagerFactoryDb1",
transactionManagerRef = "transactionManagerDb1",
basePackages = {"<basePackageUrl>.jpa.db1"})
public class Db1DBConfig {
@Autowired
@Qualifier("db1DataSource")
private DataSource db1DataSource;
@Autowired
private HibernateProperties hibernateProperties;
@Autowired
private JpaProperties jpaProperties;
@Primary
@Bean(name = "entityManagerDb1")
public EntityManager entityManager(EntityManagerFactoryBuilder builder) {
return entityManagerFactoryDb1(builder).getObject().createEntityManager();
}
@Primary
@Bean(name = "entityManagerFactoryDb1")
public LocalContainerEntityManagerFactoryBean entityManagerFactoryNM (EntityManagerFactoryBuilder builder) {
return builder.dataSource(db1DataSource)
.properties(getHibernateProperties())
.packages("<basePackageUrl>.jpa.db1.repositories") //换成你自己的实体类所在位置
.persistenceUnit("db1PersistenceUnit")
.build();
}
@Primary
@Bean(name = "transactionManagerDb1")
public PlatformTransactionManager transactionManager(EntityManagerFactoryBuilder builder) {
return new JpaTransactionManager(entityManagerFactoryDb1(builder).getObject());
}
private Map<String, Object> getHibernateProperties() {
return hibernateProperties.determineHibernateProperties(jpaProperties.getProperties(), new HibernateSettings());
}
}
2.5. 在jpa\db2\config目录创建一个JavaConfig类,用于配置db2
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(entityManagerFactoryRef = "entityManagerFactoryDb2",
transactionManagerRef = "transactionManagerDb2",
basePackages = {"<basePackageUrl>.jpa.db2"})
public class Db2DBConfig {
@Autowired
@Qualifier("db2DataSource")
private DataSource db2DataSource;
@Autowired
private HibernateProperties hibernateProperties;
@Autowired
private JpaProperties jpaProperties;
@Bean(name = "entityManagerDb2")
public EntityManager entityManager(EntityManagerFactoryBuilder builder) {
return entityManagerFactoryDb2(builder).getObject().createEntityManager();
}
@Bean(name = "entityManagerFactoryDb2") //primary实体工厂
public LocalContainerEntityManagerFactoryBean entityManagerFactoryMes (EntityManagerFactoryBuilder builder) {
return builder.dataSource(mesDataSource)
.properties(getHibernateProperties())
.packages("<basePackageUrl>.jpa.db2") //换成你自己的实体类所在位置
.persistenceUnit("db2PersistenceUnit")
.build();
}
@Bean(name = "transactionManagerDb2")
public PlatformTransactionManager transactionManager(EntityManagerFactoryBuilder builder) {
return new JpaTransactionManager(entityManagerFactoryDb2(builder).getObject());
}
private Map<String, Object> getHibernateProperties() {
return hibernateProperties.determineHibernateProperties(jpaProperties.getProperties(), new HibernateSettings());
}
}
这样就完成了多数据源的配置,以后在相应的db目录下创建相关的entity和repository。
service与controller就不必放在jpa目录下,service的代码与单数据源的代码一样,就不再赘述。