0

I'm having a big problem for which I can't find an answer.

I have a OneToOne bidirectional Lazy fetched relation between two entities, but when I query one of them, it eagerly fetch the other, even though I'm explicitly saying that it's Lazy.

According to what I've found, almost all from 2010 and back, says that that is the way hibernate behaves on OneToOne relations. This is my first time using Hibernate ever but I highly doubt that is true, and if it was that it still is true. But i can't find any recent information about it. Post1, Post2, Post3 as you can see, they are not really recent. So I wanted to know if that's still the case or maybe guide me to where I can find the answer, examples, anything would help really.

Here's what I'm doing, just in case I'm doing something wrong. Note the classes has fewer attributes than the original, but all of them are columns of the entity, no FK, PK, or something like that.

User Entity

@Entity
@Table(name = "\"User\"")
public class User {

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

    @Column(name = "Username", nullable = false, unique = true, length = 100)
    private String username;

    @Valid
    @OneToOne(fetch = FetchType.LAZY, mappedBy = "user", cascade = CascadeType.ALL)
    @JsonBackReference
    private UserProfile userProfile;
    //Getters and Setters
}

UserProfile Entity

@Entity
@Table(name = "UserProfile")
public class UserProfile {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;

    @NotBlank
    @Size(max = 100)
    @Column(name = "FirstName", nullable = false, unique = false, length = 100)
    private String firstName;

    @NotBlank
    @Size(max = 100)
    @Column(name = "LastName", nullable = false, unique = false, length = 100)
    private String lastName;

    @Valid
    @OneToOne(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    @JoinColumn(name = "UserId")
    @JsonManagedReference
    private User user;

    //Getters and Setters
}

Test controller method

@RequestMapping(value = "/test", method = RequestMethod.GET)
public ResponseEntity<Void> test(){
    User user = userService.findUserByUsername("admin");
    if(user.getUserProfile() == null){
        return new ResponseEntity<Void>(HttpStatus.OK); 
    }
    return new ResponseEntity<Void>(HttpStatus.CONFLICT);
}

And the UserService simply calls the UserDao method, which is

@Override
public User findByUsername(String username) {
    Criteria criteria = createEntityCriteria();
    criteria.add(Restrictions.eq("username", username));
    return (User) criteria.uniqueResult();
}

The result of that service is always Conflict. Even though I'm calling the UserService (Which is Transactional) and the direct relation is in UserProfile. The controller is not transactional.

The log:

2016-02-29 18:50:58 DEBUG SQL::logStatement:92 - 
    select
        this_.Id as Id1_2_0_,
        this_.Username as Username5_2_0_ 
    from
        Public.[User] this_ 
    where
        this_.Username=?
Hibernate: 
    select
        this_.Id as Id1_2_0_,
        this_.Username as Username5_2_0_ 
    from
        Public.[User] this_ 
    where
        this_.Username=?
2016-02-29 18:50:58 DEBUG Loader::debugf:384 - Result set row: 0
2016-02-29 18:50:58 DEBUG Loader::getRow:1514 - Result row: EntityKey[com.portal.model.user.User#1]
2016-02-29 18:50:58 DEBUG TwoPhaseLoad::doInitializeEntity:144 - Resolving associations for [com.portal.model.user.User#1]
2016-02-29 18:50:58 DEBUG Loader::loadEntity:2186 - Loading entity: [com.portal.model.user.UserProfile#1]
2016-02-29 18:50:58 DEBUG SQL::logStatement:92 - 
    select
        userprofil0_.id as id1_18_0_,
        userprofil0_.FirstName as FirstNam5_18_0_,
        userprofil0_.LastName as LastName7_18_0_,
        userprofil0_.UserId as UserId10_18_0_ 
    from
        Public.UserProfile userprofil0_ 
    where
        userprofil0_.UserId=?
Hibernate: 
    select
        userprofil0_.id as id1_18_0_,
        userprofil0_.FirstName as FirstNam5_18_0_,
        userprofil0_.LastName as LastName7_18_0_,
        userprofil0_.UserId as UserId10_18_0_
    from
        Public.UserProfile userprofil0_ 
    where
        userprofil0_.UserId=?

Is there something wrong? Am I doing something wrong?

Thanks for any help you can provide! Let me know if you need more info!

Community
  • 1
  • 1
  • can you add `nullable=false` to `onetoone` annotation and try. – Madhusudana Reddy Sunnapu Mar 01 '16 at 02:31
  • Correction: I believe it is `optional = false` and not nullable attribute. – Madhusudana Reddy Sunnapu Mar 01 '16 at 02:45
  • Hi Madhusudana, thank you for you input. I already tried that, but just in case i tried it again. Using optional=false on the user OneToOne, on the userProfile and in both. Still fetching all. Thanks you again! – SoManyDoubtsSoLittleTime Mar 01 '16 at 03:50
  • There is a bug in hibernate. There are cases where you would get LazyInitializationException for a not found child entity. Try upgrading your hibernate version along with JPA. Moreover the LAZY was intended for collections, in this case you can just set FETCH join on the Criteria, so that you ignore the entity altogether. – Narayana Nagireddi Mar 01 '16 at 04:12
  • Hi Narayana! I'm using version 5.0.7 Final of hibernate. About the FETCH join i would have to investigate a little bit more because honestly I don't know what that is. I'll look for it tomorrow morning and update you if it worked! Thank you very much for the help!! really appreciate it! – SoManyDoubtsSoLittleTime Mar 01 '16 at 04:18
  • Hi! I tried that and nothing! On the criteria i set the FecthMode to Join and still getting user and userprofile together. Thanks for your answer anyway! – SoManyDoubtsSoLittleTime Mar 02 '16 at 01:18

0 Answers0