Java JPA Hibernate 一对一关系

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/787698/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 19:30:02  来源:igfitidea点击:

JPA Hibernate One-to-One relationship

javahibernatejpa

提问by Steve Kuo

I have a one-to-one relationship but hibernatetool complains when generating the schema. Here's an example that shows the problem:

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

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

    @OneToOne
    public OtherInfo otherInfo;

    rest of attributes ...
}

Person has a one-to-one relationship with OtherInfo:

Person 与 OtherInfo 是一对一的关系:

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

    rest of attributes ...
}

Person is owning side of OtherInfo. OtherInfo is the owned side so person uses mappedByto specify the attribute name "otherInfo" in Person.

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

I get the following error when using hibernatetool to generate the database schema:

使用 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)
        ...

Any idea why? Am I a doing something wrong or is this a Hibernate bug?

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

采纳答案by topchef

JPA doesn't allow the @Idannotation on a OneToOneor ManyToOnemapping. What you are trying to do is one-to-one entity association with shared primary key. The simplest case is unidirectional one-to-one with shared key:

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

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

    @OneToOne
    @PrimaryKeyJoinColumn
    private OtherInfo otherInfo;

    rest of attributes ...
}

The main problem with this is that JPA provides no support for shared primary key generation in OtherInfoentity. The classic book Java Persistence with Hibernate by Bauer and Kinggives the following solution to the problem using Hibernate extension:

这样做的主要问题是 JPA 不支持其他信息实体中的共享主键生成。Bauer 和 King的经典著作Java Persistence with Hibernate给出了以下使用 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 ...
}

Also, see here.

另外,请参见此处

回答by razenha

I'm not sure you can use a relationship as an Id/PrimaryKey in Hibernate.

我不确定您是否可以在 Hibernate 中将关系用作 Id/PrimaryKey。

回答by Jugal

Try this

尝试这个

@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 ...
}

回答by waxwing

I think you still need the primary key property in the OtherInfo class.

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

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

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

    rest of attributes ...
}

Also, you may need to add the @PrimaryKeyJoinColumn annotation to the other side of the mapping. I know that Hibernate uses this by default. But then I haven't used JPA annotations, which seem to require you to specify how the association wokrs.

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

回答by Vodo-Siosk Baas

I have a better way of doing this:

我有一个更好的方法来做到这一点:

@Entity
public class Person {

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

}

That's all

就这样

回答by Mariusz

This should be working too using JPA 2.0 @MapsId annotation instead of Hibernate's GenericGenerator:

这也应该使用 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 ...
}

More details on this in Hibernate 4.1 documentation under section 5.1.2.2.7.

在 Hibernate 4.1 文档的 5.1.2.2.7 节下有更多细节。

回答by Igor Sadovnikov

You just need to add @JoinColumn(name="column_name")to Host Entity relation . column_name is the database column name in person table.

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

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

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

    rest of attributes ...
}

Person has a one-to-one relationship with OtherInfo: mappedBy="var_name" var_name is variable name for otherInfo in Person class.

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

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

    rest of attributes ...
}