web-dev-qa-db-fra.com

javax.persistence.PersistenceException: org.hibernate.PersistentObjectException: entité détachée passée pour persister

En utilisant JPA avec Hibernate, j'ai eu une exception lors de l'exécution du code suivant. La première fois que je l'exécute, tout se passe bien et les données sont insérées dans la base de données. La deuxième fois, lorsque les données doivent être mises à jour, cela échoue:

@AdminTx
public void processSite(Site site) {
    FluxBoutiqueMapping mapping = mapper.generateMappingFromUrl(site);

    Boutique boutique;
    for (FluxBoutiqueMapping.Boutique fluxBoutique : mapping.getListe().getBoutiques()) {
        log.error("Dans la boucle");
        boutique = daoAdmin.namedQuerySingle(Boutique.LOAD_BOUTIQUE_BY_IDWEBSC, fluxBoutique.getId());
        log.error("boutique : "+boutique);

        if (boutique==null) {
            log.error("Dans le new");
            boutique = new Boutique();
        }

        boutique.setSite(site);
        boutique.setUrlLogo(fluxBoutique.getLogo());
        boutique.setUrlBoutique(fluxBoutique.getUrl());
        boutique.setSelected(false);
        boutique.setIdWebSC(fluxBoutique.getId());
        boutique.setDateModification(new Date());

        boutiqueDao.persist(boutique);

        boutique = null;
    }
}

boutiqueDao.persist () appelle simplement la méthode EntityManager.persist ().

Et voici ma classe Boutique:

@Entity
@Table(name = "BOUTIQUE")
@SequenceGenerator(name = "SEQ_BOUTIQUE", sequenceName = "SEQ_BOUTIQUE")
@NamedQueries(value = {
        @NamedQuery(name = Boutique.LOAD_BOUTIQUE_BY_IDWEBSC, query = "from Boutique b where b.idWebSC=?1"),
})
public class Boutique implements IPersistentObject, IPubliable<Manifestation> {

    /**
     * 
     */
    private static final long serialVersionUID = -3038903536445432584L;

    public static final String LOAD_BOUTIQUE_BY_IDWEBSC = "load.boutique.by.idwebsc";

    protected long idBoutique;

    protected Site site;

    protected Long idOrigine;

    protected String urlLogo;

    protected String urlBoutique;

    protected boolean selected;

    protected long idWebSC;

    protected Date datePublication;

    protected Date dateModification;

    @Override
    @Id
    @GeneratedValue(generator="SEQ_BOUTIQUE")
    @Column(name = "ID_BOUTIQUE", unique = true, nullable = false, precision = 8, scale = 0)
    public Long getId() {
        return this.idBoutique;
    }

    public void setId(Long idBoutique) {
        this.idBoutique = idBoutique;
    }

    @Override
    public void setIdOrigine(Long idOrigine) {
        this.idOrigine = idOrigine;
    }

    @Override
    @Column(name = "IDORIGINE", length = 7)
    public Long getIdOrigine() {
        return this.idOrigine;
    }

    @Override
    @Temporal(TemporalType.DATE)
    @Column(name = "DATE_PUBLICATION", length = 7)
    public Date getDatePublication() {
        return datePublication;
    }

    @Override
    public void setDatePublication(Date datePublication) {
        this.datePublication = datePublication;

    }

    @Override
    @Temporal(TemporalType.DATE)
    @Column(name = "DATE_MODIFICATION", length = 7)
    public Date getDateModification() {
        return dateModification;
    }

    public void setDateModification(Date dateModification) {
        this.dateModification = dateModification;
    }

    @Override
    public void update(Manifestation newer) {
        // TODO Auto-generated method stub

    }

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "ID_SITE")
    @ForeignKey(name = "FK_BOUTIQUE_SITE")
    public Site getSite() {
        return site;
    }

    public void setSite(Site site) {
        this.site = site;
    }

    @Column(name = "URL_LOGO", length = 255)
    public String getUrlLogo() {
        return urlLogo;
    }

    public void setUrlLogo(String urlLogo) {
        this.urlLogo = urlLogo;
    }

    @Column(name = "URL_BOUTIQUE", length = 255)
    public String getUrlBoutique() {
        return urlBoutique;
    }

    public void setUrlBoutique(String urlBoutique) {
        this.urlBoutique = urlBoutique;
    }

    @Column(name = "SELECTED")
    public boolean isSelected() {
        return selected;
    }

    public void setSelected(boolean selected) {
        this.selected = selected;
    }

    @Column(name = "ID_WEBSC", length = 7)
    public long getIdWebSC() {
        return idWebSC;
    }

    public void setIdWebSC(long idWebSC) {
        this.idWebSC = idWebSC;
    }

}

Et enfin, mon stacktrace:

javax.persistence.PersistenceException: org.hibernate.PersistentObjectException: detached entity passed to persist: fr.u2m.viparis.business.Boutique
        at org.hibernate.ejb.AbstractEntityManagerImpl.throwPersistenceException(AbstractEntityManagerImpl.Java:630)
        at org.hibernate.ejb.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.Java:219)
        at fr.u2m.dao.jpa.GenericDaoJPAImpl.persist(GenericDaoJPAImpl.Java:60)
        at fr.u2m.viparis.service.impl.BoutiqueService.processSite(BoutiqueService.Java:81)
        at fr.u2m.viparis.service.impl.BoutiqueService.processAllFluxBoutique(BoutiqueService.Java:52)
        at Sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at Sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
        at Sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
        at Java.lang.reflect.Method.invoke(Unknown Source)
        at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.Java:309)
        at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.Java:196)
        at $Proxy136.processAllFluxBoutique(Unknown Source)
        at fr.u2m.viparis.fluxboutique.action.FluxBoutiqueAction.loadFlux(FluxBoutiqueAction.Java:27)
        at Sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
        at Sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
        at Sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
        at Java.lang.reflect.Method.invoke(Unknown Source)
        at org.Apache.struts.actions.DispatchAction.dispatchMethod(DispatchAction.Java:270)
        at org.Apache.struts.actions.DispatchAction.execute(DispatchAction.Java:187)
        at fr.u2m.struts.OpenViewRequestProcessor.processJpaActionPerform(OpenViewRequestProcessor.Java:270)
        at fr.u2m.struts.OpenViewRequestProcessor.processActionPerform(OpenViewRequestProcessor.Java:115)
        at org.Apache.struts.action.RequestProcessor.process(RequestProcessor.Java:236)
        at fr.u2m.struts.OpenViewRequestProcessor.process(OpenViewRequestProcessor.Java:230)
        at org.Apache.struts.action.ActionServlet.process(ActionServlet.Java:1196)
        at org.Apache.struts.action.ActionServlet.doGet(ActionServlet.Java:414)
        at javax.servlet.http.HttpServlet.service(HttpServlet.Java:621)
        at javax.servlet.http.HttpServlet.service(HttpServlet.Java:722)
        at org.Apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.Java:305)
        at org.Apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.Java:210)
        at fr.u2m.viparis.cms.filter.MultiTabSessionFilter.doFilter(MultiTabSessionFilter.Java:75)
        at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.Java:237)
        at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.Java:167)
        at org.Apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.Java:243)
        at org.Apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.Java:210)
        at fr.u2m.viparis.cms.filter.MonitoringFilter.doFilter(MonitoringFilter.Java:54)
        at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.Java:237)
        at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.Java:167)
        at org.Apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.Java:243)
        at org.Apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.Java:210)
        at fr.u2m.viparis.cms.util.auditing.AuditingFilter.doFilter(AuditingFilter.Java:44)
        at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.Java:237)
        at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.Java:167)
        at org.Apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.Java:243)
        at org.Apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.Java:210)
        at fr.u2m.util.SetCharacterEncodingFilter.doFilter(SetCharacterEncodingFilter.Java:71)
        at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.Java:237)
        at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.Java:167)
        at org.Apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.Java:243)
        at org.Apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.Java:210)
        at org.springframework.orm.hibernate3.support.OpenSessionInViewFilter.doFilterInternal(OpenSessionInViewFilter.Java:198)
        at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.Java:76)
        at org.Apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.Java:243)
        at org.Apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.Java:210)
        at org.Apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.Java:222)
        at org.Apache.catalina.core.StandardContextValve.invoke(StandardContextValve.Java:123)
        at org.Apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.Java:472)
        at org.Apache.catalina.core.StandardHostValve.invoke(StandardHostValve.Java:168)
        at org.Apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.Java:99)
        at org.Apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.Java:929)
        at org.Apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.Java:118)
        at org.Apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.Java:407)
        at org.Apache.coyote.ajp.AjpProcessor.process(AjpProcessor.Java:200)
        at org.Apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.Java:585)
        at org.Apache.Tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.Java:310)
        at Java.util.concurrent.ThreadPoolExecutor.runWorker(Unknown Source)
        at Java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source)
        at Java.lang.Thread.run(Unknown Source)
Caused by: org.hibernate.PersistentObjectException: detached entity passed to persist: fr.u2m.viparis.business.Boutique
        at org.hibernate.event.def.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.Java:79)
        at org.hibernate.event.def.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.Java:38)
        at org.hibernate.impl.SessionImpl.firePersist(SessionImpl.Java:618)
        at org.hibernate.impl.SessionImpl.persist(SessionImpl.Java:592)
        at org.hibernate.impl.SessionImpl.persist(SessionImpl.Java:596)
        at org.hibernate.ejb.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.Java:213)
        ... 65 more

J'exécute Java 7.0.11 sur un serveur Tomcat 7.0.32.

Une idée?

20
Alexis Dufrenoy

Persist est destiné aux tout nouveaux objets transitoires et il échoue si l'id est déjà attribué. Vous devriez probablement appeler saveOrUpdate au lieu de persist.

Vous pouvez également vérifier si l'objet est déjà contenu dans votre gestionnaire d'entités, et si c'est le cas,

entityManager.merge(yourObject);

,autre

entityManager.persist(yourObject);
39
Raul Rene

Votre problème principal est que vous chargez des entités dans un DAO:

boutique = daoAdmin.namedQuerySingle(
    Boutique.LOAD_BOUTIQUE_BY_IDWEBSC, fluxBoutique.getId());

Mais ensuite, enregistrez-les avec un autre:

boutiqueDao.persist(boutique);

Dans le cas d'entités existantes, cela générera une erreur d'entité détachée, car l'entité a un identifiant, mais n'existe pas dans l'unité de travail du deuxième DAO. Bien sûr, même si vous aviez utilisé le même DAO pour la lecture/persistance, vous rencontriez toujours des problèmes car vous n'êtes pas censé utiliser persist pour enregistrer les entités existantes. Essayez plutôt ceci:

Lisez les entités utilisant le même DAO que vous allez utiliser pour les enregistrer

boutique = boutiqueDAO.namedQuerySingle (Boutique.LOAD_BOUTIQUE_BY_IDWEBSC, fluxBoutique.getId ());

Modifiez votre gestion des nouvelles boutiques, pour faire une persistance immédiate de l'objet

if (boutique==null) {
    log.error("Dans le new");
    boutique = new Boutique();
    boutiqueDAO.persist(boutique);
}

Changer la dernière persistance en fusion

boutique.setIdWebSC(fluxBoutique.getId());
boutique.setDateModification(new Date());

boutique = boutiqueDao.merge(boutique);
4
Perception