javax.persistence.PersistenceException: org.hibernate.PersistentObjectException: 分离的实体传递给 persist

2022-09-01 15:19:32

将JPA与Hibernate一起使用,我在运行以下代码时遇到了异常。我第一次运行它时,一切顺利,数据入到数据库中。第二次,当数据应该更新时,它失败了:

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

有什么想法吗?


答案 1

Persist适用于全新的瞬态对象,如果已分配 id,它将失败。您可能应该调用 而不是 。saveOrUpdatepersist

或者,您可以检查对象是否已包含在实体管理器中,如果是,则执行

entityManager.merge(yourObject);

entityManager.persist(yourObject);

答案 2

您的主要问题是您在一个DAO中加载实体:

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

但是,然后用另一个保存它们:

boutiqueDao.persist(boutique);

对于现有实体,这将生成分离的实体错误,因为实体具有 id,但不存在于第二个 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);

推荐