被忽略的remove()

问题描述 投票:4回答:2

[存在实体A引用(多对一)实体B,从B到A的反向(映射)引用。也有从A到C的引用,以及从C到A的反向引用。当我发出entityManager.remove(A)然后flush()时,“删除”未生效!但也没有例外。就像根本没有调用remove()一样。为什么会这样?如果在remove()之前,我们从反向引用B.listOfA和C.listOfA中提取A,则会按预期生成“删除”。

还请注意my another question,我得出的结论是orphanRemoval并非总是按预期运行。现在,我开始怀疑级联效果很好,但是在实际级联的删除之后,就象我在这里描述的那样被“吞噬”了。

java hibernate jpa jpa-2.0
2个回答
8
投票

看看这个answer。基本上,JPA规范要求如果对持久对象执行了持久化操作,就必须再次对其进行管理。

要验证是否确实在发生这种情况,请启用org.hibernate程序包的跟踪日志级别并搜索类似以下的日志条目:

un-scheduling entity deletion ...

为了避免任何不可预测的行为,建议从加载了相同会话/事务的所有其他实体实例中删除对已删除实体的引用。


0
投票

我遇到了这个问题。即使show_sql已启用:

<property name="hibernate.show_sql" value="true"></property>

没有输出,并且删除命令被静默忽略。

问题是围绕一对多关系,其中:待办事项1 --- * * todoitem

环境是:-JSF-Wildfly 18(JPA默认实现-休眠)-PostgreSQL 10

试图在任何一侧删除实例都将失败,并且在服务器的输出上没有相应的“ delete”命令,并且没有任何类型的异常消息。

SOLUTION

首先,我将Wildfly18 / JBoss文档在其示例中建议的多方代码从以下位置切换:

//    @Override
//    public void delete(Todoitem todoitem) {
//        if (todoitem == null) {
//            return;
//        }
//        if (!emPg.contains(todoitem)) {
//            todoitem = emPg.merge(todoitem);
//        }
//        emPg.remove(todoitem);
//        emPg.flush();
//        emPg.clear();
//    }

至等效形式:

@Override
public void delete(Todoitem todoitem) {
    if (todoitem == null) {
        return;
    }
    Todoitem ti = emPg.find(Todoitem.class, todoitem.getId());
    if(ti == null) {
        return;
    }
    emPg.remove(ti);
    emPg.flush();
    emPg.clear();
}

不幸的是,我得到了相同的结果-删除默默地忽略了。

然后,我怀疑数据库,因为休眠处理自己的密钥。在实施过程中我做了很多测试...为了确保一致性问题,我决定清空数据库,删除关系双方的内容。然后,我使用应用程序的资源(没有SQL命令)创建了新的实体实例和关系,因为除实体移除之外,其他所有东西都运行良好。之后,我使用SQL命令检查了数据库关系,以确保一切都很好。

接下来,我再次尝试了新测试,但是这次成功了。

由于是个好消息,我在“一个”方面重复了同样的操作(下面的代码-注释的代码是从Wildfly 18文档继承的第一个代码,如上所述)。

发件人:

//    @Override
//    public void delete(Todo todo) {
//        if(todo == null) {
//            return;
//        }
//        if (!emPg.contains(todo)) {
//            todo = emPg.merge(todo);
//        }
//        //todoitemDao.deleteAll(todo);
//        emPg.remove(todo);
//        emPg.flush();
//    }

收件人:

@Override
public void delete(Todo todo) {
    if (todo == null) {
        return;
    }
    Todo t = emPg.find(Todo.class, todo.getId());
    if(t == null) {
        return;
    }
    emPg.remove(t);
    emPg.flush();
    emPg.clear();
}

再次重复测试,但是这次不删除Todoitem实例(“很多”面,而是删除Todo实例(“一个”面)。

问题已解决。成功。

重要提示:

直接在数据库上使用SQL语句检查删除测试。有时,由于缓存问题或代码实现错误,实例似乎并未被删除,需要分开对待。

© www.soinside.com 2019 - 2024. All rights reserved.