延迟加载(使用FK一对一)问题 [英] Lazy loading (one to one using FK) issue

查看:120
本文介绍了延迟加载(使用FK一对一)问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

执行session.createQuery(来自Author)。list();
即使当关系被标记为optional = false时,相关联的书籍实例信息也会被热切地加载,从Author-> book中获取type = lazy会生成sql。
我只是为了理解目的而将这种关系作为一对一的关系,而不是一对一的关系。如果不知道我缺少什么,是否有可能让它懒惰?



Hibernate:选择author0_.AUTHOR_ID作为AUTHOR_I1_0_,author0_.email作为email2_0_ ,author0_.name作为name3_0_来自AUTHOR author0 _


$ b Hibernate:选择book0_.BOOK_ID作为BOOK_ID1_1_0_,book0_.AUTHOR_ID作为AUTHOR_I5_1_0_,book0_.description作为descript2_1_0_,book0_.PUBLISHED作为PUBLISHE3_1_0_ ,book0_.title as title4_1_0_ from book book0_ where book0_.AUTHOR_ID =?



Hibernate:选择book0_.BOOK_ID作为BOOK_ID1_1_0_,book0_.AUTHOR_ID作为AUTHOR_I5_1_0_,book0_.description作为descript2_1_0_ ,book0_.PUBLISHED as PUBLISHE3_1_0_,book0_.title as title4_1_0_ from book book0_ where book0_.AUTHOR_ID =?


$ b Hibernate:选择book0_.BOOK_ID作为BOOK_ID1_1_0_,book0_.AUTHOR_ID作为AUTHOR_I5_1_0_ ,book0_.description as descript2_1_0_,book0_.PUBLISHED as PUBLISHE3_1_0_,book0_.title as title4_1_0_ from BOOK book0_ where book0_.AUTHOR_ID =?



Hibe rnate:选择book0_.BOOK_ID作为BOOK_ID1_1_0_,book0_.AUTHOR_ID作为AUTHOR_I5_1_0_,book0_.description作为descript2_1_0_,book0_.PUBLISHED作为PUBLISHE3_1_0_,book0_.title作为title4_1_0_从BOOK book0_ where book0_.AUTHOR_ID =?



Hibernate:选择book0_.BOOK_ID作为BOOK_ID1_1_0_,book0_.AUTHOR_ID作为AUTHOR_I5_1_0_,book0_.description作为descript2_1_0_,book0_.PUBLISHED作为PUBLISHE3_1_0_,book0_.title作为title4_1_0_从BOOK book0_ where book0_.AUTHOR_ID =?



Hibernate:选择book0_.BOOK_ID作为BOOK_ID1_1_0_,book0_.AUTHOR_ID作为AUTHOR_I5_1_0_,book0_.description作为descript2_1_0_,book0_.PUBLISHED作为PUBLISHE3_1_0_,book0_.title作为title4_1_0_从BOOK book0_ where book0_。 AUTHOR_ID =?

  @Entity 
@BatchSize(size = 3)
@Table(name = AUTHOR)
公共类作者{
私人长ID;
私人字符串名称;
私人字符串电子邮件;
私人图书;

$ b public作者(){
}

作者(String name,String email){
this.name = name;
this.email =电子邮件;

$ b @Id
@Column(name =AUTHOR_ID)
@GeneratedValue
public long getId(){
return id ;
}

public void setId(long id){
this.id = id;
}

public String getName(){
return name;
}

public void setName(String name){
this.name = name;
}

public String getEmail(){
return email;
}

public void setEmail(String email){
this.email = email;

$ b $ @ @OneToOne(cascade = CascadeType.ALL,fetch = FetchType.LAZY,optional = false,mappedBy =author)
public Book getBook(){
归还书;
}

public void setBook(Book book){
this.book = book;


$ b @Entity
@BatchSize(size = 3)
@Table(name =BOOK)
public class Book {

私人长ID;
私有字符串标题;
私有字符串描述;
私人日期publishedDate;

私人作者作者;

public Book(){
}

@Id
@Column(name =BOOK_ID)
@GeneratedValue
public long getId(){
return id;
}

public void setId(long id){
this.id = id;
}

public String getTitle(){
return title;
}

public void setTitle(String title){
this.title = title;
}

public String getDescription(){
return description;
}

public void setDescription(String description){
this.description = description;
}

@Temporal(TemporalType.DATE)
@Column(name =PUBLISHED)
public Date getPublishedDate(){
return publishedDate;
}

public void setPublishedDate(Date publishedDate){
this.publishedDate = publishedDate;
}

@OneToOne(cascade = CascadeType.ALL,fetch = FetchType.LAZY,可选= false)
@JoinColumn(name =AUTHOR_ID,unique = true)
public作者getAuthor(){
返回作者;
}

public void setAuthor(Author author){
this.author = author;



$ div $解析方案

你缺少从 Author Book 的链接不是双向关联的定义所有者,我的意思是定义为mappedBy,FK驻留在 Book 表中。
所以当一个作者被检索到时,它需要通过Book表查询来检查FK,并确定是否有书和每个作者关联了哪本书。这就是为什么你在书桌上看到尽可能多的选择语句的原因(它被称为N + 1查询问题)。



避免它的一种方法是切换关联的所有者一方(在Author表中定义一个FK到书),但是你会看到类似的行为为书籍寻找。



如果您的担心是附属查询,则可以在查询强制中应用提取策略来检索与作者关联的图书。这个查询就像
session.createQuery(from Author a left join fetch a.book)。list();



我告诉过你原因和基本解决方案/解决方法,但也有更复杂的选项,你可以在stackoverflow中找到它。


when executing session.createQuery("from Author").list(); The associated book instance info is loaded eagerly even when relationship is marked optional=false,fetch type = lazy from Author->book as per below generated sql's. I have this relationship as one to one just for understanding purposes, and not one to many at the moment. Is it possible to make it lazy from Author-Book, if so not sure what I am missing?

Hibernate: select author0_.AUTHOR_ID as AUTHOR_I1_0_, author0_.email as email2_0_, author0_.name as name3_0_ from AUTHOR author0_

Hibernate: select book0_.BOOK_ID as BOOK_ID1_1_0_, book0_.AUTHOR_ID as AUTHOR_I5_1_0_, book0_.description as descript2_1_0_, book0_.PUBLISHED as PUBLISHE3_1_0_, book0_.title as title4_1_0_ from BOOK book0_ where book0_.AUTHOR_ID=?

Hibernate: select book0_.BOOK_ID as BOOK_ID1_1_0_, book0_.AUTHOR_ID as AUTHOR_I5_1_0_, book0_.description as descript2_1_0_, book0_.PUBLISHED as PUBLISHE3_1_0_, book0_.title as title4_1_0_ from BOOK book0_ where book0_.AUTHOR_ID=?

Hibernate: select book0_.BOOK_ID as BOOK_ID1_1_0_, book0_.AUTHOR_ID as AUTHOR_I5_1_0_, book0_.description as descript2_1_0_, book0_.PUBLISHED as PUBLISHE3_1_0_, book0_.title as title4_1_0_ from BOOK book0_ where book0_.AUTHOR_ID=?

Hibernate: select book0_.BOOK_ID as BOOK_ID1_1_0_, book0_.AUTHOR_ID as AUTHOR_I5_1_0_, book0_.description as descript2_1_0_, book0_.PUBLISHED as PUBLISHE3_1_0_, book0_.title as title4_1_0_ from BOOK book0_ where book0_.AUTHOR_ID=?

Hibernate: select book0_.BOOK_ID as BOOK_ID1_1_0_, book0_.AUTHOR_ID as AUTHOR_I5_1_0_, book0_.description as descript2_1_0_, book0_.PUBLISHED as PUBLISHE3_1_0_, book0_.title as title4_1_0_ from BOOK book0_ where book0_.AUTHOR_ID=?

Hibernate: select book0_.BOOK_ID as BOOK_ID1_1_0_, book0_.AUTHOR_ID as AUTHOR_I5_1_0_, book0_.description as descript2_1_0_, book0_.PUBLISHED as PUBLISHE3_1_0_, book0_.title as title4_1_0_ from BOOK book0_ where book0_.AUTHOR_ID=?

@Entity
@BatchSize(size=3)
@Table(name = "AUTHOR")
public class Author {
    private long id;
    private String name;
    private String email;
    private Book book;


    public Author() {
    }

    public Author(String name, String email) {
        this.name = name;
        this.email = email;
    }

    @Id
    @Column(name = "AUTHOR_ID")
    @GeneratedValue
    public long getId() {
        return id;
    }

    public void setId(long id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    @OneToOne(cascade=CascadeType.ALL,fetch=FetchType.LAZY,optional=false,mappedBy="author")
    public Book getBook() {
        return book;
    }

    public void setBook(Book book) {
        this.book = book;
    }


@Entity
@BatchSize(size=3)
@Table(name = "BOOK")
public class Book {

     private long id;
        private String title;
        private String description;
        private Date publishedDate;

        private Author author;

        public Book() {
        }

        @Id
        @Column(name = "BOOK_ID")
        @GeneratedValue
        public long getId() {
            return id;
        }

        public void setId(long id) {
            this.id = id;
        }

        public String getTitle() {
            return title;
        }

        public void setTitle(String title) {
            this.title = title;
        }

        public String getDescription() {
            return description;
        }

        public void setDescription(String description) {
            this.description = description;
        }

        @Temporal(TemporalType.DATE)
        @Column(name = "PUBLISHED")
        public Date getPublishedDate() {
            return publishedDate;
        }

        public void setPublishedDate(Date publishedDate) {
            this.publishedDate = publishedDate;
        }

        @OneToOne(cascade=CascadeType.ALL,fetch=FetchType.LAZY,optional=false)
        @JoinColumn(name ="AUTHOR_ID",unique=true)
        public Author getAuthor() {
            return author;
        }

        public void setAuthor(Author author) {
            this.author = author;
        }
    }

解决方案

You are missing that the link from Author to Book isn't the definition owner of the bidirectional association, I mean it is defined as mappedBy and the FK resides in the Book table. So when an Author is retrieved, it needs to query over the Book table to check the FK and find out if there is a book and which book is associated per Author. That is why you are seeing as many select statement on book table as Authors you have (it is known as the N+1 Query Problem).

One way to avoid it is switch the owner side of the association (defining in Author table a FK to the Book) but you will see analogous behavior quering for books.

If your concern are the collateral queries, one option is apply a fetching strategy in the query forcing to retrieve the Books associated with the Authors. The query will be something like, session.createQuery("from Author a left join fetch a.book").list();

I told you the cause and basic solution/workaround but there are more complicated options too, you could find those in stackoverflow for sure.

这篇关于延迟加载(使用FK一对一)问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆