2015-07-12 33 views
2

對於下面的批處理插入方法,我得到這個異常「分離的實體傳遞給持久化」。你可以看看這個方法並給我一些提示嗎?分離的實體傳遞給JPA中的批量插入持久

非常感謝。

如果需要的話,我會在這裏提供的實體,目前我提供關鍵字實體

public class Keyword implements Serializable { 


    private static final long serialVersionUID = -1429681347817644570L; 

    @Id 
    @GeneratedValue(strategy=GenerationType.IDENTITY) 
    @Column(name="key_id") 
    private long keyId; 

    @Column(name="key_name") 
    private String keyName; 

    @ManyToOne 
    @JoinColumn(name="tweet_id") 
    private Tweet tweet; 


    public long getKeyId() { 
     return keyId; 
    } 


    public void setKeyId(long keyId) { 
     this.keyId = keyId; 
    } 

    public String getKeyName() { 
     return keyName; 
    } 

    public void setKeyName(String keyName) { 
     this.keyName = keyName; 
    } 


    public Tweet getTweet() { 
     return tweet; 
    } 

    public void setTweet(Tweet tweet) { 
     this.tweet = tweet; 
    } 

} 

這裏分享Tweet實體:

@Entity 
@Table(name="tweets") 

public class Tweet implements Serializable{ 

    @Id 
    @Column(name="tweet_id") 
    private long tweetId; 

    @Column(name="tweet_text") 
    private String tweetText; 

    @Temporal(TemporalType.TIMESTAMP) 
    @Column(name = "created_at") 
    private Date createdAt; 

    @Column(name="lang_code") 
    private String languageCode; 

    @ManyToOne 
    @JoinColumn(name = "user_id") 
    private User user; 


    @OneToMany(mappedBy="tweet") 
    //@JoinColumn(name="hashtag_id") 
    private List<Hashtag> hashtags; 


    @OneToMany(mappedBy="tweet") 
    //@JoinColumn(name="url_id") 
    private List<Url> urls; 


    public List<Keyword> getKeywords() { 
     return keywords; 
    } 


    public void setKeywords(List<Keyword> keywords) { 
     this.keywords = keywords; 
    } 


    @OneToMany(mappedBy="tweet") 
    //@JoinColumn(name="url_id") 
    private List<Keyword> keywords; 




    public long getTweetId() { 
     return tweetId; 
    } 


    public void setTweetId(long tweetId) { 
     this.tweetId = tweetId; 
    } 


    public String getTweetText() { 
     return tweetText; 
    } 


    public void setTweetText(String tweetText) { 
     this.tweetText = tweetText; 
    } 


    public Date getCreatedAt() { 
     return createdAt; 
    } 


    public void setCreatedAt(Date createdAt) { 
     this.createdAt = createdAt; 
    } 


    public String getLanguageCode() { 
     return languageCode; 
    } 


    public void setLanguageCode(String languageCode) { 
     this.languageCode = languageCode; 
    } 


    public User getUser() { 
     return user; 
    } 


    public void setUser(User user) { 
     this.user = user; 
    } 


    public List<Hashtag> getHashtags() { 
     return hashtags; 
    } 


    public void setHashtags(List<Hashtag> hashtags) { 
     this.hashtags = hashtags; 
    } 


    public List<Url> getUrls() { 
     return urls; 
    } 


    public void setUrls(List<Url> urls) { 
     this.urls = urls; 
    } 


    @Override 
    public int hashCode() { 
     final int prime = 31; 
     int result = 1; 
     result = prime * result + (int) (tweetId^(tweetId >>> 32)); 
     return result; 
    } 


    @Override 
    public boolean equals(Object obj) { 
     if (this == obj) 
      return true; 
     if (obj == null) 
      return false; 
     if (getClass() != obj.getClass()) 
      return false; 
     Tweet other = (Tweet) obj; 
     if (tweetId != other.tweetId) 
      return false; 
     return true; 
    } 

這裏地址實體:

@Entity 
@Table(name="tweet_url") 
public class Url implements Serializable{ 


    @Id 
    @GeneratedValue(strategy=GenerationType.IDENTITY) 
    @Column(name="url_id") 
    private int urlId; 


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

    @ManyToOne 
    @JoinColumn(name="tweet_id",referencedColumnName="tweet_id") 
    private Tweet tweet; 

    public int getUrlId() { 
     return urlId; 
    } 

    public void setUrlId(int urlId) { 
     this.urlId = urlId; 
    } 

    public String getUrl() { 
     return url; 
    } 

    public void setUrl(String url) { 
     this.url = url; 
    } 

    public Tweet getTweet() { 
     return tweet; 
    } 

    public void setTweet(Tweet tweet) { 
     this.tweet = tweet; 
    } 

這裏是包括hashtag實體:

@Entity 
@Table(name="tweet_hashtag") 
public class Hashtag implements Serializable{ 


    @Id 
    @GeneratedValue(strategy=GenerationType.IDENTITY) 
    @Column(name="hashtag_id") 
    private int hashtagId; 


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

    @ManyToOne 
    @JoinColumn(name="tweet_id",referencedColumnName="tweet_id") 
    private Tweet tweet; 

    public int getHashtagId() { 
     return hashtagId; 
    } 

    public void setHashtagId(int hashtagId) { 
     this.hashtagId = hashtagId; 
    } 

    public String getHashtag() { 
     return hashtag; 
    } 

    public void setHashtag(String hashtag) { 
     this.hashtag = hashtag; 
    } 

    public Tweet getTweet() { 
     return tweet; 
    } 

    public void setTweet(Tweet tweet) { 
     this.tweet = tweet; 
    } 

而且方法

public void batchInsert(List<Keyword> results) throws HibernateException { 

    // chekeywordck if key exists 

    // try { 
    em=RunQuery.emf.createEntityManager(); 
    em.getTransaction().begin(); 

    for(Keyword result:results) 
    { 

     try{ 
     em.persist(result.getTweet().getUser()); 
     } 
     catch(ConstraintViolationException ce) 
     { 
      System.out.print("duplicated insert catched"); 

     } 

     try{ 
     em.persist(result.getTweet()); 
     } 
     catch(ConstraintViolationException ce) 
     { 
     System.out.print("duplicated insert catched"); 
     } 

     if(result.getTweet().getHashtags()!=null) 
      for(Hashtag hashtag:result.getTweet().getHashtags()) 
        em.persist(hashtag); 

     if(result.getTweet().getUrls()!=null) 
      for(Url url:result.getTweet().getUrls()) 
       em.persist(url); 

     em.persist(result); 

     em.flush(); 
     em.clear(); 

     //when I put these two line out of this loop, it still is the same. 
    } 
    em.getTransaction().commit(); 


     // } 


} 

這裏是例外:

Exception in thread "Thread-3" javax.persistence.PersistenceException: org.hibernate.PersistentObjectException: detached entity passed to persist: model.twitter.entities.Url 
    at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1763) 
    at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1677) 
    at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1683) 
    at org.hibernate.jpa.spi.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:1187) 
    at model.service.QueryResultService.batchInsert(QueryResultService.java:74) 
    at controller.ResultsController.save(ResultsController.java:125) 
    at controller.ResultsController.parse(ResultsController.java:89) 
    at main.TwitterStreamConsumer.run(TwitterStreamConsumer.java:41) 
    at java.lang.Thread.run(Thread.java:745) 
Caused by: org.hibernate.PersistentObjectException: detached entity passed to persist: model.twitter.entities.Url 
    at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:139) 
    at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:75) 
    at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:811) 
    at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:784) 
    at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:789) 
    at org.hibernate.jpa.spi.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:1181) 
    ... 5 more 
+0

問題出在Url類或Tweet.Urls映射中。你可以添加這些類嗎? – Augusto

+0

預先感謝您。我真的需要你的答案。增加了兩個其他的實體。 –

+0

你能指出哪裏是行號74 – Amogh

回答

1

要回答你的問題:你的模型定義了Tweet和U​​RL之間的一對多關係沒有任何級聯。當您傳遞一個Tweet實例進行持久化時,URL對象尚未保存,並且您的模型不會強制Tweet將持久操作級聯到URL實例。因此它不能與他們建立關係。 級聯告訴hibernate如何對相關實體執行數據庫操作。 您可以指示它將持久操作傳遞/級聯到相關實體,以級聯所有操作或一系列操作。

話雖這麼說,你的問題(其中1)可以是固定的,如果你修改與級聯信息的關係:

@OneToMany(mappedBy="tweet", cascade={CascadeType.PERSIST}) 
private List<Url> urls; 

但是你的樣品表明其他可能的問題,我會鼓勵你花了一些更實時閱讀Hibernate ORM文檔,並在關係較少的樣本模型上進行實踐。

其中一個明顯的問題似乎是關係所有者概念的理解不足。 例如,在您的Twitter訊息對網址的關係,網址是關係所有者(負責管理的關係,例如通過管理外鍵的鏈接) 請諮詢hibernate docs或數百個類似的問題here on SO更多的信息之一。 根據填充數據的方式,您可能會遇到約束問題,或者您的實體不會鏈接在一起,因爲您沒有保存擁有方。 同樣使用try/catch來限制違規是檢測重複條目的一種非常糟糕的方式。ConstraintViolationException可能有很多原因,你得到它們的原因與上面提到的關係映射問題有關。 ORM是一個複雜的主題,從更小的例子開始,試圖在轉向更具挑戰性的模型之前瞭解框架機制是非常有益的。好運

0

對於所有的堅持呼叫嘗試用這個代替:

if(result.getTweet().getUser().getId() == null) { 
    em.persist(result.getTweet().getUser()); 
} else { 
    result.getTweet().setUser(em.merge(result.getTweet().getUser())); 
} 

if(result.getTweet().getId() == null) { 
    em.persist(result.getTweet()); 
} else { 
    result.setTweet(em.merge(result.getTweet())); 
} 

if(result.getId() == null) { 
    em.persist(result); 
} else { 
    result = em.merge(result); 
} 
+0

非常感謝。 getId()== null這個方法的返回值是int,它怎麼能是null!? –

+0

getId == 0?有了這個條件(0而不是1),它不會插入任何url或hashtag。我會考慮代碼。 –

+0

然後切換到整數或使用未保存的值。 –

相關問題