How can I make a JPA OneToOne relation lazy

前端 未结 10 1725
暖寄归人
暖寄归人 2020-11-22 03:34

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

相关标签:
10条回答
  • 2020-11-22 04:25

    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.

    0 讨论(0)
  • 2020-11-22 04:28

    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.

    0 讨论(0)
  • 2020-11-22 04:36

    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.

    0 讨论(0)
  • 2020-11-22 04:37

    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

    • You can activate lazy loading bytecode enhancement
    • Or, you can just remove the parent side and use the client side with @MapsId as explained in the article above. This way, you will find that you don’t really need the parent side since the child shares the same id with the parent so you can easily fetch the child by knowing the parent id .
    0 讨论(0)
提交回复
热议问题