JPA:传递给持久化的分离实体:嵌套异常是 org.hibernate.PersistentObjectException
Posted
技术标签:
【中文标题】JPA:传递给持久化的分离实体:嵌套异常是 org.hibernate.PersistentObjectException【英文标题】:JPA: detached entity passed to persist: nested exception is org.hibernate.PersistentObjectException 【发布时间】:2018-09-10 12:53:41 【问题描述】:JPA:多对多连接。
场景:
多个产品可以保存在多个类别下。 Like:芒果可以作为水果类和沙漠类。
产品 == [商品]
类别 == [GENRE]
例外:
detached entity passed to persist: sari.core.domain.account.Genre; nested exception is org.hibernate.PersistentObjectException: detached entity passed to persist:
商品.java:
@Entity
@Table(name = "COMMODITY")
public class Commodity implements Serializable
@Id
@Column(name = "id")
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
.........
.........
@ManyToMany(fetch = FetchType.LAZY,
cascade =
CascadeType.MERGE,
CascadeType.PERSIST
)
@JoinTable(name = "commodity_genre", joinColumns =
@JoinColumn(name = "commodity_id", referencedColumnName = "id") , inverseJoinColumns =
@JoinColumn(name = "genre_id", referencedColumnName = "id") )
@JsonManagedReference
private List<Genre> genres;
流派.java:
@Entity
@Table(name = "GENRE")
public class Genre implements Serializable
private static final long serialVersionUID = 7643588406864492883L;
@Id
@Column(name = "id")
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
.........
.........
@ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.PERSIST, CascadeType.MERGE , mappedBy = "genres")
@JsonBackReference
private List<Commodity> commodities;
我的行动计划:
-
检查您是否尝试持久化具有相同 ID 的实体
作为另一个实体,并且已经存在于
应用程序中的 PersistenceContext。
在保存或持久化之前不要设置 ID。休眠会看起来
在你通过的实体,它假设因为它有它的
主键填充它已经在数据库中。各种各样的
博客和人,已经使用删除 setId() 给出了解决方案
但没有运气。卡住几个小时。非常感谢任何形式的帮助。
资源链接:
Hibernate / JPA – Detached entity passed to persist exception
更多信息,您可以查看完整的异常日志:
01-04-2018 00:55:39 [g.a.c.CommodityController:55] addCommodity : addCommodity() method started!!
01-04-2018 00:55:39 [g.a.c.CommodityController:56] addCommodity : Full Model: Commodity [id=null, commodityName=Pant, price=345.0, unit=3, genres=null]
01-04-2018 00:55:39 [g.a.c.CommodityController:57] addCommodity : Genre Name is: Cloth
01-04-2018 00:55:39 [g.a.c.CommodityController:58] addCommodity : commodityName is: Pant
01-04-2018 00:55:39 [g.a.d.i.CommodityDaoImpl:124] saveCommodities : saveCommodites called
01-04-2018 00:55:39 [g.a.d.i.CommodityDaoImpl:113] checkGenreExistsInDB : checkGenreExistsInDB started
Hibernate: select genre0_.id as id1_9_, genre0_.genre_name as genre_na2_9_ from genre genre0_ where genre0_.genre_name=?
01-04-2018 00:55:39 [g.a.d.i.CommodityDaoImpl:118] checkGenreExistsInDB : checkGenreExistsInDB ended
01-04-2018 00:55:39 [g.a.d.i.CommodityDaoImpl:133] saveCommodities : genre not Exists
01-04-2018 00:55:39 [g.a.d.i.CommodityDaoImpl:135] saveCommodities : genre save in DB started
Hibernate: insert into genre (genre_name) values (?)
Hibernate: insert into commodity (commodity_name, price, unit) values (?, ?, ?)
01-04-2018 00:55:39 [g.a.d.i.CommodityDaoImpl:137] saveCommodities : genre save in DB ended
01-04-2018 00:55:39 [g.a.d.i.CommodityDaoImpl:140] saveCommodities : Size of genreList: 1
Hibernate: insert into commodity (commodity_name, price, unit) values (?, ?, ?)
01-04-2018 00:55:39 [g.c.u.GlobalExceptionHandler:58] runtimeExceptionHandle : org.springframework.dao.InvalidDataAccessApiUsageException: detached entity passed to persist: sari.core.domain.account.Genre; nested exception is org.hibernate.PersistentObjectException: detached entity passed to persist: sari.core.domain.account.Genre
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:299)
at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:244)
at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:488)
at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:59)
at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:213)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:147)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodInterceptor.invoke(CrudMethodMetadataPostProcessor.java:133)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.data.repository.core.support.SurroundingTransactionDetectorMethodInterceptor.invoke(SurroundingTransactionDetectorMethodInterceptor.java:57)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:213)
at com.sun.proxy.$Proxy160.save(Unknown Source)
at sari.account.dao.impl.CommodityDaoImpl.saveCommodities(CommodityDaoImpl.java:142)
at sari.account.services.CommodityService.saveCommodities(CommodityService.java:31)
at sari.account.controllers.CommodityController.addCommodity(CommodityController.java:59)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.web.method.support.InvocableHandlerMethod.doInvoke(InvocableHandlerMethod.java:205)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:133)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:116)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:827)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:738)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:85)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:963)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:897)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:970)
at org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:872)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:648)
at org.springframework.web.servlet.FrameworkServlet.service(FrameworkServlet.java:846)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:729)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:230)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
at sari.core.util.CorsConfiguration.doFilterInternal(CorsConfiguration.java:29)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
at org.springframework.security.web.FilterChainProxy.doFilterInternal(FilterChainProxy.java:208)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:177)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:262)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
at org.springframework.web.filter.RequestContextFilter.doFilterInternal(RequestContextFilter.java:99)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
at org.springframework.web.filter.HttpPutFormContentFilter.doFilterInternal(HttpPutFormContentFilter.java:105)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
at org.springframework.web.filter.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:81)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:197)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:192)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:165)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:198)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:96)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:474)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:140)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:87)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:349)
at org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:783)
at org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
at org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:798)
at org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1434)
at org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
at java.lang.Thread.run(Thread.java:748)
Caused by: org.hibernate.PersistentObjectException: detached entity passed to persist: sari.core.domain.account.Genre
at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:124)
at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:765)
at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:758)
at org.hibernate.jpa.event.internal.core.JpaPersistEventListener$1.cascade(JpaPersistEventListener.java:80)
at org.hibernate.engine.internal.Cascade.cascadeToOne(Cascade.java:398)
at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:323)
at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:162)
at org.hibernate.engine.internal.Cascade.cascadeCollectionElements(Cascade.java:431)
at org.hibernate.engine.internal.Cascade.cascadeCollection(Cascade.java:363)
at org.hibernate.engine.internal.Cascade.cascadeAssociation(Cascade.java:326)
at org.hibernate.engine.internal.Cascade.cascadeProperty(Cascade.java:162)
at org.hibernate.engine.internal.Cascade.cascade(Cascade.java:111)
at org.hibernate.event.internal.AbstractSaveEventListener.cascadeAfterSave(AbstractSaveEventListener.java:456)
at org.hibernate.event.internal.AbstractSaveEventListener.performSaveOrReplicate(AbstractSaveEventListener.java:278)
at org.hibernate.event.internal.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:178)
at org.hibernate.event.internal.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:109)
at org.hibernate.jpa.event.internal.core.JpaPersistEventListener.saveWithGeneratedId(JpaPersistEventListener.java:67)
at org.hibernate.event.internal.DefaultPersistEventListener.entityIsTransient(DefaultPersistEventListener.java:189)
at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:132)
at org.hibernate.event.internal.DefaultPersistEventListener.onPersist(DefaultPersistEventListener.java:58)
at org.hibernate.internal.SessionImpl.firePersist(SessionImpl.java:775)
at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:748)
at org.hibernate.internal.SessionImpl.persist(SessionImpl.java:753)
at org.hibernate.jpa.spi.AbstractEntityManagerImpl.persist(AbstractEntityManagerImpl.java:1146)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:298)
at com.sun.proxy.$Proxy156.persist(Unknown Source)
at org.springframework.data.jpa.repository.support.SimpleJpaRepository.save(SimpleJpaRepository.java:508)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.executeMethodOn(RepositoryFactorySupport.java:504)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.doInvoke(RepositoryFactorySupport.java:489)
at org.springframework.data.repository.core.support.RepositoryFactorySupport$QueryExecutorMethodInterceptor.invoke(RepositoryFactorySupport.java:461)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.data.projection.DefaultMethodInvokingMethodInterceptor.invoke(DefaultMethodInvokingMethodInterceptor.java:61)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:282)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:136)
... 76 more
01-04-2018 00:55:39 [g.c.u.GlobalExceptionHandler:77] <init> : Status: 200
01-04-2018 00:55:39 [g.c.u.GlobalExceptionHandler:78] <init> : Message : detached entity passed to persist: sari.core.domain.account.Genre; nested exception is org.hibernate.PersistentObjectException: detached entity passed to persist: sari.core.domain.account.Genre
01-04-2018 00:55:39 [g.c.u.GlobalExceptionHandler:79] <init> : Trace: Resource Not Available
【问题讨论】:
【参考方案1】:最后,我得到了 JPA 中多对多连接的解决方案。
根本原因分析:
在 JPA 多对多关系中,如果级联类型已设置为 CascadeType.PERSIST
(或 CascadeType.ALL
,其中包括 CascadeType.PERSIST),则在保存父级并使用子级引用更新它时,它会再次尝试拯救孩子。
可能会出现以下问题:
孩子已经在持久性存储(A detached instance has been passed)
- 在这种情况下,它会抛出一个异常“org.hibernate.PersistentObjectException: detached entity passed to persist”
解决方案:
使用这个:
@ManyToMany(fetch = FetchType.EAGER,
cascade =
CascadeType.MERGE,
CascadeType.REFRESH
)
@JoinTable(name = "commodity_genre", joinColumns =
@JoinColumn(name = "commodity_id", referencedColumnName = "id") , inverseJoinColumns =
@JoinColumn(name = "genre_id", referencedColumnName = "id") )
@JsonManagedReference
private List<Genre> genres;
代替:
@ManyToMany(fetch = FetchType.LAZY,
cascade =
CascadeType.MERGE,
CascadeType.PERSIST
)
@JoinTable(name = "commodity_genre", joinColumns =
@JoinColumn(name = "commodity_id", referencedColumnName = "id") , inverseJoinColumns =
@JoinColumn(name = "genre_id", referencedColumnName = "id") )
@JsonManagedReference
private List<Genre> genres;
对于 JPA,最好的选择是在尝试保存之前在服务器端查询实体。
如果确定只会添加新的孩子,而不是分离的 来自 DB 的实例,CascadeType.PERSIST
会处理它。
另一方面,如果要求是永远不要添加新的孩子,如果它是
尚未在 DB 中,则应删除 CascadeType.PERSIST
并
应该使用cascade=CascadeType.MERGE,CascadeType.REFRESH
资源链接:
Persisting a detached entity in JPA
【讨论】:
【参考方案2】:对我来说,问题在于使用 Cascade.ALL
而不是 Cascade.MERGE
。
【讨论】:
以上是关于JPA:传递给持久化的分离实体:嵌套异常是 org.hibernate.PersistentObjectException的主要内容,如果未能解决你的问题,请参考以下文章
有没有办法将分离的对象传递给 JPA 持久化? (分离的实体传递给坚持)
Spring Data JPA:一对一实例化问题:PersistentObjectException:分离实体传递给持久化