web-dev-qa-db-ja.com

javax.persistence.PersistenceException:org.hibernate.PersistentObjectException:永続化に渡された分離されたエンティティ

HibernateでJPAを使用すると、次のコードを実行すると例外が発生しました。初めて実行すると、すべてが正常に実行され、データがデータベースに挿入されます。 2回目は、データを更新する必要があるときに失敗します。

@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()は、単にEntityManager.persist()メソッドを呼び出します。

そして、ここで私のブティッククラス:

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

}

そして最後に、私のスタックトレース:

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

Tomcat 7.0.32サーバーでJava 7.0.11を実行しています。

何か案が?

20
Alexis Dufrenoy

Persistは、新しい一時オブジェクトを対象としており、IDが既に割り当てられている場合は失敗します。おそらくsaveOrUpdateの代わりにpersistを呼び出す必要があります。

または、オブジェクトが既にエンティティマネージャーに含まれているかどうかを確認できます。含まれている場合は、

entityManager.merge(yourObject);

、その他

entityManager.persist(yourObject);
39
Raul Rene

主な問題は、1つのDAOにエンティティをロードしていることです。

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

しかし、それらを別のもので保存します:

boutiqueDao.persist(boutique);

既存のエンティティの場合、エンティティにはIDがありますが、2番目のDAOの作業単位には存在しないため、これは分離エンティティエラーを生成します。もちろん、読み取り/永続化に同じDAOを使用した場合でも、persistを使用して既存のエンティティを保存することは想定されていないため、問題が発生します。代わりにこれを試してください:

エンティティの保存に使用するのと同じDAOを使用してエンティティを読み取ります

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

オブジェクトの即時永続化を行うために、新しいブティックの取り扱いを変更します

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

最後の持続をマージに変更します

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

boutique = boutiqueDao.merge(boutique);
4
Perception