具有一对多关系的保存实体

时间:2019-03-30 03:57:15

标签: java hibernate

我认为我的休眠数据库设置不正确。我有Citizen个实体,它们与WeeklyCare实体具有一对多的关系。下面是相关代码。

公民:

@Entity
@Table(name = "citizens")
public class Citizen {
@Id
@Size(max = 10, min = 10, message = "CPR must be exactly 10 characters")
private String cpr;

@OneToMany()
@JoinColumn(name = "cpr")
private List<WeeklyCare> weeklyCare;
}

每周护理:

@Entity
public class WeeklyCare {
@EmbeddedId
private WeeklyCareIdentifier weeklyCareIdentifier;
}

WeeklyCareIdentifier:

@Embeddable
public class WeeklyCareIdentifier implements Serializable {

@NotNull
@Size(max = 10, min = 10, message = "CPR must tbe exactly 10 characters")
private String cpr;

@NotNull
private Integer week;

@NotNull
private Integer year;
}

要将数据保存到数据库时遇到一些问题:

  1. 我无法先保存WeeklyCare,因为它需要Citizen
  2. 当我将市民发送到我的后端时,对象包含WeeklyCare的列表。当我尝试拯救公民时,它给了我这个错误:Unable to find Application.Models.WeeklyCare with id Application.Models.WeeklyCareIdentifier@b23ef67b

我可以通过以下方法解决该问题:在保存之前清除WeeklyCare上的Citizen列表,然后在之后保存WeeklyCare列表,但这听起来像是一种糟糕的方法做吧。

我想我想让休眠状态在保存WeeklyCare时忽略Citizen的列表,但是在获取Citizen时确认它。这可能吗?还是有更好的方法呢?谢谢。

1 个答案:

答案 0 :(得分:0)

  
      
  1. 我不能先保存WeeklyCare,因为它需要公民。
  2.   

您在两个实体中使用了“ cpr”标识符:

  • 这是Citizen的主要ID
  • 它是WeeklyCare的综合ID的一部分

从理论上讲,您可以创建WeeklyCare的列表(虽然现在不采用它的建模方式),然后将每个WeeklyCare的关联更新为Citizen

  
      
  1. 当我将公民发送到后端时,这些对象包含WeeklyCare列表。当我试图拯救公民时,它给了我   错误:找不到ID为Application.Models.WeeklyCare   Application.Models.WeeklyCareIdentifier@b23ef67b
  2.   

映射一对多关联的最佳方法是双向。这还将使您免于仅在将@OneToMany与@JoinColumn一起使用时Hibernate生成的一些不必要的查询。

1)从WeeklyCareIdentifier类中删除cpr(并可能重命名该类)。

@Embeddable
public class WeeklyCareIdentifier implements Serializable {

  @NotNull
  private Integer week;

  @NotNull
  private Integer year;

  //constructors, getters, setters
}

2)删除复合@EmbeddedId,以使用Long id字段:

@Entity
public class WeeklyCare {

  @Id
  @GeneratedValue
  private Long id;

  @Embedded
  private WeeklyCareIdentifier weeklyCareIdentifier;

  //constructors, getters, setters
}

3)转到双向映射:

@Entity
@Table(name = "citizens")
public class Citizen {
  @Id
  @Size(max = 10, min = 10, message = "CPR must be exactly 10 characters")
  private String cpr;

  @OneToMany(
      mappedBy = "citizen",
      cascade = CascadeType.ALL, //cascade all operations to children
      orphanRemoval = true //remove orphaned WeeklyCare if they don't have associated Citizen
  )
  private List<WeeklyCare> weeklyCares = new ArrayList<>(); //init collections to avoid nulls

    //constructors, getters, setters

    //add utility methods to manipulate the relationship

    public void addWeeklyCare(WeeklyCare weeklyCare) {
      weeklyCares.add(weeklyCare);
      weeklyCare.setCitizen(this);
    }

    public void removeWeeklyCare(WeeklyCare weeklyCare) {
      weeklyCares.remove(weeklyCare);
      weeklyCare.setCitizen(null);
    }
}

和:

@Entity
public class WeeklyCare {

    @Id
    @GeneratedValue
    private Long id;

    //having reference to the citizen entity from WeeklyCare
    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "citizen_cpr")
    private Citizen citizen;

    @Embedded
    private WeeklyCareIdentifier weeklyCareIdentifier;

    //constructors, getters, setters
}

即使cpr是唯一的,我也建议对实体使用Long ID。将cpr转换为普通列,并在内部域中引入一个DB生成的ID列,您可以将其与之结合使用,并将cpr视为纯面向用户的数据列。