2012-02-10 177 views
3

我想學習休眠。我有一個電影表和一個流派表的外鍵。每部電影都被分配到一個流派。每種類型都可以分配給許多電影。休眠外鍵語法

下面是表定義:

CREATE TABLE `movie` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `title` varchar(64) NOT NULL, 
    `genre_id` int(11) NOT NULL, 
    PRIMARY KEY (`id`), 
    KEY `fk_genre` (`genre_id`), 
    CONSTRAINT `fk_genre` FOREIGN KEY (`genre_id`) REFERENCES `genre` (`id`) ON UPDATE CASCADE, 

) 

CREATE TABLE IF NOT EXISTS `genre` (
    `id` int(11) NOT NULL AUTO_INCREMENT, 
    `name` varchar(32) DEFAULT NULL, 
    PRIMARY KEY (`id`) 
) 

對於代碼,我有

@Entity 
public class Movie implements java.io.Serializable { 

    private static final long serialVersionUID = 1; 
    private Integer id; 
    private String title; 
    private Genre genre; 
    ... 

    @ManyToOne 
    public Genre getGenre() { 
     return genre; 
    } 

而且

@Entity 
public class Genre implements java.io.Serializable { 

    private static final long serialVersionUID = 1; 
    private Integer id; 
    private String name; 

    @Id 
    @GeneratedValue 
    @Column(name = "id") 
    public Integer getId() { 
     return this.id; 
    } 

然後選擇由Hibernate生成看起來像

select 
    movie0_.id as column1_4_, 
    movie0_.genre_id as genre11_4_, 
    movie0_.title as title4_ 
from 
    Movie movie0_ 

這不正確,因爲沒有對流派表的引用。正確的查詢應該與流派表連接。更多類似

select 
    movie0_.id as column1_4_, 
    genre.name as genre11_4_, 
    movie0_.title as title4_ 
from 
    Movie movie0_, Genre genre 
where 
    movie0_.genre_id = genre.id; 

我無所適從,我做錯了一點點。多對一的註釋應該在流派類中而不是電影類中嗎?或者你看到我做錯了什麼?

基於下面的提醒,電影現在有

@Override 
public String toString() { 
    StringBuilder sb = new StringBuilder(); 
    sb.append(id).append(" "); 
    sb.append(title).append(" "); 

    this.getGenre(); //new 

    sb.append(genre.getName()); 
    return sb.toString(); 
} 

@ManyToOne(fetch=FetchType.EAGER) //new 
public Genre getGenre() { 
    return genre; 
} 

而且我加載電影的方式是通過

public static void main(String[] args) { 
    SessionFactory sf = HibernateUtil.getSessionFactory(); 
    Session session = sf.openSession(); 
    List<Movie> movies = session.createQuery("from Movie").list(); 
    for (Movie movie : movies) { 
     System.out.println(movie.toString()); 
    } 
    session.close(); 
} 

我所看到的是,即使我有渴望負載,我明確地說toString中的getGenre,沒有生成查詢,我只是得到一個空回來。

+0

你如何獲取'Movie'對象?向我們展示您正在使用的代碼。 – skaffman 2012-02-10 14:11:44

+0

我編輯了上述說明以迴應您的建議,skaffman。 – 2012-02-10 14:22:34

回答

0

當您使用HQL語法(例如createQuery("from Movie")),則Hibernate/JPA將只有當您在Movie對象調用getGenre()獲取Genre實體。這被稱爲「懶取」。當該方法被調用時,Hibernate將發出另一個查詢來獲取Genre

請注意,HQL查詢會忽略註釋上的FetchType - HQL用於告訴Hibernate 完全是該做什麼,而不是在註釋中使用提示。

,使其在同一查詢作爲MovieGenre,你需要告訴它:

createQuery("from Movie m join fetch m.genre") 
+0

是不是OneToOne和ManyToOnes'默認爲EAGER? – SelimOber 2012-02-10 14:09:24

+0

@SelimOber:很對。據此編輯。 – skaffman 2012-02-10 14:30:29

+0

這也工作!我已經在http://clippy.tk/index.php?show=1036發佈了這些文件的優秀版本。 – 2012-02-10 15:03:44

0

試試這個:

影視方面:

@ManyToOne 
@JoinColumn(name = "genre_id") 
public Genre getGenre() {..} 

和另一面(流派):

@OneToMany(mappedBy="genre") 
List/Set getMovies(){..} 

然後你可以從一個電影對象movie.getGenre()獲得流派。

+0

在流派方面的映射不應該是必要的。但我也建議嘗試使用joinColumn註釋 – steffinchen 2012-02-10 14:35:05

+0

這工作!我已經在http://clippy.tk/index.php?show=1035發佈了所有文件,希望它可以幫助別人。 – 2012-02-10 14:55:35