【问题标题】:JPA (hibernate) onetomany relationJPA(休眠)单机关系
【发布时间】:2010-07-27 17:21:25
【问题描述】:

我不确定建立双向单机关系(休眠引擎)缺少什么。领域模型的缩小版:

class Person {
@OneToMany(mappedBy="personFrom", cascade = CascadeType.PERSIST)
    public List<Relationship> relationships;
}

class Relationship {
@ManyToOne
  public Person personFrom;

  @ManyToOne
  public Person personTo;
}

一些观察:
1. 使用上面的映射,没有创建连接表。
2. 当我删除 mappedBy (@OneToMany(cascade = CascadeType.PERSIST) ) 时,会创建连接表,我可以通过 Person 保持关系。 “personFrom”字段为空,但我认为这是正常的,因为关系是通过连接表维护的。

我也尝试在关系中指定连接列,但没有任何区别。任何帮助,高度赞赏。 谢谢。

编辑:1

根据 Dan 的评论,如果看到域类的完整内容很重要,我在下面展开了它们。

class Relationship extends Model{

  @ManyToOne
  public RelationshipType relationshipType;

  @ManyToOne
  public Person personFrom;

  @ManyToOne
  public Person personTo;

  @ManyToOne
  public Person createdBy;

  @ManyToOne
  public Role roleFrom;

  @ManyToOne
  public Role roleTo;

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

class Person extends Model {

    public Date dateCreated;

    @Lob
    public String description;

    @OneToMany(cascade = CascadeType.ALL)
    public List<Role> roles;

    @OneToMany(mappedBy="personFrom", cascade = CascadeType.PERSIST)
    public List<Relationship> relationships;
}

Role 也与 Person 相关,但我认为保留 personFrom、personTo 有助于优化我的查询。

Role extends Model {

    @ManyToOne
    public RoleType roleType;

    @ManyToOne
    public Person createdBy; 
}

【问题讨论】:

  • Relationship 是否只有如图所示的两个字段?这将使它有资格进行@JoinTable 简化。
  • 感谢 Dan,我通过您的评论了解了 @JoinTable。请查看域模型的更新。

标签: java hibernate jpa orm


【解决方案1】:

使用上述映射,没有创建连接表。

OneToMany 不需要连接表,您将在多端获得外键列。这就是我在使用您的代码时得到的:

create table Person (
    id bigint not null,
    primary key (id)
)

create table Relationship (
    id bigint not null,
    personFrom_id bigint,
    personTo_id bigint,
    primary key (id)
)

alter table Relationship 
    add constraint FK499B69164A731563 
    foreign key (personTo_id) 
    references Person

alter table Relationship 
    add constraint FK499B691698EA8314 
    foreign key (personFrom_id) 
    references Person

这是预期的结果(至少对我而言)。也许你真正想要的是ManyToMany

当我删除 mappedBy (@OneToMany(cascade = CascadeType.PERSIST) ) 时,会创建连接表,我可以通过 Person 保持关系。 “personFrom”字段为空,但我认为这是正常的,因为关系是通过连接表维护的。

我使用提供的代码(使用 Hibernate 的 API,但这不会改变任何东西)编写了一个小型单元测试,但我不明白问题所在(会话是在测试方法之前创建的,并且该方法在交易):

Person p1 = new Person();
Person p2 = new Person();
Relationship r = new Relationship();

// create the personFrom bi-directional association
r.setPersonFrom(p1);
List<Relationship> relationships = new ArrayList<Relationship>();
relationships.add(r);
p1.setRelationships(relationships); // these four lines should be moved to some 
                                    // link management method (see update below).

// create the personTo uni-directional association
r.setPersonTo(p2);

session.persist(p2);
session.persist(p1);

assertNotNull(p2.getId());
assertNotNull(p1.getId());
assertNotNull(r.getId());

以上代码导致在 Person 表中插入两次,在关系表中插入一次(对 3 列进行赋值)。

正如我所说,我不明白这个问题。也许您应该解释预期的结果是什么(关系模型和查询)。

更新: 完全清楚的是,在使用双向关联时,您必须设置链接的两侧,一个常见的模式是使用防御性链接管理方法来正确设置两侧协会的。像这样的:

public void addToRelationships(Relationship relationship) {
    if (this.relationships == null) {
       this.relationships = new ArrayList<Relationship>();
    }
    this.relationships.add(relationship);
    relationship.setPersonFrom(this);
}

Hibernate 文档的1.2.6. Working bi-directional links 部分对此进行了详细说明。

【讨论】:

  • 我非常感谢你,因为你第二次救了我。我的印象是拥有实体(Person)管理映射关系,所以我不想明确设置它.行:r.setPersonFrom(p1);您的测试用例清楚地说明了如何正确地保留实体谢谢。我有一个关于单向一对多的类似 qn,我将在单独的 qn 中询问。再次感谢您的时间和帮助。
  • Pascal Thivent .. 我阅读了有关 JPA oneToOne 映射的更多信息,并从疑虑中解脱出来.. 我还有另一个疑问,与双向映射的 yaml 语法有关.. 请在此处查看..@987654322 @您的专业知识可能对我有所帮助。谢谢。
【解决方案2】:

您是否将外键列名称指定为连接列的名称?假设外键列名为 PERSON_ID,代码应如下所示:

class Relationship {
    @ManyToOne
    @JoinColumn(name="PERSON_ID")
    public Person personFrom;
    ...
}

【讨论】:

  • 没有任何区别..除了person_id之外的所有列都正确填写..但是,没有连接表。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-07-21
  • 2014-09-21
  • 2017-09-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多