【问题标题】:Hibernate transaction duplicate problemHibernate事务重复问题
【发布时间】:2010-11-16 00:32:33
【问题描述】:

我想更新我在数据库中的一些表,并希望所有这些工作在 1 个事务中完成, 首先,我删除了 branchbuildin(Table) 中的一些条目并在此操作后插入新条目 当我使用相同的 buildingname 和 branch_fk 插入和输入时出现问题(因为我在这个表上有这个约束( uniqueConstraints={@UniqueConstraint(columnNames={"buildingname","branch_fk"})}))但是当我没有t 使用休眠会话并使用正常的 JDBC 事务我没有这些问题。

List<Integer> allBranchBuilding = branchBuildingDao.getAllBranchBuildingID(pkId, sess);
            for (Integer integer : allBranchBuilding) {
                branchBuildingDao.delete(integer, sess); // delete kardane tamame BranchBuilding ha va tel haie aanha
            }

            Address myAdr = new Address();
            setAddress(myAdr, centralFlag, city, latit, longit, mainstreet, remainAdr, state);
            BranchBuildingEntity bbe = new BranchBuildingEntity();
            setBranchBuildingEntity(bbe, be, myAdr, city, centralFlag, latit, longit, mainstreet, buildingName, remainAdr, state, des);
            branchBuildingDao.save(bbe, sess);//Exception Occurred                

我在第一个方法中得到我的会话:

        Session sess = null;
        sess = HibernateUtil.getSession();
        Transaction tx = sess.beginTransaction();

【问题讨论】:

    标签: java hibernate session transactions


    【解决方案1】:

    你是对的,一切都发生在同一个事务和同一个 Hibernate Session 中。

    Session 会跟踪它管理的每个实体。即使您要求在数据库中删除它,相应的对象仍会保存在 Session 中,直到 Session 终止。

    一般来说,有可能 Hibernate 重新排序您的操作 将它们发送到数据库时,对于 效率原因。

    您可以做的是刷新(即发送到数据库)您的事务,因为保存(如果需要,您还可以清除 - 即清空 Session 存储的实体 - 刷新后):

    sess.flush();
    // sess.clear(); // if needed or convenient for you
    branchBuildingDao.save(bbe, sess);
    

    另请注意,虽然会话会记住您的实体,但修改它们会在关闭会话时触发自动更新。

    在我们的项目中,我们有一个方法可以有效地删除一个集合(另一个用于数组,使用方便的... 参数语法声明)实体(它适用于所有实体,不必这样做对于每个实体),同时将它们从会话中删除,并在之前处理刷新:

    1. 循环遍历所有实体,将其删除(使用sess.delete(e))并将其添加到“已删除”列表中。
    2. 每 50 个实体(对应于我们出于效率原因配置的批量大小)(最后):
      • 刷新 Session 以强制 Hibernate 立即将更改发送到数据库,
      • 在“已删除”列表上循环,从 Session 中清除每个实体(使用 sess.evict(e))。
      • 清空“已删除”列表。

    别担心,flush 只会将 SQL 发送到数据库。它仍然可以提交或回滚。

    【讨论】:

    • Tanx 但是如果我刷新会话会发生什么,然后我的连接 CUTOFF 在刷新后事务回滚?我需要在一个事务中完成所有工作(我可以在它们之间使用刷新并且不会伤害事务回滚和提交吗?)
    • KLE 是对的(除了在先前删除的实体上调用 evict() 是非常有问题的,但与手头的问题无关)“刷新”只是一个与数据库同步会话状态的过程,例如它将向数据库发出必要的插入/更新/删除语句。关于事务,这与手动发出相同的语句没有什么不同——除非事务被提交,所有这些语句都将被回滚(因为显式回滚、终止连接、服务器死机,你有什么)。
    • @ChssPly76 嗨。我很好奇你的“驱逐”评论。你能扩展一下这个问题吗?
    • 在最好的情况下(被删除的实例没有在应用程序的其他地方引用)随后的驱逐是毫无意义的(如果你这样做是为了节省内存,你要么坚持你的会话long 或者您应该使用批量删除 HQL)。如果从某处引用了实体 ,那么您通过驱逐它来欺骗自己摆脱快速失败的“已删除实体传递给持久”异常。是的,只有当您的代码有错误时才会发生这种情况,但这样的事情非常很难捕捉到。这就是所有“帮助!我删除的记录再次出现”错误的来源
    猜你喜欢
    • 1970-01-01
    • 2011-01-07
    • 1970-01-01
    • 1970-01-01
    • 2012-04-28
    • 1970-01-01
    • 1970-01-01
    • 2015-04-28
    • 2016-01-11
    相关资源
    最近更新 更多