2015-07-01 189 views
1

在書和作者之間的下面映射中,我使用book表中的外鍵列author_id完成了一對一映射,並且關聯從book-> author被標記爲可選false,但是當我查詢 session.createQuery(「from Book」).list();一對一外鍵映射

1)它急切地獲取信息的作者時,它被標記爲可選的是假的,爲什麼不代理它,有人可以解釋爲什麼像它在主鍵聯接列不與外鍵的方式工作?

Hibernate: select book0_.BOOK_ID as BOOK_ID1_1_, book0_.AUTHOR_ID as AUTHOR_I5_1_, book0_.description as descript2_1_, book0_.PUBLISHED as PUBLISHE3_1_, book0_.title as title4_1_ from BOOK book0_ 

Hibernate: select author0_.AUTHOR_ID as AUTHOR_I1_0_0_, author0_.email as email2_0_0_, author0_.name as name3_0_0_ from AUTHOR author0_ where author0_.AUTHOR_ID in (?, ?, ?) 

Hibernate: select author0_.AUTHOR_ID as AUTHOR_I1_0_0_, author0_.email as email2_0_0_, author0_.name as name3_0_0_ from AUTHOR author0_ where author0_.AUTHOR_ID in (?, ?, ?) 
@Entity 
@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,optional=false) 
     @JoinColumn(name = "AUTHOR_ID") 
     public Author getAuthor() { 
      return author; 
     } 

     public void setAuthor(Author author) { 
      this.author = author; 
     } 
    } 
@Entity 
@BatchSize(size=3) 
@Table(name = "AUTHOR") 
public class Author { 
    private long id; 
    private String name; 
    private String email; 


    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; 
    } 
} 

2)當我提出從作者 - >書這個雙向的,並且運行查詢 session.createQuery( 「來自作者」)。名單() ;

它首先根據期望從作者中提取記錄,然後使用2個連接運行如下所示的單個查詢。 爲什麼它必須做一個連接,而不是直接使用作者ID來查詢書籍表?

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_2_, book0_.AUTHOR_ID as AUTHOR_I5_1_2_, book0_.description as descript2_1_2_, book0_.PUBLISHED as PUBLISHE3_1_2_, book0_.title as title4_1_2_, author1_.AUTHOR_ID as AUTHOR_I1_0_0_, author1_.email as email2_0_0_, author1_.name as name3_0_0_, book2_.BOOK_ID as BOOK_ID1_1_1_, book2_.AUTHOR_ID as AUTHOR_I5_1_1_, book2_.description as descript2_1_1_, book2_.PUBLISHED as PUBLISHE3_1_1_, book2_.title as title4_1_1_ from BOOK book0_ inner join AUTHOR author1_ on book0_.AUTHOR_ID=author1_.AUTHOR_ID left outer join BOOK book2_ on author1_.AUTHOR_ID=book2_.AUTHOR_ID where book0_.AUTHOR_ID=? 

Hibernate: select book0_.BOOK_ID as BOOK_ID1_1_2_, book0_.AUTHOR_ID as AUTHOR_I5_1_2_, book0_.description as descript2_1_2_, book0_.PUBLISHED as PUBLISHE3_1_2_, book0_.title as title4_1_2_, author1_.AUTHOR_ID as AUTHOR_I1_0_0_, author1_.email as email2_0_0_, author1_.name as name3_0_0_, book2_.BOOK_ID as BOOK_ID1_1_1_, book2_.AUTHOR_ID as AUTHOR_I5_1_1_, book2_.description as descript2_1_1_, book2_.PUBLISHED as PUBLISHE3_1_1_, book2_.title as title4_1_1_ from BOOK book0_ inner join AUTHOR author1_ on book0_.AUTHOR_ID=author1_.AUTHOR_ID left outer join BOOK book2_ on author1_.AUTHOR_ID=book2_.AUTHOR_ID where book0_.AUTHOR_ID=? 

Hibernate: select book0_.BOOK_ID as BOOK_ID1_1_2_, book0_.AUTHOR_ID as AUTHOR_I5_1_2_, book0_.description as descript2_1_2_, book0_.PUBLISHED as PUBLISHE3_1_2_, book0_.title as title4_1_2_, author1_.AUTHOR_ID as AUTHOR_I1_0_0_, author1_.email as email2_0_0_, author1_.name as name3_0_0_, book2_.BOOK_ID as BOOK_ID1_1_1_, book2_.AUTHOR_ID as AUTHOR_I5_1_1_, book2_.description as descript2_1_1_, book2_.PUBLISHED as PUBLISHE3_1_1_, book2_.title as title4_1_1_ from BOOK book0_ inner join AUTHOR author1_ on book0_.AUTHOR_ID=author1_.AUTHOR_ID left outer join BOOK book2_ on author1_.AUTHOR_ID=book2_.AUTHOR_ID where book0_.AUTHOR_ID=? 

Hibernate: select book0_.BOOK_ID as BOOK_ID1_1_2_, book0_.AUTHOR_ID as AUTHOR_I5_1_2_, book0_.description as descript2_1_2_, book0_.PUBLISHED as PUBLISHE3_1_2_, book0_.title as title4_1_2_, author1_.AUTHOR_ID as AUTHOR_I1_0_0_, author1_.email as email2_0_0_, author1_.name as name3_0_0_, book2_.BOOK_ID as BOOK_ID1_1_1_, book2_.AUTHOR_ID as AUTHOR_I5_1_1_, book2_.description as descript2_1_1_, book2_.PUBLISHED as PUBLISHE3_1_1_, book2_.title as title4_1_1_ from BOOK book0_ inner join AUTHOR author1_ on book0_.AUTHOR_ID=author1_.AUTHOR_ID left outer join BOOK book2_ on author1_.AUTHOR_ID=book2_.AUTHOR_ID where book0_.AUTHOR_ID=? 

回答

0

1)ToOne關聯在JPA中默認爲渴望。爲了讓懶惰:

@OneToOne(cascade = CascadeType.ALL, optional = false, , fetch = FetchType.LAZY) 

不要緊,您是否使用@PrimaryKeyJoinColumn與否。 2)不錯,這是不必要的,Hibernate可以做得更好;請看這question。關鍵是Hibernate想要在急切提取關聯實體時避免附加查詢。

那麼,這裏發生了什麼?

首先,您可能沒有在Author一側聲明關聯爲強制關聯(即left outer join來自哪裏)。其次,Hibernate通過提供的作者id(對於第一個查詢返回的每個作者)讀取該書。你會得到相同的查詢,如果你手工做的:

select b from Book b where b.author.id = :authorId 

Hibernate使用第一連接表讀的書,第二個讀這本書的作者,而第三個閱讀作者的書。

第三個連接表在這裏是非常不必要的,我希望Hibernate在未來的版本中改進它。

如果您手動執行上述查詢(在同一個查詢中而不是新的查詢中讀取該書的作者),那麼第二個連接表是一個很好的優化,但在您的示例中是不必要的,因爲所需的作者已經加載。我希望這在未來的版本中也會得到改進。

PS AuthorBook之間的實際關聯是一對多關係。