How can I make a JPA OneToOne relation lazy

前端 未结 10 1730
暖寄归人
暖寄归人 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:21

    Here's something that has been working for me (without instrumentation):

    Instead of using @OneToOne on both sides, I use @OneToMany in the inverse part of the relationship (the one with mappedBy). That makes the property a collection (List in the example below), but I translate it into an item in the getter, making it transparent to the clients.

    This setup works lazily, that is, the selects are only made when getPrevious() or getNext() are called - and only one select for each call.

    The table structure:

    CREATE TABLE `TB_ISSUE` (
        `ID`            INT(9) NOT NULL AUTO_INCREMENT,
        `NAME`          VARCHAR(255) NULL,
        `PREVIOUS`      DECIMAL(9,2) NULL
        CONSTRAINT `PK_ISSUE` PRIMARY KEY (`ID`)
    );
    ALTER TABLE `TB_ISSUE` ADD CONSTRAINT `FK_ISSUE_ISSUE_PREVIOUS`
                     FOREIGN KEY (`PREVIOUS`) REFERENCES `TB_ISSUE` (`ID`);
    

    The class:

    @Entity
    @Table(name = "TB_ISSUE") 
    public class Issue {
    
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)
        protected Integer id;
    
        @Column
        private String name;
    
        @OneToOne(fetch=FetchType.LAZY)  // one to one, as expected
        @JoinColumn(name="previous")
        private Issue previous;
    
        // use @OneToMany instead of @OneToOne to "fake" the lazy loading
        @OneToMany(mappedBy="previous", fetch=FetchType.LAZY)
        // notice the type isnt Issue, but a collection (that will have 0 or 1 items)
        private List next;
    
        public Integer getId() { return id; }
        public String getName() { return name; }
    
        public Issue getPrevious() { return previous; }
        // in the getter, transform the collection into an Issue for the clients
        public Issue getNext() { return next.isEmpty() ? null : next.get(0); }
    
    }
    

提交回复
热议问题