Hibernate - bidirectional @OneToOne

本秂侑毒 提交于 2019-12-17 19:39:21

问题


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?


回答1:


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



回答2:


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.




回答3:


Lazy loading in One to One works even when we specify the field as non nullable in the JoinColumn annotation. However in a bidirectional One to One the lazy loading doesn't work on the entity where we use mappedBy=''. For eg if we have two entities Contract and House, where Contract table holds a foreign key to House. When we use bidirectional OneToOne here and try to load contract then lazy loading works(i.e. House is not loaded eagerly) but when we try to load House (using House repository) then the Contract is always fetched eagerly. Does anybody have an idea why this happens?

Public class Contract {
  .....
  @onetoone(lazy)
  @JoinColumn(name='houseid', nullable=false)
  Private House house
  .....
}

Public class House {
  .....
  @onetoone(lazy, mappedBy='house')
  Private Contract contract
  .....
}

I know this is only a partial answer, cum question. But it is very much related to the discussion here.



来源:https://stackoverflow.com/questions/13044567/hibernate-bidirectional-onetoone

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!