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

使用JPA和Hibernate,运行以下代码时出现exception。 我第一次运行它,一切都很顺利,数据插入数据库。 第二次,当数据应该更新时,它会失败:

@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 { /** * */ 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。

任何想法?

Persist用于全新的瞬态对象,如果已经分配了id,则失败。 您应该调用saveOrUpdate而不是persist

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

 entityManager.merge(yourObject); 

,其他

 entityManager.persist(yourObject); 

您的主要问题是您在一个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);