26

I'm trying to get Hibernate @OneToOne annotations working and not having much success here...

Let's say I've got a table called status that looks like this:

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

And I've got an entity for User that looks like this:

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

And a similar one for Content, and another entity for Status that looks like this:

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

When I perform a read on User, I expect that User.getStatus() will return a Status object with id=1. Instead, I get an AnnotationException: "Referenced property not a (One|Many)ToOne: Status.userId in mappedBy User.status"

I've poured through docs, tutorials and examples here on SO, but everything I've tried so far has failed.

Also worth noting: This should support a one-to-zero-or-one relationship, as some user and content records will not have a reference in the status table.

Any help would be greatly appreciated!

BuZZ-dEE
  • 6,075
  • 12
  • 66
  • 96
Shaun Scovil
  • 3,905
  • 5
  • 39
  • 58
  • 2
    `userId` needs to be of type `User` with a `@OneToOne`/`@JoinColumn` on it. Also note you have a typo (contentId/userId) –  Feb 13 '14 at 18:20
  • see also http://stackoverflow.com/questions/18303522/jpa-hibernate-issue-with-onetoone-mappedby-annotation?rq=1 –  Feb 13 '14 at 18:21
  • Just a database design idea: maybe you could reconsider your design as a many-to-many relationship between users and contents, and the status description would be in that design a user attribute? – Jorge_B Feb 13 '14 at 18:24
  • Thanks @RC. I didn't realize it had to be an object. – Shaun Scovil Feb 13 '14 at 18:27
  • @Jorge_B Yeah the DB design is not ideal but I'm stuck using it for the time being.. – Shaun Scovil Feb 13 '14 at 18:27

2 Answers2

77

Your Status entity must not have properties userId and contentId of type Integer, mapped with @Column. It must have properties user and content of type User and Content, mapped with @OneToOne:

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

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

A user has one status. A status has one user.

JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
  • Thanks for sharing this. I was stucked on `mappedBy` from last 3 days. I Googled & go through so many Stackoverflow posts for this, but no luck at all. When I go through your solution, then I remember **I have created a `java.util.Set` in `OneToOne` mapping on the reverse side of relation**. As soon as **I removed the `Set` & just create Entity type property, my code starts working**. Thank you so much. Upvote. – OO7 Apr 10 '15 at 08:49
  • I am a bit confused after gone through [@Vlad Mihalcea Answer on this post](http://stackoverflow.com/questions/23925322/delete-child-from-parent-and-parent-from-child-automatically-with-jpa-annotation/23926548#23926548). In his answer, `Child` has `many toys` then *why he has annotated `List toys` with `OneToOne(mappedBy = "child")` ? Why not with `OneToMany` ?* Also you have specified `JoinColumn` on `User` in `Status` & Vlad Mihalcea didn't on `Child` in `Toy`. *What is the objective of `mappedBy` with/without `JoinColumn` ?* Will you please clear my doubt ? – OO7 Apr 10 '15 at 09:10
  • 1
    It's wrong. It should be OneToMany. JoinColumn is used to specify the name of the join column. If you don't specify one, Hibernate will use a defaukt name (How this default name is constructed name is specified in the JPA spec) – JB Nizet Apr 10 '15 at 09:19
  • I used the same code as you mentioned here. But still I get the frn_user_id as null – viper Aug 24 '16 at 10:35
0

use this way. Add below field in Customer entity.

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

and don't add getter and setter for status field in Customer entity. And add below code to Status Entity.

@OneToOne(fetch = FetchType.LAZY, optional = false)
@JoinColumn(name = "customer_id", nullable = false)
private Customer customer;

Here add the getter and setter for customer field in Status Entity class. You can see one working example here.

Abhishek
  • 648
  • 7
  • 8