Spring Boot - 不同数据库的相同存储库和相同实体

Posted

技术标签:

【中文标题】Spring Boot - 不同数据库的相同存储库和相同实体【英文标题】:Spring Boot - Same repository and same entity for different databases 【发布时间】:2018-03-30 05:28:01 【问题描述】:

我有一个 Spring Boot 项目,其中包含一个实体和一个与该实体关联的存储库。在存储库中,有一种带有自定义查询的方法,在项目控制器中,该存储库用于从不同的 postgresql 数据库返回数据。这些数据库具有相同的表和相同的列(因此引用的实体是相同的),这些数据库之间的唯一区别是年份(...,DB2015,DB2016,DB2017)。 我的问题是:如何在项目控制器中返回属于“不同”数据库的数据?是否可以使用相同的查询首先从第一个数据库中选择数据,然后从第二个数据库中选择数据,依此类推? 在我读过的其他问题中,我需要不同的数据源,这是正确的吗?

这是实体:

@Entity(name = "REQUEST")
public class Request implements Serializable 

/**
 * 
 */
private static final long serialVersionUID = 1L;

@Id
@Column(name="IDREQUEST", nullable=false)
private BigDecimal idrequest;


@Column(name="PAYLOAD")
private String payload;

@Column(name="MITTENTE")
private String mittente;

@Column(name="SERVIZIO")
private String servizio;

@Column(name="DATARICEZIONE")
private BigDecimal dataricezione;

public BigDecimal getIdrequest() 
    return idrequest;


public void setIdrequest(BigDecimal idrequest) 
    this.idrequest = idrequest;


public String getPayload() 
    return payload;


public void setPayload(String payload) 
    this.payload = payload;


public String getMittente() 
    return mittente;


public void setMittente(String mittente) 
    this.mittente = mittente;


public String getServizio() 
    return servizio;


public void setServizio(String servizio) 
    this.servizio = servizio;


public BigDecimal getDataricezione() 
    return dataricezione;


public void setDataricezione(BigDecimal dataricezione) 
    this.dataricezione = dataricezione;



这是存储库:

@Repository
public interface RequestRepository extends PagingAndSortingRepository<Request, BigDecimal> 

    @Query(nativeQuery=true, value="SELECT * FROM \"REQUEST\" WHERE strpos(\"PAYLOAD\",\'?1\') > 0")
    List<Request> findByCodiceFiscale(String codiceFiscale);


这是控制器

@RequestMapping(value="/ricercaadesioni/codicefiscale", method=RequestMethod.GET)
public ResponseEntity<List<Request>> ricercaAdesioniByCodiceFIscale(@PathVariable("codicefiscale") String codicefiscale) 

    List<Request> listAdesioni = requestRepo.findByCodiceFiscale(codicefiscale);

    return new ResponseEntity<List<Request>>(listAdesioni, HttpStatus.OK);

这是 application.properties(在这种情况下,数据源仅引用一个 db):

spring.datasource.url=jdbc:postgresql://localhost:5432/DB2017_test
spring.datasource.username=xxx
spring.datasource.password=xxx

希望一切都清楚

【问题讨论】:

您可以定义多个LocalContainerEntityManagerFactoryBeanbeans,每个@beans 都有与所需数据库关联的数据源。 【参考方案1】:

使用不同的数据源创建 2 个配置文件,这 2 个配置文件对于 2 个不同的 jpa 存储库类具有不同的规范。但可以具有相同的域类。

步骤 1> 在您的属性文件中有 2 个数据源详细信息。

spring.datasource.url=jdbc:postgresql://localhost:5432/DB2017_test
spring.datasource.username=xxx
spring.datasource.password=xxx


# DB2018 DB - ""
spring.datasource2.url=jdbc:postgresql://localhost:5432/DB2018_test
spring.datasource2.username=xxx
spring.datasource2.password=xxx

step2>然后为第一个数据源创建配置文件

package com.package1;

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
  entityManagerFactoryRef = "entityManagerFactory",
  basePackages =  "com.package1.repo"  
)
public class DB2017Config 

  @Primary
  @Bean(name = "dataSource")
  @ConfigurationProperties(prefix = "spring.datasource")
  public DataSource dataSource() 
    return DataSourceBuilder.create().build();
  

  @Primary
  @Bean(name = "entityManagerFactory")
  public LocalContainerEntityManagerFactoryBean 
  entityManagerFactory(
    EntityManagerFactoryBuilder builder,
    @Qualifier("dataSource") DataSource dataSource
  ) 
    return builder
      .dataSource(dataSource)
      .packages("com.domain")
      .persistenceUnit("foo")
      .build();
  

  @Primary
  @Bean(name = "transactionManager")
  public PlatformTransactionManager transactionManager(
    @Qualifier("entityManagerFactory") EntityManagerFactory 
    entityManagerFactory
  ) 
    return new JpaTransactionManager(entityManagerFactory);
  

step3> 类似地为其他数据源创建另一个配置文件,

@EnableJpaRepositories(
  entityManagerFactoryRef = "entityManagerFactory",
  basePackages =  "com.package2.repo" 

并更改前缀

@ConfigurationProperties(prefix = "spring.datasource2")

现在您将在 package1 和 package2 中分别有 2 个类似的 RequestRepository1 和 RequestRepository2,如上所述 (basePackages = "com.package1.repo" )。

step4>全部设置 autowire 2 个不同的 repo。

@Autowired
private final RequestRepository1  repo1;
@Autowired
private final RequestRepository2  repo2;

然后使用它们。

List<Request> listAdesioni = repo1.findByCodiceFiscale(codicefiscale);
List<Request> listAdesioni = repo2.findByCodiceFiscale(codicefiscale);

【讨论】:

我有 1 个模型的 6 个不同数据源...有没有比重复存储库更好的解决方案? 有点老了...一直推荐?我害怕使用 ThreadLocal。它与事务上下文兼容吗? ... 我发现了一些很棒的资源。实际上,这似乎是最好的解决方案。资源:tech.asimio.net/2017/01/17/… 和 rjbtechnology.com/blog/2017-01/…。

以上是关于Spring Boot - 不同数据库的相同存储库和相同实体的主要内容,如果未能解决你的问题,请参考以下文章

如何使用Spring Boot从不同的包中自动装配存储库接口?

Spring Boot JPA 存储库查询

Spring Boot JPA,存储库不删除记录

Spring Boot Autowired 存储库不适用于 SpringRunner 和 JPA 数据

如果从计划的作业中调用,Spring Boot 存储库不会保存到数据库

条件存储库注入 - Spring Boot