JPA Hibernate一对一的关系

时间:2009-04-24 21:48:54

标签: java hibernate jpa

我有一对一的关系,但hibernatetool在生成架构时抱怨。这是一个显示问题的示例:

@Entity
public class Person {
    @Id
    public int id;

    @OneToOne
    public OtherInfo otherInfo;

    rest of attributes ...
}

Person与OtherInfo有一对一的关系:

@Entity
public class OtherInfo {
    @Id
    @OneToOne(mappedBy="otherInfo")
    public Person person;

    rest of attributes ...
}

Person拥有OtherInfo的一面。 OtherInfo是拥有方,因此人使用mappedBy在Person中指定属性名称“otherInfo”。

使用hibernatetool生成数据库模式时出现以下错误:

org.hibernate.MappingException: Could not determine type for: Person, at table: OtherInfo, for columns: [org.hibernate.mapping.Column(person)]
        at org.hibernate.mapping.SimpleValue.getType(SimpleValue.java:292)
        at org.hibernate.mapping.SimpleValue.createIdentifierGenerator(SimpleValue.java:175)
        at org.hibernate.cfg.Configuration.iterateGenerators(Configuration.java:743)
        at org.hibernate.cfg.Configuration.generateDropSchemaScript(Configuration.java:854)
        at org.hibernate.tool.hbm2ddl.SchemaExport.<init>(SchemaExport.java:128)
        ...

知道为什么吗?我是做错了还是这是一个Hibernate错误?

7 个答案:

答案 0 :(得分:85)

JPA不允许 OneToOne ManyToOne 映射中的 @Id 注释。您要做的是与共享主键的一对一实体关联。最简单的情况是使用共享密钥进行单向一对一:

@Entity
public class Person {
    @Id
    private int id;

    @OneToOne
    @PrimaryKeyJoinColumn
    private OtherInfo otherInfo;

    rest of attributes ...
}

此问题的主要问题是JPA不支持 OtherInfo 实体中的共享主键生成。经典书籍Java Persistence with Hibernate by Bauer and King使用Hibernate扩展为问题提供了以下解决方案:

@Entity
public class OtherInfo {
    @Id @GeneratedValue(generator = "customForeignGenerator")
    @org.hibernate.annotations.GenericGenerator(
        name = "customForeignGenerator",
        strategy = "foreign",
        parameters = @Parameter(name = "property", value = "person")
    )
    private Long id;

    @OneToOne(mappedBy="otherInfo")
    @PrimaryKeyJoinColumn
    public Person person;

    rest of attributes ...
}

另请参阅here

答案 1 :(得分:23)

这也应该使用JPA 2.0 @MapsId注释而不是Hibernate的GenericGenerator:

@Entity
public class Person {

    @Id
    @GeneratedValue
    public int id;

    @OneToOne
    @PrimaryKeyJoinColumn
    public OtherInfo otherInfo;

    rest of attributes ...
}

@Entity
public class OtherInfo {

    @Id
    public int id;

    @MapsId
    @OneToOne
    @JoinColumn(name="id")
    public Person person;

    rest of attributes ...
}

有关详细信息,请参阅第5.1.2.2.7节中的Hibernate 4.1文档。

答案 2 :(得分:10)

您只需要将@JoinColumn(name="column_name")添加到主机实体关系。 column_name是person表中的数据库列名。

@Entity
public class Person {
    @Id
    public int id;

    @OneToOne
    @JoinColumn(name="other_info")
    public OtherInfo otherInfo;

    rest of attributes ...
}

Person与OtherInfo有一对一的关系: mappedBy =“var_name”var_name是Person类中otherInfo的变量名。

@Entity
public class OtherInfo {
    @Id
    @OneToOne(mappedBy="otherInfo")
    public Person person;

    rest of attributes ...
}

答案 3 :(得分:4)

我认为你仍然需要OtherInfo类中的主键属性。

@Entity
public class OtherInfo {
    @Id
    public int id;

    @OneToOne(mappedBy="otherInfo")
    public Person person;

    rest of attributes ...
}

此外,您可能需要将@PrimaryKeyJoinColumn注释添加到映射的另一侧。我知道Hibernate默认使用它。但后来我没有使用JPA注释,这似乎要求你指定关联的方式。

答案 4 :(得分:2)

我有更好的方法:

@Entity
public class Person {

    @OneToOne(cascade={javax.persistence.CascadeType.ALL})
    @JoinColumn(name = "`Id_OtherInfo`")
    public OtherInfo getOtherInfo() {
      return otherInfo;
    }

}

这就是全部

答案 5 :(得分:1)

我不确定你可以在Hibernate中使用关系作为Id / Primary Key。

答案 6 :(得分:1)

试试这个

@Entity

@Table(name="tblperson")

public class Person {

public int id;

public OtherInfo otherInfo;
@Id //Here Id is autogenerated
@Column(name="id")
@GeneratedValue(strategy=GenerationType.AUTO)
public int getId() {
    return id;
}
public void setId(int id) {
    this.id = id;
}

@OneToOne(cascade = CascadeType.ALL,targetEntity=OtherInfo.class)
@JoinColumn(name="otherInfo_id") //there should be a column otherInfo_id in Person
public OtherInfo getOtherInfo() {
    return otherInfo;
}
public void setOtherInfo(OtherInfo otherInfo) {
    this.otherInfo= otherInfo;
}
rest of attributes ...
}


@Entity

@Table(name="tblotherInfo")

public class OtherInfo {

private int id;

private Person person;

@Id

@Column(name="id")
@GeneratedValue(strategy=GenerationType.AUTO)
public Long getId() {
    return id;
}
public void setId(Long id) {
    this.id = id;
}

  @OneToOne(mappedBy="OtherInfo",targetEntity=Person.class)   
public College getPerson() {
    return person;
}
public void setPerson(Person person) {
    this.person = person;
}    
 rest of attributes ...
}