2012-02-10 4 views
3

Я пытаюсь изучить спящий режим. У меня есть таблица фильмов с внешним ключом в жанровой таблице. Каждому фильму присваивается один жанр. Каждому жанру может быть присвоено множество фильмов.Симулятор внешнего ключа 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; 
    } 

Затем выберите порождены спящим режимом выглядит

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

Что я вижу в том, что даже если у меня есть нетерпеливый load, и я явно говорю getGenre в toString, никакой запрос не генерируется, и я просто возвращаю null.

+0

Как вы получаете объект 'Movie'? Покажите нам код, который вы используете для этого. – skaffman

+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") 
+0

не являются OneToOne и ManyToOnes 'по умолчанию для EAGER? – SelimOber

+0

@SelimOber: Совершенно верно. Отредактировано соответственно. – skaffman

+0

Это тоже сработало! И я опубликовал хорошие версии файлов по адресу http://clippy.tk/index.php?show=1036. –

0

попробовать это:

Moive сторона:

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

и с другой стороны (жанр):

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

тогда вы можете из фильма объект movie.getGenre() получить жанр.

+0

картирование на жанровой стороне не обязательно. но я бы также рекомендовал попробовать его с аннотацией joinColumn – steffinchen

+0

Это сработало! Я опубликовал все файлы по адресу http://clippy.tk/index.php?show=1035 в надежде, что он может помочь кому-то другому. –

Смежные вопросы