Hibernate:not-null属性引用null或transient值

时间:2013-11-27 19:06:20

标签: java hibernate hibernate-mapping

解决了问题。谢谢。

现在我有三个表movie_informationrelease_companyratingmovie_informationrating具有一对一关系,release_companymovie_information具有一对多关系。 我正在尝试使用hibernate构建CMS,但我发现我无法正确构建涉及这三个表的部分。

这是我的代码

MovieInformation.java

public class MovieInformation {
    private ReleaseCompany releaseCompany;
    private Rating rating;
    // Other data member
    // Constructor, getter and setter
    public ReleaseCompany getReleaseCompany(){
        ReleaseCompany newReleaseCompany = new ReleaseCompany(this.releaseCompany);
        return newReleaseCompany;
    }
    public Rating getRating(){
        Rating newRating = new Rating(this.rating);
        return newRating;
    }
    public void setReleaseCompany(ReleaseCompany releaseCompany){
        this.releaseCompany = new ReleaseCompany(releaseCompany);
    }
}

ReleaseCompany.java

public class ReleaseCompany {
    private int releaseCompanyId;
    private String releaseCompanyName;

    private Set<MovieInformation> movies = new HashSet<MovieInformation>();

    public ReleaseCompany(){
    }
    public ReleaseCompany(String releaseCompanyName){
        this.releaseCompanyName = releaseCompanyName;
    }
    public ReleaseCompany(ReleaseCompany releaseCompany){
        this.releaseCompanyName = releaseCompany.getReleaseCompanyName();
    }
    public Set<MovieInformation> getMovies() {  
        Set<MovieInformation> newMoviesSet = new HashSet<MovieInformation>(movies);
        return newMoviesSet;  
    }  
    public void setMovies(Set<MovieInformation> movies) {  
        this.movies = new HashSet<MovieInformation>(movies);
    }  
    // Other constructor, getter and setter
}

Rating.java

public class Rating {
    private MovieInformation movie;
    // other data member

    public void setMovie(MovieInformation movie){
        this.movie = new MovieInformation(movie);
    }
    // other constructor, getter and setter
}

MovieInformation.hbm.xml

<class name="cart.hibernate.movieInformation.MovieInformation" table="movie_information">
    <id column="move_id" name="movieId" type="long">
        <generator class="native"/>
    </id>

    <one-to-one name="rating" class="cart.hibernate.rating.Rating" cascade="save-update"></one-to-one> 

    <many-to-one name="releaseCompany" class="cart.hibernate.releaseCompany.ReleaseCompany"  unique="false"><!-- constrained="true" -->
        <column name="release_company_id" not-null="true" />
    </many-to-one>
    // Other property
</class>

Rating.hbm.xml

<class name="cart.hibernate.rating.Rating" table="rating">
  <id name="movieId" type="java.lang.Long">
      <column name="movie_id" />
      <generator class="foreign">
          <param name="property">movie</param>
      </generator>
  </id>

  <property column="avg_rate" name="avgRate" type="double"/>
  <property column="num_of_rate" name="numOfRate" type="long"/>

  <one-to-one name="movie" class="cart.hibernate.movieInformation.MovieInformation" constrained="true"></one-to-one>
</class>

ReleaseCompany.hbm.xml

<class name="cart.hibernate.releaseCompany.ReleaseCompany" table="release_company">
    <id column="release_company_id" name="releaseCompanyId" type="int">
        <generator class="native"/>
    </id>
    <property column="release_company_name" name="releaseCompanyName" type="string"/>

    <set name="movies" table="movie_information" inverse="true" lazy="true" fetch="select">
        <key>
            <column name="movie_id" not-null="true" />
        </key>
        <one-to-many class="cart.hibernate.movieInformation.MovieInformation" />
    </set>
</class>

测试主要方法

Session session = HibernateUtil.getSessionFactory().openSession();
Transaction tx = null;
tx = session.beginTransaction();

Rating rating = new Rating(5.6, 80);
ReleaseCompany releaseCompany = new ReleaseCompany();
releaseCompany.setReleaseCompanyName("a");
session.save(releaseCompany);        

//  ReleaseCompany releaseCompany = (ReleaseCompany)session.get(ReleaseCompany.class, 15); 
//  Another testing case that I have tried. It throw another exception,
//  if you need the information in this part, please let me know.

MovieInformation movie = new MovieInformation("Matrix", 150, 1, 50, date, releaseDate, "good description");
movie.setRating(rating);
movie.setReleaseCompany(releaseCompany);

rating.setMovie(movie);

session.save(movie);  // <--- Error occur here
tx.commit();

栈跟踪

org.hibernate.PropertyValueException: not-null property references a null or transient value: cart.hibernate.movieInformation.MovieInformation.releaseCompany
    at org.hibernate.engine.Nullability.checkNullability(Nullability.java:100)
    at org.hibernate.event.def.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:312)
    at org.hibernate.event.def.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:203)
    at org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:129)
    at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:210)
    at org.hibernate.event.def.DefaultSaveEventListener.saveWithGeneratedOrRequestedId(DefaultSaveEventListener.java:56)
    at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:195)
    at org.hibernate.event.def.DefaultSaveEventListener.performSaveOrUpdate(DefaultSaveEventListener.java:50)
    at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:93)
    at org.hibernate.impl.SessionImpl.fireSave(SessionImpl.java:713)
    at org.hibernate.impl.SessionImpl.save(SessionImpl.java:701)
    at org.hibernate.impl.SessionImpl.save(SessionImpl.java:697)
    at cart.hibernate.movieInformation.ManageMovieInformation.main(ManageMovieInformation.java:61)
BUILD SUCCESSFUL (total time: 1 second)

我已经阅读了几个类似的问题,有些人说releaseCompany(在我的情况下)对象没有保存到数据库中,因此setReleaseCompany()无法按预期工作。我不确定releaseCompany对象是否存在,因为我无法在MySql中看到记录(如果抛出异常,我不确定记录是否会被保存)。此外,他们中的一些人说地图标签的属性不正确,但我不确定我的是否正确。

我很抱歉在帖子中放了这么多代码,希望你能解决这个问题。

1 个答案:

答案 0 :(得分:3)

保持简单:

public class MovieInformation {
    private ReleaseCompany releaseCompany;
    private Rating rating;
    // Other data member
    // Constructor, getter and setter
    public ReleaseCompany getReleaseCompany(){
        return releaseCompany;
    }
    public Rating getRating(){
        return rating;
    }
    public void setReleaseCompany(ReleaseCompany releaseCompany){
        this.releaseCompany = releaseCompany;
    }
}

public class ReleaseCompany {
    private int releaseCompanyId;
    private String releaseCompanyName;

    private Set<MovieInformation> movies = new HashSet<MovieInformation>();

    public ReleaseCompany(){
    }
    public ReleaseCompany(String releaseCompanyName){
        this.releaseCompanyName = releaseCompanyName;
    }

    public ReleaseCompany(ReleaseCompany releaseCompany){
        this.releaseCompanyName = releaseCompany.getReleaseCompanyName();
    }
    public Set<MovieInformation> getMovies() {  
        return movies;  
    }  
    private void setMovies(Set<MovieInformation> movies) {  
        this.movies = movies;
    }  
    // Other constructor, getter and setter
}

public class Rating {
    private MovieInformation movie;
    // other data member

    public void setMovie(MovieInformation movie){
        this.movie = movie;
    }
    // other constructor, getter and setter
}

请注意,setMovies(Set movies)是私密的,因此更改所有电影的唯一方法是执行以下操作:

releaseCompany.getMovies().clear();
releaseCompany.getMovies().addAll(newMovieCollection);

你需要这样做因为:

  • hibernate需要跟踪对集合所做的更改
  • hibernate在集合周围放置代理来执行此跟踪。
  • 用另一个替换Set意味着hibernate代理将丢失