JPA(休眠)onetomany关系

时间:2010-07-27 17:21:26

标签: java hibernate jpa orm

我不确定我缺少什么来建立双向的onetomany关系(hibernate引擎)。域模型的缩小版本:

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;
}

角色也与Person有关,但我认为保持personFrom,personTo有助于优化我的查询。

Role extends Model {

    @ManyToOne
    public RoleType roleType;

    @ManyToOne
    public Person createdBy; 
}

2 个答案:

答案 0 :(得分:2)

  

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

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

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表中的两个插入和Relationship表中的一个插入(估计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部分。

答案 1 :(得分:0)

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

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