Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Spring Data JPA JpaObjectRetrievalFailureException occurring after deleting ManyToOne record

I am having an issue where when I delete a record on the many side of a ManyToOne relationship it works, but on the next database transaction I get an exception saying the entity I just deleted is not found (e.g when trying to add another link it says it can't find the one I just deleted). I verified in the database the record is being deleted.

I am using Spring MVC and Spring Data JPA with Hibernate. I have a user class and a NewsLink class. A user can have many newslinks and I want to delete one of those newslinks. I'm just learning how to use Spring framework on my own by building a simple application. So this is pretty new to me. I appreciate any help!

User Entity Class

@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 Class

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

This is the method in the service class that is executing the delete. I think this is the part I'm not doing correctly:

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

This is the exception I'm seeing:

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)
like image 650
ssn771 Avatar asked Jan 06 '13 21:01

ssn771


1 Answers

I'm not sure if that is your problem because I can't see the rest of the code but I think that you should return the User instance return by userRepository.save(user) instead of the original user object if you still want to use that object after deleting a NewsLink.

In the javadoc of the save method it says :

Saves a given entity. Use the returned instance for further operations as the save operation might have changed the entity instance completely.

Try something like that :

@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);
}
like image 97
Jean-Philippe Bond Avatar answered Oct 05 '22 13:10

Jean-Philippe Bond