Skip to content
Advertisement

Detached entity passed to persist java spring

So i have a big error when trying to do an update method in my spring application ,the problem is regarding to the Caracter class as thats the one the seems to generate it. When i set my stuff in main and try to update an Anime object in the database the Caracter class gives me the errors presented below

the code

package com.site.anime.model;


import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import javax.persistence.*;
import java.util.List;

@Entity
@NoArgsConstructor
@AllArgsConstructor
@Data
public class Caracter {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    private String name;
    private String image;


    private String description;
    
    private Double overall_mark;

    @ManyToMany(cascade = { CascadeType.ALL })
    private List<Anime> shows;
}
package com.site.anime.model;


import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.hibernate.annotations.Fetch;

import javax.persistence.*;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Entity
@NoArgsConstructor
@AllArgsConstructor
@Data
public class Anime {

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


    private String name;
    private String image;



    private Integer no_episodes;
    private String description;
    private Double overall_score;

    @ManyToMany(cascade = { CascadeType.ALL })
    private List<Caracter> caracters;

    @OneToMany(cascade = { CascadeType.ALL })
    private List<Review> reviews;

    @ManyToMany(cascade = { CascadeType.ALL })
    private List<Category> categories;

}

package com.site.anime.service.impl;


import com.site.anime.model.Anime;
import com.site.anime.repository.RepositoryShow;
import com.site.anime.service.AnimeService;
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
import org.springframework.stereotype.Service;

import javax.transaction.Transactional;
import java.lang.reflect.Field;

@Service

public class AnimeServiceImpl implements AnimeService {


    private final RepositoryShow repositoryShow;

    public AnimeServiceImpl(RepositoryShow repositoryShow) {
        this.repositoryShow = repositoryShow;
    }

    @Override
    public Anime findFirstByName(String name) {
        return repositoryShow.findFirstByName(name);
    }

    @Override
    @Transactional
    public Anime updateAnime(Anime newShow) {
        Anime anime=repositoryShow.findById(newShow.getId()).orElseThrow();
        //System.out.println(anime.getCaracters().get(0).getName());
        if(newShow.getName()!=null){
            anime.setName(newShow.getName());
        }
        if(newShow.getImage()!=null){
            anime.setImage(newShow.getImage());
        }
        if(newShow.getNo_episodes()!=null){
            anime.setNo_episodes(newShow.getNo_episodes());
        }
        if(newShow.getDescription()!=null){
            anime.setDescription(newShow.getDescription());
        }
        if(newShow.getCaracters()!=null){
            anime.setCaracters(newShow.getCaracters());
        }
        if(newShow.getCategories()!=null){
            anime.setCategories(newShow.getCategories());
        }
        return anime;

        //anime=newShow;



//        Field[] fields = anime.getClass().getDeclaredFields();
//        Field[] fields1 = newShow.getClass().getDeclaredFields();
//        for(int i=0;i<fields.length;i++){
//            if(fields[i]!=fields1[i]){
//                fields[i]=fields1[i];
//            }
//        }
        //return null;
    }




}
package com.site.anime;

import com.site.anime.model.*;
import com.site.anime.repository.*;
import com.site.anime.service.impl.AnimeServiceImpl;
import com.site.anime.service.impl.CaracterServiceImpl;
import com.site.anime.service.impl.UserServiceImpl;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.data.jpa.repository.config.EnableJpaRepositories;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;

@EnableJpaRepositories
@SpringBootApplication
public class AnimeApplication {

    public static void main(String[] args) {
        SpringApplication.run(AnimeApplication.class, args);
    }

    @Bean
    CommandLineRunner init(RepositoryShow repositoryShow, RepositoryCategory repositoryCategory,
                           RepositoryCaracter repositoryCaracter, RepositoryUser repositoryUser,
                           RepositorySuperUser repositorySuperUser, ProfileRepository profileRepository, AnimeServiceImpl animeService,
                           CaracterServiceImpl caracterService, UserServiceImpl userService){
        return args -> {

            List<Anime> shows=new LinkedList<>();
            Caracter caracter=new Caracter(null,"Subaru","","",0.0,null);

            List<Caracter> caracters=new LinkedList<>();
            caracters.add(caracter);

            Profile profile=new Profile(null,"","",18,"",null,null,null,null,null);
            Utilizator user=new Utilizator(null);
            user.setName("rusu");
            //Review review=new Review(null,user,"",0);
            Review review=new Review(null,"",2,null,null,null);
            Review review1=new Review(null,"",5,null,null,null);
            List<Review> reviews=new LinkedList<>();
            review.setUser(user);
            review1.setUser(user);
            reviews.add(review);
            reviews.add(review1);
            //profile.setUser(user);

            Anime show=new Anime(null,"ReZero Season 1","",25,"",0.0,null,reviews,null);
            shows.add(show);

            caracter.setShows(shows);

            show.setCaracters(caracters);
            review.setReviewed_show(show);
            review1.setReviewed_show(show);
            profile.setReviews(reviews);
            user.setProfile(profile);


            repositoryShow.save(show);
            repositoryCaracter.save(caracter);
            repositoryUser.save(user);

            System.out.println(animeService.findFirstByName("ReZero Season 1").getName());
            //System.out.println(repositoryUser.findFirstByName("rusu").getName());
            Anime show1=new Anime(null,"ReZero Season 2","",25,"",0.0,null,reviews,null);

            System.out.println(caracterService.findFirstByName("Subaru").getName());
            System.out.println(userService.findFirstByName("rusu").getName());
            //System.out.println(animeService.findFirstByName("ReZero Season 1"));

            Utilizator user1=new Utilizator(null);
            List<Review> reviews1=new LinkedList<>();
            Review review2=new Review(null,"",2,null,null,null);
            Profile profile1=new Profile(null,"","",18,"",null,null,null,null,null);
            review2.setUser(user1);
            review2.setReviewed_show(show);
            reviews1.add(review2);
            profile1.setReviews(reviews1);
            user1.setProfile(profile1);
            repositoryUser.save(user1);
            
            
            
            show.setName("ReZero Season 2");
            animeService.updateAnime(show);

            userService.deleteUser(user1);

        };
    }
}

and the error

java.lang.IllegalStateException: Failed to execute CommandLineRunner
    at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:807) ~[spring-boot-2.4.3.jar:2.4.3]
    at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:788) ~[spring-boot-2.4.3.jar:2.4.3]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:333) ~[spring-boot-2.4.3.jar:2.4.3]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1311) ~[spring-boot-2.4.3.jar:2.4.3]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1300) ~[spring-boot-2.4.3.jar:2.4.3]
    at com.site.anime.AnimeApplication.main(AnimeApplication.java:23) ~[classes/:na]
Caused by: org.springframework.dao.InvalidDataAccessApiUsageException: detached entity passed to persist: com.site.anime.model.Caracter; nested exception is org.hibernate.PersistentObjectException: detached entity passed to persist: com.site.anime.model.Caracter
    at org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:297) ~[spring-orm-5.3.4.jar:5.3.4]
    at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:233) ~[spring-orm-5.3.4.jar:5.3.4]
    at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:566) ~[spring-orm-5.3.4.jar:5.3.4]
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:743) ~[spring-tx-5.3.4.jar:5.3.4]
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:711) ~[spring-tx-5.3.4.jar:5.3.4]
    at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:654) ~[spring-tx-5.3.4.jar:5.3.4]
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:407) ~[spring-tx-5.3.4.jar:5.3.4]
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:119) ~[spring-tx-5.3.4.jar:5.3.4]
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:186) ~[spring-aop-5.3.4.jar:5.3.4]
    at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.proceed(CglibAopProxy.java:750) ~[spring-aop-5.3.4.jar:5.3.4]
    at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:692) ~[spring-aop-5.3.4.jar:5.3.4]
    at com.site.anime.service.impl.AnimeServiceImpl$$EnhancerBySpringCGLIB$$3ebceda5.updateAnime(<generated>) ~[classes/:na]
    at com.site.anime.AnimeApplication.lambda$init$0(AnimeApplication.java:91) ~[classes/:na]
    at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:804) ~[spring-boot-2.4.3.jar:2.4.3]
    ... 5 common frames omitted
Caused by: org.hibernate.PersistentObjectException: detached entity passed to persist: com.site.anime.model.Caracter
    at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:120) ~[hibernate-core-5.4.28.Final.jar:5.4.28.Final]
    at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:104) ~[hibernate-core-5.4.28.Final.jar:5.4.28.Final]
    at org.hibernate.internal.SessionImpl.persistOnFlush(SessionImpl.java:765) ~[hibernate-core-5.4.28.Final.jar:5.4.28.Final]
    at org.hibernate.engine.spi.CascadingActions$8.cascade(CascadingActions.java:341) ~[hibernate-core-5.4.28.Final.jar:5.4.28.Final]
    at org.hibernate.engine.internal.Cascade.cascadeToOne(Cascade.java:492) ~[hibernate-core-5.4.28.Final.jar:5.4.28.Final]
    at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:416) ~[hibernate-core-5.4.28.Final.jar:5.4.28.Final]
    at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:218) ~[hibernate-core-5.4.28.Final.jar:5.4.28.Final]
    at org.hibernate.engine.internal.Cascade.cascadeCollectionElements(Cascade.java:525) ~[hibernate-core-5.4.28.Final.jar:5.4.28.Final]
    at org.hibernate.engine.internal.Cascade.cascadeCollection(Cascade.java:456) ~[hibernate-core-5.4.28.Final.jar:5.4.28.Final]
    at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:419) ~[hibernate-core-5.4.28.Final.jar:5.4.28.Final]
    at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:218) ~[hibernate-core-5.4.28.Final.jar:5.4.28.Final]
    at org.hibernate.engine.internal.Cascade.cascade(Cascade.java:151) ~[hibernate-core-5.4.28.Final.jar:5.4.28.Final]
    at org.hibernate.event.internal.AbstractFlushingEventListener.cascadeOnFlush(AbstractFlushingEventListener.java:159) ~[hibernate-core-5.4.28.Final.jar:5.4.28.Final]
    at org.hibernate.event.internal.AbstractFlushingEventListener.prepareEntityFlushes(AbstractFlushingEventListener.java:149) ~[hibernate-core-5.4.28.Final.jar:5.4.28.Final]
    at org.hibernate.event.internal.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:82) ~[hibernate-core-5.4.28.Final.jar:5.4.28.Final]
    at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:39) ~[hibernate-core-5.4.28.Final.jar:5.4.28.Final]
    at org.hibernate.event.service.internal.EventListenerGroupImpl.fireEventOnEachListener(EventListenerGroupImpl.java:93) ~[hibernate-core-5.4.28.Final.jar:5.4.28.Final]
    at org.hibernate.internal.SessionImpl.doFlush(SessionImpl.java:1362) ~[hibernate-core-5.4.28.Final.jar:5.4.28.Final]
    at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:453) ~[hibernate-core-5.4.28.Final.jar:5.4.28.Final]
    at org.hibernate.internal.SessionImpl.flushBeforeTransactionCompletion(SessionImpl.java:3212) ~[hibernate-core-5.4.28.Final.jar:5.4.28.Final]
    at org.hibernate.internal.SessionImpl.beforeTransactionCompletion(SessionImpl.java:2380) ~[hibernate-core-5.4.28.Final.jar:5.4.28.Final]
    at org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.beforeTransactionCompletion(JdbcCoordinatorImpl.java:447) ~[hibernate-core-5.4.28.Final.jar:5.4.28.Final]
    at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.beforeCompletionCallback(JdbcResourceLocalTransactionCoordinatorImpl.java:183) ~[hibernate-core-5.4.28.Final.jar:5.4.28.Final]
    at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.access$300(JdbcResourceLocalTransactionCoordinatorImpl.java:40) ~[hibernate-core-5.4.28.Final.jar:5.4.28.Final]
    at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.commit(JdbcResourceLocalTransactionCoordinatorImpl.java:281) ~[hibernate-core-5.4.28.Final.jar:5.4.28.Final]
    at org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:101) ~[hibernate-core-5.4.28.Final.jar:5.4.28.Final]
    at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:562) ~[spring-orm-5.3.4.jar:5.3.4]
    ... 16 common frames omitted

Advertisement

Answer

I think that the issue here is, that you are replacing the characters collection with a new collection and the collection has different object than the persistence context, although it uses the same primary key. Since you are cascading changes, Hibernate tries to flush the changes and realizes that an entity for that primary key is already associated with the persistence context and fails to flush with the exception you are seeing. If you want to just apply the entity to the database, try to use entityManager.merge without loading the entity first. Alternatively, you could also try to apply the collections like this:

    if (newShow.getCaracters()!=null) {
        for (Character c : newShow.getCaracters()) {
            anime.getCaracters().add(entityManager.getReference(Character.class, c.getId());
        }
    }
    if (newShow.getCategories()!=null) {
        for (Category c : newShow.getCategories()) {
            anime.getCategories().add(entityManager.getReference(Category.class, c.getId());
        }
    }
Advertisement