In this application we are developing, we noticed that a view was particularly slow. I profiled the view and noticed that there was one query executed by hibernate which too
In native Hibernate XML mappings, you can accomplish this by declaring a one-to-one mapping with the constrained attribute set to true. I am not sure what the Hibernate/JPA annotation equivalent of that is, and a quick search of the doc provided no answer, but hopefully that gives you a lead to go on.
As I explained in this article, unless you are using Bytecode Enhancement, you cannot fetch lazily the parent-side @OneToOne
association.
However, most often, you don't even need the parent-side association if you use @MapsId
on the client side:
@Entity(name = "PostDetails")
@Table(name = "post_details")
public class PostDetails {
@Id
private Long id;
@Column(name = "created_on")
private Date createdOn;
@Column(name = "created_by")
private String createdBy;
@OneToOne(fetch = FetchType.LAZY)
@MapsId
private Post post;
public PostDetails() {}
public PostDetails(String createdBy) {
createdOn = new Date();
this.createdBy = createdBy;
}
//Getters and setters omitted for brevity
}
With @MapsId
, the id
property in the child table serves as both Primary Key and Foreign Key to the parent table Primary Key.
So, if you have a reference to the parent Post
entity, you can easily fetch the child entity using the parent entity identifier:
PostDetails details = entityManager.find(
PostDetails.class,
post.getId()
);
This way, you won't have N+1 query issues that could be caused by the mappedBy
@OneToOne
association on the parent side.
As already perfectly explained by ChssPly76, Hibernate's proxies don't help with unconstrained (nullable) one-to-one associations, BUT there is a trick explained here to avoid to set up instrumentation. The idea is to fool Hibernate that the entity class which we want to use has been already instrumented: you instrument it manually in the source code. It's easy! I've implemented it with CGLib as bytecode provider and it works (ensure that you configure lazy="no-proxy" and fetch="select", not "join", in your HBM).
I think this is a good alternative to real (I mean automatic) instrumentation when you have just one one-to-one nullable relation that you want to make lazy. The main drawback is that the solution depends on the bytecode provider you are using, so comment your class accurately because you could have to change the bytecode provider in the future; of course, you are also modifying your model bean for a technical reason and this is not fine.
This question is quite old, but with Hibernate 5.1.10, there are some new better comfortable solution.
Lazy loading works except for the parent side of a @OneToOne association. This is because Hibernate has no other way of knowing whether to assign a null or a Proxy to this variable. More details you can find in this article