我一直在尝试解决在Spring中使用具有相同架构的2个DB的问题,但未成功。我要解决的问题是为位于两个不同城市的餐厅创建网页,因此我认为为每个城市使用单独的数据库将是最佳解决方案。
我仅从一个数据库获取结果,而另一个由于某种原因未使用。这些数据库分别称为城市的BA和KE,而我使用的是具有相同值的City枚举。
BAConfig.java
@Configuration
@PropertySources(
{@PropertySource("classpath:jpa.properties"),
@PropertySource("classpath:jdbc.properties")})
@EnableTransactionManagement // Enable use of the @Transactional annotation
@ComponentScan(basePackages = "dao")
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class BAConfig {
@Autowired
private Environment environment;
@Bean(name="dataSourceBA")
public DataSource buildDataSource()
{
HikariConfig hkcfg = new HikariConfig();
hkcfg.setJdbcUrl(environment.getRequiredProperty("jdbc.urlBA"));
hkcfg.setDriverClassName(environment.getRequiredProperty("jdbc.driverClassName"));
hkcfg.setUsername(environment.getRequiredProperty("jdbc.username"));
hkcfg.setPassword(environment.getRequiredProperty("jdbc.password"));
HikariDataSource ds = new HikariDataSource(hkcfg);
return ds;
}
public static LocalContainerEntityManagerFactoryBean entityManagerFactoryBuilder(DataSource ds)
{
LocalContainerEntityManagerFactoryBean emf = new LocalContainerEntityManagerFactoryBean();
emf.setDataSource(ds);
emf.setJpaVendorAdapter(new EclipseLinkJpaVendorAdapter());
emf.setPackagesToScan("model"); // Look for entities in this package
Properties props = new Properties();
props.setProperty("databasePlatform", "org.eclipse.persistence.platform.database.PostgreSQLPlatform");
props.setProperty("generateDdl", "true");
props.setProperty("showSql", "true");
props.setProperty("eclipselink.weaving", "false");
props.setProperty("eclipselink.ddl-generation", "create-tables");
emf.setJpaProperties(props);
return emf;
}
@Bean(name="BAEM")
public LocalContainerEntityManagerFactoryBean entityManagerFactory(@Qualifier("dataSourceBA") DataSource ds) {
return entityManagerFactoryBuilder(ds);
}
@Bean(name = "txManagerBA")
JpaTransactionManager transactionManager(@Qualifier("BAEM") EntityManagerFactory em) {
JpaTransactionManager transactionManager = new JpaTransactionManager(em);
return transactionManager;
}
}
KEConfig.java
@Configuration
@PropertySources(
{@PropertySource("classpath:jpa.properties"),
@PropertySource("classpath:jdbc.properties")})
@EnableTransactionManagement // Enable use of the @Transactional annotation
@ComponentScan(basePackages = "dao")
@EnableAspectJAutoProxy(proxyTargetClass = true)
public class KEConfig {
@Autowired
private Environment environment;
@Bean("dataSourceKE")
public DataSource buildDataSource()
{
HikariConfig hkcfg = new HikariConfig();
hkcfg.setJdbcUrl(environment.getRequiredProperty("jdbc.urlKE"));
hkcfg.setDriverClassName(environment.getRequiredProperty("jdbc.driverClassName"));
hkcfg.setUsername(environment.getRequiredProperty("jdbc.username"));
hkcfg.setPassword(environment.getRequiredProperty("jdbc.password"));
HikariDataSource ds = new HikariDataSource(hkcfg);
return ds;
}
@Bean(name="KEEM")
public LocalContainerEntityManagerFactoryBean entityManagerFactory(@Qualifier("dataSourceKE")DataSource ds) {
return BAConfig.entityManagerFactoryBuilder(ds);
}
@Bean(name = "txManagerKE")
JpaTransactionManager transactionManager(@Qualifier("KEEM") EntityManagerFactory em) {
JpaTransactionManager transactionManager = new JpaTransactionManager(em);
return transactionManager;
}
}
这些都导入MainConfig.java类中,并使用以下属性文件。
jdbc.properties
jdbc.driverClassName=org.postgresql.Driver
jdbc.urlBA=jdbc:postgresql://localhost:5432/BambooBA
jdbc.urlKE=jdbc:postgresql://localhost:5432/BambooKE
这是给定实体的其余控制器。
ReservationsController.java
@RestController
@RequestMapping("/reservations")
public class ReservationsController {
@Autowired
private ReservationsService reservationsService;
@RequestMapping(value = "/getAll/{c}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<List<Reservations>> getAll(@PathVariable City c) {
try {
List<Reservations> reservations = new ArrayList<Reservations>();
switch(c)
{
case BA: reservations = reservationsService.findAllBA(); break;
case KE: reservations = reservationsService.findAllKE(); break;
}
return new ResponseEntity<List<Reservations>>(reservations, HttpStatus.OK);
} catch (NoSuchElementException e)
{
return new ResponseEntity<List<Reservations>>(HttpStatus.NOT_FOUND);
}
}
}
这是预订服务,我一直在尝试提取虚拟数据(在两个数据库中,id为1)。
ReservationsService.java
@Service
public class ReservationsService {
@Autowired
private ReservationsDao reservationsDao;
@Transactional("txManagerBA")
public List<Reservations> findAllBA() throws NoSuchElementException {
reservationsDao.setEM(City.BA);
List<Reservations> reservations = new ArrayList<Reservations>();
reservations.add(reservationsDao.find(1));
if(reservations.size() == 0)
{
throw new NoSuchElementException();
}
return reservations;
}
@Transactional("txManagerKE")
public List<Reservations> findAllKE() throws NoSuchElementException {
reservationsDao.setEM(City.KE);
List<Reservations> reservations = new ArrayList<Reservations>();
reservations.add(reservationsDao.find(1));
if(reservations.size() == 0)
{
throw new NoSuchElementException();
}
return reservations;
}
}
这是DAO的超类(特定的DAO继承自此类,并且其中只有一个超级构造函数)。
BaseDao.java
public abstract class BaseDao<T>{
@PersistenceContext(unitName = "BAEM")
EntityManager emBA;
@PersistenceContext(unitName = "KEEM")
EntityManager emKE;
EntityManager em;
protected final Class<T> type;
protected BaseDao(Class<T> type) {
this.type = type;
}
public void setEM(City c)
{
switch(c) {
case BA: em = emBA; break;
case KE: em = emKE; break;
}
}
public T find(Integer id) {
return em.find(type, id);
}
public List<T> findAll() {
return em.createQuery("SELECT e FROM " + type.getSimpleName() + " e", type).getResultList();
}
}
调试(在find()函数的BaseDAO中设置的断点)表明使用了正确的持久性单元来检索数据(当我一直向下移到persistenceUnitInfo.nonJtaDataSource.jdbcUrl时,URL是正确的)。 / p>
但无论请求如何,都仅使用一个数据库。我还尝试过使用AbstractRoutingDataSource,但存在相同的问题-数据库将在第一个请求上设置,然后从那以后将只使用该数据库,而与请求无关。
答案 0 :(得分:0)
这是我们在Hikaripool的spring4应用程序中使用的配置 当您有多个数据库数据源时,@Qualifier注释将很有用;当与@AutoWired一起使用时,@Qualmary可以作为默认数据源;当与其他数据源一起使用时,可以将@Qualifier注释与@AutoWired一起使用
@Bean(destroyMethod = "close")
@Primary
@Qualifier("tspDataSource")
public DataSource dataSource() {
HikariConfig config = new HikariConfig("/hikari-tsp.properties");
config.addDataSourceProperty("cachePrepStmts", "true");
config.addDataSourceProperty("prepStmtCacheSize", "250");
config.addDataSourceProperty("prepStmtCacheSqlLimit", "2048");
final HikariDataSource ds = new HikariDataSource(config);
return ds;
}
第二个
@Bean(destroyMethod = "close")
@Qualifier("fdxDataSource")
public DataSource fdxDataSource() {
HikariConfig config = new HikariConfig("/hikari-fdx.properties");
config.addDataSourceProperty("cachePrepStmts", "true");
config.addDataSourceProperty("prepStmtCacheSize", "250");
config.addDataSourceProperty("prepStmtCacheSqlLimit", "2048");
final HikariDataSource ds = new HikariDataSource(config);
return ds;
}