【问题标题】:Hibernate one-to-many mapping (annotations)Hibernate 一对多映射(注解)
【发布时间】:2014-06-02 18:21:34
【问题描述】:

我是 hibernate 的新手,我正在尝试学习它,但在尝试使一对多关系正常工作时遇到了问题。我尝试了几个示例,但似乎没有一个有效。

谁能看看下面的代码,告诉我哪里出错了。我尝试了许多不同的教程,但总是不起作用,所以我一定是遗漏了一些东西。

有两个类:MovieDb 和 Genre。每部电影应该有很多类型。

我相信我已经包含了所有需要的文件和信息,如果没有,请告诉我。

感谢您的帮助。

MovieDb.java

@Entity
@Table(name = "movies")
public class MovieDb extends IdElement {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private int id;

    @JsonProperty("id")
    @Column(name = "movieId")
    private int movieId;

    @JsonProperty("title")
    @Column(name = "title")
    private String title;

    @JsonProperty("genres")
    @OneToMany
    private List<Genre> genres;

    public int getMovieId() { return movieId; }
    public String getTitle() { return title; }
    public List<Genre> getGenres() { return genres; }

    public void setMovieId(int movieId) { this.movieId = movieId; }
    public void setTitle(String title) { this.title = title; }
    public void setGenres(List<Genre> genres) { this.genres = genres; }
}

Genre.java

@JsonRootName("genre")
@Entity
@Table(name = "moviesGenre")
public class Genre implements Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name="id")
    private int id;

    @Column(name = "movieId")
    private int movieId;

    @JsonProperty("name")
    @Column(name = "name")
    private String name;

    public int getMovieId() { return movieId; }
    public String getName() { return name; }

    public void setMovieId(int movieId) { this.movieId = movieId; }
    public void setName(String name) { this.name = name; }
}

Main.java

public MovieDb getMovie(int movieId) {
    Session s = HibernateUtil.getSessionFactory().openSession();
    Transaction tx = s.beginTransaction();
    MovieDb movie = null;
    try {
        String hql = "FROM MovieDb E WHERE E.movieId = " + movieId;
        Query query = s.createQuery(hql);
        List movies = query.list();
        movie = (MovieDb)movies.get(0); 
        tx.commit();
    }catch (HibernateException ex) {
        if (tx != null) 
            tx.rollback();
    }finally {
        s.close(); 
    }
    return movie;
}

public void saveMovie(MovieDb movie) {
    Session s = HibernateUtil.getSessionFactory().openSession();
    Transaction tx = s.beginTransaction();
    try {
        s.save(movie);
        s.flush();
        tx.commit();
    } catch (HibernateException ex) {
        if (tx != null) 
            tx.rollback();
    } finally {
        s.close(); 
    }
}

我的数据库是这样设置的:

电影

id          int           (primary)
movieId     int
title       varchar

电影类型

id          int           (primary)
movieId     int 
name        varchar

我的 Hibernate.cfg.xml 文件显示映射如下:

Hibernate.cfg.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
  <session-factory>
    ...
    ...
    ...
    <mapping class="com.medialibrary.api.model.MovieDb"/>
    <mapping class="com.medialibrary.api.model.Genre"/>
  </session-factory>
</hibernate-configuration>

【问题讨论】:

    标签: java mysql hibernate annotations one-to-many


    【解决方案1】:

    在 MovieDb 类方面

    @OneToMany(mappedBy="movie", cascade = CascadeType.ALL)
    private List<Genre> genres;
    

    和类型

    @ManyToOne
    @JoinColumn(name="movieId")
        private MovieDb movie;
    

    代码中的错误:

    当您保存父实体时,只要您不使用 CascadeType.PERSIST 或 CascadeType.ALL(对于所有操作类型),它们的子实体就不会持久化

    您正在尝试建立双向关系,因此您必须指定所有者 mappedBy="movie" 将完成这项工作 - 它表示将在 Genre 端写入 moveId

    【讨论】:

    • 感谢您的回复。当我使用上面的代码时,出现以下错误: Initial SessionFactory creation failed.org.hibernate.MappingException: Repeated column in mapping for entity: com.medialibrary.api.model.Genre column: movieId (应该用 insert=" 映射假”更新=“假”)
    • 你删除了这个字段@Column(name = "movieId") private int movieId; ?如果不只是这样做,并且只是为了确保也删除它的 setter/getter。
    • 如果我删除上面的代码,虽然在数据库上,moviesGenre -> movieId 为空,但它可以工作。
    • 当您不将父对象设置为子对象时,您将获得该效果。现在记住 Genre 有一个对其父级的引用,这也必须设置所以 ..genre.setMovie(movie);换句话说,电影必须在其集合中包含流派,流派必须设置电影字段。
    • 最好的方法,我认为一种常见的方法是在 MovieDb addGenre(Genre Genre){this.genres.add(genre); 中创建另一个方法流派.setMovie(this)}
    猜你喜欢
    • 2012-03-22
    • 2015-08-20
    • 1970-01-01
    • 2016-09-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-08
    相关资源
    最近更新 更多