【问题标题】:Spring Data JPA JpaObjectRetrievalFailureException occurring after deleting ManyToOne record删除 ManyToOne 记录后发生 Spring Data JPA JpaObjectRetrievalFailureException
【发布时间】:2012-12-20 15:41:58
【问题描述】:

我遇到一个问题,当我在 ManyToOne 关系的多方删除一条记录时,它可以工作,但在下一个数据库事务中,我收到一个异常,说找不到我刚刚删除的实体(例如,当尝试添加另一个链接说它找不到我刚刚删除的那个)。我在数据库中验证了记录正在被删除。

我在 Hibernate 中使用 Spring MVC 和 Spring Data JPA。我有一个用户类和一个 NewsLink 类。一个用户可以有许多新闻链接,我想删除其中一个新闻链接。我只是通过构建一个简单的应用程序来学习如何自己使用 Spring 框架。所以这对我来说很新。感谢您的帮助!

用户实体类

@Entity
@Table(name = "users")
public class User implements Serializable{

@Id 
@Column(name = "idusers")
@GeneratedValue(strategy = GenerationType.AUTO)     
private Long id;

....    

@OneToMany(mappedBy="user", fetch= FetchType.EAGER, cascade=CascadeType.ALL, orphanRemoval= true)
private Set<NewsLink> newsLink;

NewsLink 实体类

@Entity
@Table(name = "news_links")
public class NewsLink implements Serializable{

@Id
@Column
@GeneratedValue(strategy = GenerationType.AUTO) 
private Long id;

@Column(insertable=false, updatable=false)
private Long idusers;   
....

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

这是执行删除的服务类中的方法。我认为这是我做得不对的部分:

@Override
@Transactional
public User deleteNewsLink(int id, User user){

    Iterator<NewsLink> links = user.getNewsLink().iterator();

    while(links.hasNext()){
        NewsLink link = links.next();

        if (link.getId() == id){
            links.remove();
        }

    }

    userRepository.save(user);

    return user;
}

这是我看到的异常:

Request processing failed; nested exception is  org.springframework.orm.jpa.JpaObjectRetrievalFailureException: Unable to find com.test.dailyemail.repository.NewsLink with id 8; nested exception is javax.persistence.EntityNotFoundException: Unable to find com.test.dailyemail.repository.NewsLink with id 8
javax.persistence.EntityNotFoundException: Unable to find com.test.dailyemail.repository.NewsLink with id 8
at org.hibernate.ejb.Ejb3Configuration$Ejb3EntityNotFoundDelegate.handleEntityNotFound(Ejb3Configuration.java:155)
at org.hibernate.event.internal.DefaultLoadEventListener.load(DefaultLoadEventListener.java:210)
at org.hibernate.event.internal.DefaultLoadEventListener.proxyOrLoad(DefaultLoadEventListener.java:260)
at org.hibernate.event.internal.DefaultLoadEventListener.onLoad(DefaultLoadEventListener.java:148)
at org.hibernate.internal.SessionImpl.fireLoad(SessionImpl.java:1078)
at org.hibernate.internal.SessionImpl.internalLoad(SessionImpl.java:1005)
at org.hibernate.type.EntityType.resolveIdentifier(EntityType.java:651)
at org.hibernate.type.EntityType.resolve(EntityType.java:471)
at org.hibernate.type.EntityType.replace(EntityType.java:328)
at org.hibernate.type.CollectionType.preserveSnapshot(CollectionType.java:581)
at org.hibernate.type.CollectionType.replaceElements(CollectionType.java:534)
at org.hibernate.type.CollectionType.replace(CollectionType.java:664)
at org.hibernate.type.TypeHelper.replace(TypeHelper.java:177)
at org.hibernate.event.internal.DefaultMergeEventListener.copyValues(DefaultMergeEventListener.java:372)
at org.hibernate.event.internal.DefaultMergeEventListener.entityIsDetached(DefaultMergeEventListener.java:309)
at org.hibernate.event.internal.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:151)
at org.hibernate.event.internal.DefaultMergeEventListener.onMerge(DefaultMergeEventListener.java:76)
at org.hibernate.internal.SessionImpl.fireMerge(SessionImpl.java:903)
at org.hibernate.internal.SessionImpl.merge(SessionImpl.java:887)
at org.hibernate.internal.SessionImpl.merge(SessionImpl.java:891)
at org.hibernate.ejb.AbstractEntityManagerImpl.merge(AbstractEntityManagerImpl.java:879)

【问题讨论】:

    标签: spring hibernate spring-mvc spring-data-jpa


    【解决方案1】:

    我不确定这是否是您的问题,因为我看不到其余代码,但我认为您应该返回 userRepository.save(user) 返回的 User 实例而不是原始用户对象,如果您仍然想要在删除 NewsLink 后使用该对象。

    save 方法的 javadoc 中它说:

    保存给定的实体。使用返回的实例进行进一步操作 因为保存操作可能已经改变了实体实例 完全。

    尝试类似的方法:

    @Override
    @Transactional
    public User deleteNewsLink(int id, User user){
    
        Iterator<NewsLink> links = user.getNewsLink().iterator();
    
        while(links.hasNext()){
            NewsLink link = links.next();
    
            if (link.getId() == id){
                links.remove();
                break;
            }
    
        }
    
        return userRepository.save(user);
    }
    

    【讨论】:

      【解决方案2】:

      尝试调用saveAndFlush 刷新数据库中的实体。

      @Override
      @Transactional
      public User deleteNewsLink(int id, User user){
      
          Iterator<NewsLink> links = user.getNewsLink().iterator();
      
          while(links.hasNext()){
              NewsLink link = links.next();
      
              if (link.getId() == id){
                  links.remove();
              }
      
          }
      
          userRepository.saveAndFlush(user);
      
          return user;
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-12-07
        • 2018-09-04
        • 2020-11-08
        • 2017-06-20
        • 1970-01-01
        • 2017-06-26
        • 2018-07-02
        • 2017-03-21
        相关资源
        最近更新 更多