2015-07-01 230 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之间的实际关联是一对多关系。