首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >JPA认为我正在删除一个分离的对象

JPA认为我正在删除一个分离的对象
EN

Stack Overflow用户
提问于 2010-03-11 21:11:20
回答 7查看 62.1K关注 0票数 43

我有一个DAO,用于使用JPA加载和保存我的域对象。我终于设法让事务处理工作起来了,现在我有了另一个问题。

在我的测试用例中,我调用DAO来加载具有给定id的域对象,检查它是否已加载,然后调用相同的DAO来删除我刚刚加载的对象。当我这样做的时候,我得到了以下结果:

代码语言:javascript
运行
AI代码解释
复制
java.lang.IllegalArgumentException: Removing a detached instance mil.navy.ndms.conops.common.model.impl.jpa.Group#10
 at org.hibernate.ejb.event.EJB3DeleteEventListener.performDetachedEntityDeletionCheck(EJB3DeleteEventListener.java:45)
 at org.hibernate.event.def.DefaultDeleteEventListener.onDelete(DefaultDeleteEventListener.java:108)
 at org.hibernate.event.def.DefaultDeleteEventListener.onDelete(DefaultDeleteEventListener.java:74)
 at org.hibernate.impl.SessionImpl.fireDelete(SessionImpl.java:794)
 at org.hibernate.impl.SessionImpl.delete(SessionImpl.java:772)
 at org.hibernate.ejb.AbstractEntityManagerImpl.remove(AbstractEntityManagerImpl.java:253)
 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:48)
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:37)
 at java.lang.reflect.Method.invoke(Method.java:600)
 at org.springframework.orm.jpa.SharedEntityManagerCreator$SharedEntityManagerInvocationHandler.invoke(SharedEntityManagerCreator.java:180)
 at $Proxy27.remove(Unknown Source)
 at mil.navy.ndms.conops.common.dao.impl.jpa.GroupDao.delete(GroupDao.java:499)
 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:48)
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:37)
 at java.lang.reflect.Method.invoke(Method.java:600)
 at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:304)
 at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:182)
 at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:149)
 at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:106)
 at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
 at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
 at $Proxy28.delete(Unknown Source)
 at mil.navy.ndms.conops.common.dao.impl.jpa.GroupDaoTest.testGroupDaoSave(GroupDaoTest.java:89)
 at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
 at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:48)
 at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:37)
 at java.lang.reflect.Method.invoke(Method.java:600)
 at junit.framework.TestCase.runTest(TestCase.java:164)
 at junit.framework.TestCase.runBare(TestCase.java:130)
 at junit.framework.TestResult$1.protect(TestResult.java:106)
 at junit.framework.TestResult.runProtected(TestResult.java:124)
 at junit.framework.TestResult.run(TestResult.java:109)
 at junit.framework.TestCase.run(TestCase.java:120)
 at junit.framework.TestSuite.runTest(TestSuite.java:230)
 at junit.framework.TestSuite.run(TestSuite.java:225)
 at org.eclipse.jdt.internal.junit.runner.junit3.JUnit3TestReference.run(JUnit3TestReference.java:130)
 at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
 at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:460)
 at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:673)
 at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:386)
 at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:196)

现在假设我正在使用相同的DAO实例,并且我没有更改EntityManagers (除非Spring在没有通知我的情况下这样做),这怎么可能是一个分离的对象呢?

我的DAO代码如下所示:

代码语言:javascript
运行
AI代码解释
复制
public class GenericJPADao<INTFC extends IAddressable, VO extends BaseAddressable> implements IWebDao, IDao<INTFC>, IDaoUtil<INTFC>
{
    private static Logger logger = Logger.getLogger (GenericJPADao.class);

    protected Class<?> voClass;

    @PersistenceContext(unitName = "CONOPS_PU")
    protected EntityManagerFactory emf;

    @PersistenceContext(unitName = "CONOPS_PU")
    protected EntityManager em;

    public GenericJPADao()
    {
        super ( );

        ParameterizedType genericSuperclass = 
                        (ParameterizedType) getClass ( ).getGenericSuperclass ( );
        this.voClass = (Class<?>) genericSuperclass.getActualTypeArguments ( )[1];
    }


    ...


    public void delete (INTFC modelObj, EntityManager em)
    {
        em.remove (modelObj);
    }

    @SuppressWarnings("unchecked")
    public INTFC findById (Long id)
    {
        return ((INTFC) em.find (voClass, id));
    }
}

测试用例代码如下所示:

代码语言:javascript
运行
AI代码解释
复制
IGroup loadedGroup = dao.findById (group.getId ( ));
assertNotNull (loadedGroup);
assertEquals (group.getId ( ), loadedGroup.getId ( ));

dao.delete (loadedGroup); // - This generates the above exception

loadedGroup = dao.findById (group.getId ( ));
assertNull(loadedGroup);

有人能告诉我我哪里做错了吗?

EN

回答 7

Stack Overflow用户

回答已采纳

发布于 2010-03-11 21:30:52

我怀疑您是在事务外部运行您的代码,因此您的finddelete操作发生在单独的持久性上下文中,并且find实际上返回一个分离的实例(所以JPA是对的,您正在删除一个分离的对象)。

将查找/删除序列包装在事务中。

更新:7.3.1. Transaction Persistence Context章节摘录下面的

如果在活动事务之外将EntityManager与事务持久性上下文模型一起使用,则每次方法调用都会创建一个新的持久性上下文,执行方法操作,并结束持久性上下文。例如,考虑在事务外部使用EntityManager.find方法。EntityManager将创建一个临时持久化上下文,执行查找操作,结束持久化上下文,并将分离的结果对象返回给您。具有相同id的第二次调用将返回第二个分离的对象。

票数 68
EN

Stack Overflow用户

发布于 2012-03-01 08:31:52

代码语言:javascript
运行
AI代码解释
复制
public void remove(Object obj){
    em.remove(em.merge(obj));
}

上面的代码类似于zawhtut提出的代码。

票数 35
EN

Stack Overflow用户

发布于 2010-11-25 05:10:03

+1到Pascal Thivent的帖子,只是一个后续。

代码语言:javascript
运行
AI代码解释
复制
    @Transactional
    public void remove(long purchaseId){
        Purchase attached = jpaTemplate.find(Purchase.class,purchaseId);
        jpaTemplate.remove(attached);
    }
票数 15
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2428706

复制
相关文章

相似问题

领券
社区富文本编辑器全新改版!诚邀体验~
全新交互,全新视觉,新增快捷键、悬浮工具栏、高亮块等功能并同时优化现有功能,全面提升创作效率和体验
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文