Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Hibernate - bidirectional @OneToOne

I have 2 classes: User and UserPicture which have a 1:1 relationship.

public class User {
     @Id
     @GeneratedValue(strategy=GenerationType.AUTO)
     @Column(name="id", nullable = false, unique = true)
 private int id;

     private String firstname;

     private String lastname;

     @OneToOne
     @JoinColumn(name = "picture") //field named "picture" in the database
     private UserPicture userPicture;

     ..
}


public class UserPicture {

     @Id
     @GeneratedValue(strategy=GenerationType.AUTO)
     @Column(name="id", nullable = false, unique = true)
     private int id;

     private Blob image;

     @OneToOne
     @JoinColumn(name = "user")
     User user;

'user' in UserPicture will be loaded but 'userPicture' in User not - what did Im wrong?

EDIT Have to add that Im just create a UserPicture and insert them (with existing userId) - maybe I need to cascade 'user' in UserPicture?

like image 312
user1731299 Avatar asked Oct 24 '12 07:10

user1731299


People also ask

Is OneToOne bidirectional?

@OneToOne(mappedBy="user") //defines a bidirectional relationship.

What is Hibernate unidirectional and bidirectional?

A bidirectional relationship has both an owning side and an inverse side. A unidirectional relationship has only an owning side. The owning side of a relationship determines how the Persistence runtime makes updates to the relationship in the database.

What is difference between JPA unidirectional OneToOne and ManyToOne?

The main difference between a OneToOne and a ManyToOne relationship in JPA is that a ManyToOne always contains a foreign key from the source object's table to the target object's table, whereas a OneToOne relationship the foreign key may either be in the source object's table or the target object's table.

What is a bidirectional association?

Bi-directional associations (or symmetric associations ) are the simplest way that two classes can relate to each other. A bi-directional association is shown as a line between two classes, and can contain control points. The classes can be any mix of classes, simple classes, or composite classes.


2 Answers

In regards to your question: (because I don't have enough reputation to respond in a comment)

"All clear! Only one question more, is it possible to make userPicture in User lazy? – user1731299 Oct 24 '12 at 10:44"

Yes, it -is- possible to make it lazy fetch. However, just saying "fetchType=FetchType.Lazy" will not work. Reason being, Hibernate needs to check the joined table to see if it's a null value, or if there's a record there. Since it's a OneToOne mapping, Hibernate figures that it can save a database call by just pulling back any data that's there, since it had to check if it was null anyways. This isn't the case for x-to-many-mappings, since Hibernate knows that the 'many' means there's a list waiting on the other table... be it an empty or a populated list, it's still a list. For a single value, it has to differentiate between the actual data and a null value.

The way around this is to tell Hibernate that there will ALWAYS be a value there, and NEVER a null value. Knowing this, Hibernate can create a place-holder until it's time to fetch that data. The way you do this in annotations is to add "optional=false" to your @OneToOne annotation.

However be cautioned! There are some issues with this; including the one I'm trying to figure out now (and how I came to stumble across your question here). This optional=false makes Hibernate do a little extra validation and seems to confuse Hibernate on how it should execute inserts. So, you may want to stay away from this lazy fetching technique.

like image 70
AForsberg Avatar answered Oct 20 '22 10:10

AForsberg


You have to map your classes.

public class User {
    ...
    @OneToOne (mappedBy="user")
    private UserPicture userPicture;
    ...
}

public class UserPicture {
    ...
    @OneToOne
    @JoinColumn (name="user")
    private User user;
    ...
}
like image 42
Pigueiras Avatar answered Oct 20 '22 09:10

Pigueiras