【问题标题】:How to properly code this one to many relationship according to design如何根据设计正确编码这种一对多关系
【发布时间】:2021-10-16 08:12:36
【问题描述】:

我在使用 H2 数据库在 Java 中编写以下设计时遇到问题,我想我成功地完成了 WeatherData 表与 Location 的关系,但我无法正确处理 WeatherData/WeatherDataTemperature 关系(一对多),很多那里很麻烦,因为在 WeatherDataTemperature Hibernate 类中必须添加主键,但正如您在我的模型中看到的那样,我没有主键,这只是一个练习,但我只是被阻止了,一直在看 Baeldung 教程( https://www.baeldung.com/hibernate-one-to-many) 但仍然卡住,这是我所得到的,但现在我不能将很多温度分配给 WeatherData 因为@Id 是主键,当然不能重复,请帮助

我有以下课程:

天气数据

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;

@Entity
public class WeatherData {

    @Id
    @GeneratedValue
    Long id;
    LocalDate date;
    @OneToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "location_id", referencedColumnName = "id")
    Location location;
    // Here is the problem im having I think
    @OneToMany(mappedBy = "weatherData")
    private java.util.Set<WeatherDataTemperature> weatherDataTemperature;

    WeatherData() {

    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public LocalDate getDate() {
        return date;
    }

    public void setDate(LocalDate date) {
        this.date = date;
    }

    public Location getLocationId() {
        return location;
    }

    public void setLocationId(Location location) {
        this.location = location;
    }

    public Location getLocation() {
        return location;
    }

    public void setLocation(Location location) {
        this.location = location;
    }

    public java.util.Set<WeatherDataTemperature> getWeatherDataTemperature() {
        return weatherDataTemperature;
    }

    public void setWeatherDataTemperature(java.util.Set<WeatherDataTemperature> weatherDataTemperature) {
        this.weatherDataTemperature = weatherDataTemperature;
    }

}

位置

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToOne;

@Entity
public class Location {

    @Id
    @GeneratedValue
    Long id;
    Double lat;
    Double lon;
    String city;
    String state;

    @OneToOne(mappedBy = "location")
    private WeatherData weatherData;

    Location() {

    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public Double getLat() {
        return lat;
    }

    public void setLat(Double lat) {
        this.lat = lat;
    }

    public Double getLon() {
        return lon;
    }

    public void setLon(Double lon) {
        this.lon = lon;
    }

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }

    public String getState() {
        return state;
    }

    public void setState(String state) {
        this.state = state;
    }

    public WeatherData getWeatherData() {
        return weatherData;
    }

    public void setWeatherData(WeatherData weatherData) {
        this.weatherData = weatherData;
    }

}

天气数据温度

import java.io.Serializable;

import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;

@Entity
public class WeatherDataTemperature implements Serializable {
    /**
     * 
     */
    private static final long serialVersionUID = 1L;
    @Id
    @ManyToOne
    @JoinColumn(name = "weather_data_id", nullable = false)
    private WeatherData weatherData;
    Double temperature;

    WeatherDataTemperature() {

    }

    public WeatherData getWeatherData() {
        return weatherData;
    }

    public void setWeatherData(WeatherData weatherData) {
        this.weatherData = weatherData;
    }

    public Double getTemperature() {
        return temperature;
    }

    public void setTemperature(Double temperature) {
        this.temperature = temperature;
    }

}

编辑

有没有办法让它像设计所建议的那样工作?在温度表上没有主键的情况下,这里也是一个 JSON 格式(温度最多可以为单个 WeaterData 存储 4 个不同的值):

{
    "id": 37892,
    "date": "2020-09-15",
    "location": {
        "lat": 32.7767,
        "lon": 96.7970,
        "city": "Dallas",
        "state": "Texas"
    },
    "temperature": [
        89.7,
        84.3,
        91.2,
        93.1
    ]
}

【问题讨论】:

  • 您的天气数据温度表需要自己唯一的 id 主键。天气数据 id 字段是返回天气数据表的外键。上一句是您没有将所有主键字段命名为 id 的主要原因。这对我们人类读者来说太令人困惑了。主键应该是表名和 id 连接。
  • @GilbertLeBlanc 嗨,伙计,谢谢你的回答,我也这么认为,但问题是我需要能够让它像我展示的设计一样工作,是否可以用 Java 编写代码是这样还是我必须让这个表有它自己的主键?在我的模型编码良好后,我将发布和编辑气象天气数据的 JSON 的样子
  • 关系数据库中的每个表必须有一个唯一的主键。您不必在 JSON 中显示表的主键。如果您的主键对数据库用户保密,这实际上会更好。
  • @GilbertLeBlanc 谢谢,这么多时间没有编码...我和一个朋友聊天,他说也许用 ElementCollection 注释 hibernate 可以处理它,你怎么看?
  • 我从未使用过 Hibernate。我一直编写纯 JDBC。

标签: java hibernate database-design h2


【解决方案1】:

显然,要使这项工作完全按照设计的要求进行,我不得不像这样使用@ElementCollection:

天气数据

import java.time.LocalDate;

import javax.persistence.CascadeType;
import javax.persistence.CollectionTable;
import javax.persistence.ElementCollection;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;

@Entity
public class WeatherData {

    @Id
    @GeneratedValue
    Long id;
    LocalDate date;
    @OneToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "location_id", referencedColumnName = "id")
    Location location;

    @ElementCollection
    @CollectionTable(name = "Weather_Data_Temperature")
    private java.util.Set<Double> temperature;

    WeatherData() {

    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public LocalDate getDate() {
        return date;
    }

    public void setDate(LocalDate date) {
        this.date = date;
    }

    public Location getLocationId() {
        return location;
    }

    public void setLocationId(Location location) {
        this.location = location;
    }

    public Location getLocation() {
        return location;
    }

    public void setLocation(Location location) {
        this.location = location;
    }

}

位置类没有变化

WeatherDataTemperature 类消失(如果使用 @ElementCollection,则不需要)

所以在运行项目时,h2 数据库会像这样生成:

请注意,我能够插入两个不同的温度,但它们都具有相同的 weather_data_id,就像设计建议不需要主键一样。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-12-30
    • 1970-01-01
    • 2018-10-20
    • 2019-11-11
    • 1970-01-01
    • 2018-09-29
    • 2013-05-27
    相关资源
    最近更新 更多