2015-07-12 93 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

然后切换到整数或使用未保存的值。 –

相关问题