我认为我的休眠数据库设置不正确。我有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;
}


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


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


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

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

最佳答案

我不能先保存WeeklyCare,因为它需要一个公民。
  


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


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


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


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


映射一对多关联的最佳方法是双向。这也将使您免于仅在将@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视为纯面向用户的数据列。

09-10 02:36