使用Hibernate的Spring Boot应用程序如何与多个结构相同的表进行交互?

时间:2019-03-28 10:19:35

标签: java mysql hibernate spring-boot jpa

我有一个名为“ currency”的MySQL数据库,其中包含一百多个表,每个表都对应一种货币,并且都具有相同的结构(2列,日期时间为时间戳,浮点数为汇率)。

Spring Boot Application如何与该结构交互?

我只想将一个类CurrencyRate与字段和getter / setter方法一起使用。如果我将此类标记为@Entity@Table,则只能访问一个表。我已经研究了@SecondaryTable标记,但是它似乎仅适用于我们希望一次与多个表进行交互而不仅仅是一个表的情况。

import java.io.Serializable;
import java.util.Date;

import javax.persistence.Id;
import javax.validation.constraints.NotBlank;

import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.DateSerializer;
import com.fasterxml.jackson.databind.ser.std.NumberSerializers.FloatSerializer;

public abstract class CurrencyRate implements Serializable {

    @Id
    @JsonSerialize(using=DateSerializer.class)
    private Date datetime;

    @NotBlank
    @JsonSerialize(using=FloatSerializer.class)
    private float rate;

    Date getDate () { return this.datetime; }
    void setDate (Date timestamp) { this.datetime = timestamp; }
    float getRate () { return this.rate; }
    void setRate (float rate) { this.rate = rate; } 
}

我的想法是,可以使CurrencyRate为抽象类(如提供的图像),然后为从该类继承的每种货币创建一个类。这将是非常繁琐的,但至少可能会起作用。但是,似乎不仅我必须为每个货币模型创建一个类,而且还要为每个存储库创建一个类。

除非有一种方法可以不做所有这些事情而服务于此结构?有任何想法吗?目前正在查看文档并寻找有此问题的其他人,但是这种结构似乎并不常见。

编辑:

我想添加控制器,因为我认为这是区分抽象类的子代的逻辑问题的位置。

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/rates")
class CurrencyRateController {

    @Autowired
    private CurrencyRateService service;

    @GetMapping("/allEUR")
    public List<CurrencyRate> getAllEUR() {
        return service.findAll();
    }

    @GetMapping("/allCAD")
    public List<CurrencyRate> getAllCAD() {
        return service.findAll();
    }
}

我假设上面的控制器返回/ allCAD和/ allEUR的CAD值,因为CurrencyRateService使用CurrencyRateRepository。 Hibernate在某个地方尝试区分EUR子类和CAD子类,但是它们是相同的。因此,将为所有请求提供CAD值。

2 个答案:

答案 0 :(得分:0)

可能您必须使用正确的继承策略。像这样:

@Entity
@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS)
public abstract class CurrencyRate {
  (... omitted for brevity ...)
}

子类:

@Entity
@Table(name="USDOLLAR")
public class UnitedStatesDollar extends CurrencyRate {
}

@Entity
@Table(name="EURO")
public class Euro extends CurrencyRate {
}

与其他货币相同。您应该能够针对CurrencyRate类进行查询,从所有表中检索所有结果,并且您将必须使用instanceof来区分货币。此外,您还可以针对一种货币执行查询。

如果您想了解有关继承的更多信息,请查看here

答案 1 :(得分:0)

在您的方案中,我认为应该使用单表策略,因为它将为每个类层次结构创建一个表。如果我们未明确指定,这也是JPA选择的默认策略。 您可以通过将@Inheritance批注添加到超类来定义要使用的策略: 父实体:-

@Entity
@Inheritance(strategy = InheritanceType.SINGLE_TABLE)
public class CurrencyRate  {
    @Id
    @JsonSerialize(using=DateSerializer.class)
    private Date datetime;

    @NotBlank
    @JsonSerialize(using=FloatSerializer.class)
    private float rate;

    // constructor, getters, setters
}

没有字段的子类:-

@Entity
public class Rupee extends CurrencyRate {

}

@Entity
public class Dollar extends CurrencyRate {

}

由于所有实体的记录都将在同一表中,因此Hibernate提供了一种区分这些表行的方法。 在这种情况下,将添加一个名为DTYPE的区分符列,该列将实体名称作为值。

您可以为CurrencyRate创建存储库,然后根据DType列查询CurrencyRate表。