【问题标题】:While using @ManytoMany in Hibernate, is it possible to set non-primary keys in the provider created join table在 Hibernate 中使用 @ManytoMany 时,是否可以在提供者创建的连接表中设置非主键
【发布时间】:2016-03-15 09:49:56
【问题描述】:

假设它们是两个表:

(1)父母:parent_id(PK),parent_name,create_date,update_date

(2)孩子:child_id(PK),child_name,create_date,update_date

现在在使用@manytomany 时,将创建第三个表。让它成为: (3)父子关系

典型地,JPA 提供者将使用主键(即 parent_id 和 child_id)创建一个join table。我的问题是,我们是否有可能在更新或创建时使用@manytomany 关系设置列来设置 create_date/update_date。

【问题讨论】:

  • 您想在更新/创建父级时为子级设置 create_date/update_date 还是相反?
  • 谢谢你的回复哥们......
  • 在将父级插入到子级或子级到父级时,我需要使用 create_date/update_date 更新我的第三个表(parent_child)(基本上我们总是将 id 用于@多对多,所以我需要知道是否可以使用其他列,此处为 create_date/update_date)

标签: mysql hibernate


【解决方案1】:

如果我理解得很好,您正在尝试通过创建或更新日期时间来链接父母和孩子。这意味着您将始终必须在创建和更新期间同步这些元素,而不是像这样适当地加入它们:

SELECT
*
FROM
parent
LEFT JOIN child
    ON parent.create_date = child.create_date 
        OR parent.update_date = child.update_date;

无论如何我会说这是不安全的,因为 create_date 和 update_date 不一定是明确的。

问候

【讨论】:

  • 谢谢,我只想知道这件事是否可能,如果它是......这样做是否安全
【解决方案2】:

更新:我研究了一下,发现人们已经建立了一个关联实体来解决这类问题。这样做有一些限制,但最终结果看起来并不太糟糕。不过,可能还有一些我还没有想到的更好的设计方法。

Parent 实体将有一个OneToMany 映射到ParentChild 关联实体。必须设置mappedBy 属性以强制使用关联实体:

@Entity
public class Parent {
    @Id @GeneratedValue private Long id;

    @OneToMany(mappedBy="parent", cascade=CascadeType.ALL)
    private List<ParentChild> children = new ArrayList<ParentChild>();

    public void addChild(Child child, boolean teamLead) {
        ParentChild association = new ParentChild();
        association.setChild(child);
        association.setParent(this);
        association.setTeamLead(teamLead);
        children.add(association);
        child.setParent(this);
    }
    public Long getId() { return id; }

}

子实体将持有对父实体的引用,这与单向 ManyToMany 关系通常一样。

@Entity
public class Child {
    @Id @GeneratedValue private Long id;

    @ManyToOne
    private Parent parent;

    public Parent getParent() { return parent; }
    public void setParent(Parent parent) { this.parent = parent; }
    public Long getId() { return id; }
    public void setId(Long id) { this.id = id; }
}

然后关联实体将具有对两个实体的ManyToOne 引用,以及一个主键。由于@MapsId 注释,关联引用使用与primary key 相同的id 字段。

@Entity
public class ParentChild {
    @EmbeddedId
    private ParentChildKey id;

    @ManyToOne
    @MapsId("parentId")
    private Parent parent;

    @ManyToOne
    @MapsId("childId")
    private Child child;

    private boolean teamLead;

    public ParentChild() { id = new ParentChildKey(); }
    public boolean isTeamLead() { return teamLead; }
    public void setTeamLead(boolean teamLead) { this.teamLead = teamLead; }
    public Parent getParent() { return parent; }
    public void setParent(Parent parent) { this.parent = parent; id.setParentId(parent.getId());}
    public Child getChild() { return child; }
    public void setChild(Child child) { this.child = child; id.setChildId(child.getId());}

}

主键实体没有什么特别之处。

@Embeddable
public class ParentChildKey implements Serializable {
    private static final long serialVersionUID = 1L;
    private Long parentId;
    private Long childId;
    public Long getParentId() { return parentId; }
    public void setParentId(Long parentId) { this.parentId = parentId; }
    public Long getChildId() { return childId; }
    public void setChildId(Long childId) { this.childId = childId; }    
    ... getters and setters
}

所以,它为我做了一个插入和选择,没有太多麻烦,但你可以看到它似乎只是为一个额外的字段做了大量的额外工作。当然,额外的字段(在本例中为teamLead)被有效地存储,但我可以想象一种“角色”类型的配置,从长远来看会更容易使用并且更有意义。

【讨论】:

  • 谢谢,但是我已经尝试过使用一对多和多对一,同时显式创建第三个表。然后它工作正常,所以现在我尝试使用多对多来处理这个场景创建第三个表..(是否可能(只是出于好奇))
  • 我想知道hibernate是否可以在不显式创建第三个表的情况下自行管理
猜你喜欢
  • 2021-12-21
  • 1970-01-01
  • 1970-01-01
  • 2019-12-22
  • 2011-01-14
  • 2011-04-15
  • 2015-06-15
  • 2023-01-04
  • 1970-01-01
相关资源
最近更新 更多