2013-11-27 57 views
3

問題已解決。謝謝。

現在我有三個表movie_information,release_companyratingmovie_informationrating具有一對一的關係,而release_companymovie_information具有一對多的關係。 我想用hibernate構建一個CMS,但是我發現我無法正確構建涉及這三個表的部分。Hibernate:非空屬性引用空值或瞬態值

這裏說到我的代碼

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

StackTra CE

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中的記錄(我不確定是否保存記錄,如果拋出異常,我不知道)。此外,其中一些人表示映射標籤的屬性不正確,但我不確定我的是否正確。

我很抱歉把這麼多的代碼放在帖子中,希望你能解決這個問題。

+0

不能創建的getter/setter的新對象。問題當然存在。 – ben75

+0

你是對的,但是如果不創建一個新的對象,會不會在Set getter或setter中進行淺拷貝? 因此,我必須清除Set <>實例並將所有參數集中的值添加到setter中的Set <>實例中? –

+1

您能分享一下您如何解決問題嗎? – kmarabet

回答

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

你需要的是因爲:

  • 休眠需要追蹤到集合
  • 休眠把代理各地收集來做到這一點的跟蹤所做的更改。
  • 被另一個取代Set意味着休眠代理將失去
相關問題