Hibernate外键语法

时间:2012-02-10 13:25:15

标签: java hibernate

我正在尝试学习hibernate。我有一个带有流派表的外键的电影表。每部电影都分配到一个类型。每种类型都可以分配给许多电影。

以下是表格定义:

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看起来像

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;
对于我做错了什么,我有点失落。多对一注释应该是Genre类而不是Movie类吗?或者你看到其他任何我做错了吗?

根据以下建议,电影现在有

@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,也没有生成任何查询,我只是得到了一个空值。

2 个答案:

答案 0 :(得分:0)

当您使用HQL语法(例如createQuery("from Movie"))时,Hibernate / JPA只会在您Genre对象上调用getGenre()时获取Movie实体。这被称为“懒人取物”。调用该方法时,Hibernate将发出另一个查询来获取Genre

请注意,HQL查询会忽略注释上的FetchType - HQL用于告诉Hibernate 完全要做什么,而不是使用注释中的提示。

要在与Genre相同的查询中获取Movie,您需要告诉它:

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

答案 1 :(得分:0)

试试这个:

Moive方面:

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

另一方面(类型):

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

然后你可以从电影对象movie.getGenre()获取流派。