2015-07-12 2 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:

@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; 
    } 

А вот Url объект :

@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; 
    } 

А вот хэштегома лицо:

@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

Чтобы ответить на ваш вопрос: ваша модель определяет отношения один-ко-многим между чирикать и URL без каскадирования. Когда вы передаете экземпляр Twitter для сохранения, объекты URL еще не были сохранены, и ваша модель не предоставляет функции Tweet для каскадирования операции persist в экземплярах URL. Поэтому он не может создать отношения с ними. Каскадирование указывает на спящий режим, как выполнять операции БД на связанных объектах. Вы можете поручить ему передать/каскадировать операцию persist на связанный объект, чтобы каскадировать все операции или массив операций.

Это, как говорится, ваша проблема (1 из них) может быть исправлена, если изменить отношения с каскадом информации:

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

Но ваш пример показывает другие возможные проблемы, и я хотел бы призвать вас провел несколько больше время чтения документации Hibernate ORM и практика на образце модели с меньшими отношениями.

Одним из очевидных вопросов является отсутствие понимания концепция владельца отношения. Например, в ваших отношениях Tweet-to-Url URL-адрес владельца отношения (ответственный за управление отношениями, например, управление ссылкой через внешний ключ) Проконсультируйтесь с 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-адрес или хэштег. Я буду думать о коде. –

+0

Затем переключитесь на Integer или используйте несохраненное значение. –