繁体   English   中英

映射ManyToOne双向关系,其中一侧具有复合主键

[英]mapping ManyToOne bidirectional relation where one side has a composite primary key

我有一个用于存储使用复合主键的Workshops的实体。

我不喜欢自动生成密钥的概念,并且直到现在,大多数人还是使用业务衍生密钥,例如实体的电子邮件ID等。 但是在这里,工作坊实体似乎没有主键的自然候选者,因此我选择了组合键。我创建了一个WorkshopIdType ,它是一个枚举,包含将要组织的三个可能的工作坊

public enum WorkshopIdType implements Serializable {

  FOUNDATION("FND"), INTERMEIDATE("IMT"), ADVANCED("ADV");

  private final String name;

  private WorkshopIdType(String name) {
    this.name = name;
  }

  @Override
  public String toString() {
    return this.name;
  }

  public boolean equals(String otherName) {
    return (otherName == null) ? false : name.equals(otherName);
  }
}

然后,我有一个Embeddable类作为主键; 在这种情况下,研讨会类型和日期的组合在我看来是最适合主键的

@Embeddable
@Access(AccessType.FIELD)
public class WorkshopId implements Serializable {

  private static final long serialVersionUID = -7287847106009163526L;

  private String workshopIdType;

  private Date date;

  @Column(name = "id", nullable = false)
  public String getWorkshopIdType() {
    return workshopIdType;
  }

  public void setWorkshopIdType(WorkshopIdType workshopIdType) {
    this.workshopIdType = workshopIdType.toString();
  }

  @Temporal(TemporalType.DATE)
  @Column(name = "date", nullable = false)
  public Date getDate() {
    return date;
  }

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

该实体还与Venue建立了ManyToOne关系,这里的Venues实际上是三个城市中预先指定的五个中心

@Entity
public class Workshop implements Serializable {

  private static final long serialVersionUID = -5516160437873476233L;

  private WorkshopId id;

  private Venue venue;

  private Integer seatsAvailable;

  @EmbeddedId
  public WorkshopId getId() {
    return id;
  }

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

  @ManyToOne
  @JoinTable(name = "workshop_venue", joinColumns = { @JoinColumn(name = "workshop_id", referencedColumnName = "id") }, inverseJoinColumns = { @JoinColumn(name = "venue_name", referencedColumnName = "name") })
  public Venue getVenue() {
    return venue;
  }

  public void setVenue(Venue venue) {
    this.venue = venue;
  }

  @Column(name = "seats_available", nullable = false)
  public Integer getSeatsAvailable() {
    return seatsAvailable;
  }

  public void setSeatsAvailable(Integer seatsAvailable) {
    this.seatsAvailable = seatsAvailable;
  }
}

问题是在使用复合键的情况下将此ManyToOne与JoinTable映射

@ManyToOne
  @JoinTable(name = "workshop_venue", joinColumns = { @JoinColumn(name = "workshop_id", referencedColumnName = "id") }, inverseJoinColumns = { @JoinColumn(name = "venue_name", referencedColumnName = "name") })
  public Venue getVenue() {
    return venue;
  }

如我所料,这将无法正常工作,无法找到逻辑名称为“ id”的列。 我将通过JoinTable使用ManyToOne,因为在某些情况下,用户应该了解针对给定场地安排了培训。 在这种情况下,如何指定referencedColumnName?

还是我在建模时弄错了一切?

您有一个复合主键,由嵌入在Workshop的可嵌入WorkshopId表示。 主键的两个字段都需要连接到链接表中的目标实体–因此,您需要2个连接列和1个反向连接。 您只需要添加丢失的联接;

  @ManyToOne
  @JoinTable(name = "workshop_venue", 
            joinColumns = 
                  { @JoinColumn(name = "workshop_id", referencedColumnName = "id"),
                    /* Add this joincolumn */ 
                    @JoinColumn(name = "date_id", referencedColumnName = "date") }, 
            inverseJoinColumns = 
                  { @JoinColumn(name = "venue_name", referencedColumnName = "name") })
  public Venue getVenue() {
    return venue;

当然,您需要确保链接表具有这三个字段。 我猜您缺少date_id列。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM