Java:Hibernate @OneToOne映射

26

我试图让Hibernate的@OneToOne注释正常工作,但是效果不太好...

假设我有一个名为status的表格,样子像这样:

+------------------------------------------------+
|                     status                     |
+------------------------------------------------+
| id | frn_user_id | frn_content_id |   status   |
+----+-------------+----------------+------------+
|  1 |     111     |        0       |  "active"  |
+----+-------------+----------------+------------+
|  2 |      0      |       222      | "inactive" |
+----+-------------+----------------+------------+

我有一个名为User的实体,看起来像这样:

@Entity
@Table(name = "user")
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "id", nullable = false)
    private Integer id;

    @OneToOne(cascade = CascadeType.ALL, fetch = FetchType.EAGER, mappedBy = "userId")
    private Status status;

    // getters and setters
}

还有一个类似的用于内容,以及另一个实体用于状态,看起来像这样:

@Entity
@Table(name = "status")
public class Status {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "id", nullable = false)
    private Integer id;

    @Column(name = "frn_user_id")
    private Integer userId;

    @Column(name = "frn_content_id")
    private Integer contentId;

    @Column(name = "status")
    private String status;

    // getters and setters
}

当我在User上执行读操作时,我期望User.getStatus()返回一个Status对象,其中id=1。但是,我得到了一个AnnotationException:"Referenced property not a (One|Many)ToOne: Status.userId in mappedBy User.status"

我已经仔细阅读了文档、教程和这里的示例,但迄今为止我尝试的所有方法都失败了。

值得注意的另一点是:这应该支持一对零或一的关系,因为一些usercontent记录在status表中没有引用。

任何帮助都将不胜感激!


2
userId需要是类型为User,并带有一个@OneToOne/@JoinColumn。另外请注意您有一个拼写错误(contentId/userId)。 - user180100
请参见https://dev59.com/M3XYa4cB1Zd3GeqP-tN4?rq=1,其中涉及JPA Hibernate的OneToOne mappedBy注释问题。 - user180100
一个数据库设计的想法:也许可以重新考虑你的设计,将用户和内容之间设置为多对多的关系,并且状态描述会成为该设计中的一个用户属性? - Jorge_B
谢谢@RC。我没意识到它必须是一个对象。 - Shaun Scovil
@Jorge_B 是的,数据库设计并不理想,但目前我还被困在它里面。 - Shaun Scovil
2个回答

77

您的状态实体不得具有类型为Integer的userIdcontentId属性,这些属性已经被映射为@Column。它必须具有类型为User和Content的usercontent属性,这些属性应该使用@OneToOne进行映射:

public class User {
    @OneToOne(mappedBy = "user")
    private Status status;
    // ...
}

public class Status {
    @OneToOne
    @JoinColumn(name = "frn_user_id")
    private User user;
    // ...
}

一个用户拥有一个状态。每个状态属于一个用户。


谢谢分享。我在过去的三天里一直卡在mappedBy上。我通过谷歌并阅读了很多Stackoverflow的帖子,但是没有什么好运气。当我看到你的解决方案时,我想起了我在关系的反向侧创建了一个java.util.Set用于OneToOne映射。当我移除了Set并只创建了实体类型属性后,我的代码开始工作。非常感谢。点赞。 - OO7
我在阅读了@Vlad Mihalcea在这篇帖子上的回答后有些困惑。在他的回答中,Child很多玩具,那么为什么他用OneToOne(mappedBy = "child")注解了List<Toy> toys?为什么不用OneToMany此外,你在StatusUser上指定了JoinColumn,而Vlad Mihalcea在ToyChild上没有指定。*mappedByJoinColumn的目的是什么?*请帮我解答一下我的疑问。 - OO7
1
这是错误的。应该是OneToMany。JoinColumn用于指定连接列的名称。如果您没有指定一个,Hibernate将使用默认名称(如何构造此默认名称在JPA规范中指定)。 - JB Nizet
我使用了你在这里提到的相同代码。但是我仍然得到了frn_user_id为空的结果。 - viper

0
使用这种方法。在客户实体中添加以下字段。
@OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL, mappedBy = "customer")
private Status status;

不要为客户实体中的状态字段添加getter和setter。 并将以下代码添加到状态实体中。
@OneToOne(fetch = FetchType.LAZY, optional = false)
@JoinColumn(name = "customer_id", nullable = false)
private Customer customer;

在 Status Entity 类中添加客户字段的 getter 和 setter。你可以在这里看到一个工作示例here

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接