行被另一个事务处理更新或删除(或未保存的值映射不正确)

行被另一个事务处理更新或删除(或未保存的值映射不正确)

<p>我有一个在网络服务器上运行的 java 项目。 我总是遇到这个异常。<br /> 我阅读了一些文档,发现悲观锁定(或乐观,但我读到悲观更好)是防止此异常的最佳方法。<br /> 但我找不到任何明确的例子来解释如何使用它。<br /> 我的方法是这样的:</p> <pre><code class="lang-"> @Transactional public void test(Email email, String subject) { getEmailById(String id); email.setSubject(subject); updateEmail(email); } while: • Email is a Hibernate class (it will be a table in the database) • getEmailById(String id) is a function that returns an email (this method is not annotated with @Transactional) • updateEmail(email): is a method that updates the email. </code></pre> <p>注意:我使用 Hibernate 进行保存、更新等(例如:session.getcurrentSession.save(email))</p>
行被另一个事务处理更新或删除(或未保存的值映射不正确) 2022-09-01 15:25:13
行被另一个事务处理更新或删除(或未保存的值映射不正确) 0
行被另一个事务处理更新或删除(或未保存的值映射不正确)
<p>通常不建议使用悲观锁定,而且它在数据库端的性能方面非常昂贵。 您提到的问题(代码部分)有几件事不清楚,例如:<br /> • 如果您的代码同时被多个线程访问。<br /> • 您如何创建会话对象(不确定您是否使用 Spring)?<br /> Hibernate<a href="http://docs.jboss.org/hibernate/core/3.5/api/org/hibernate/Session.html" target="_blank">会话对象不是线程安全的</a>。因此,如果有多个线程访问同一个会话并试图更新同一个数据库实体,那么您的代码可能会出现如下错误情况。</p> <p>因此,这里发生的情况是,多个线程尝试更新同一个实体,一个线程成功,当下一个线程提交数据时,它看到它已经被修改,并最终抛出 StaleObjectStateException<br /> 编辑:</p> <p>有一种方法可以在 Hibernate 中使用悲观锁定。<a href="http://docs.jboss.org/hibernate/core/3.3/reference/en/html/transactions.html#transactions-locking" target="_blank">查看此链接</a>。但这一机制似乎存在一些问题。然而,我在 hibernate(<a href="https://hibernate.atlassian.net/browse/HHH-5275" target="_blank">HHH-5275</a>)中发现了一个 bug 。bug 中提到的场景如下:</p> <p>两个线程正在读取同一个数据库记录; 其中一个线程应该使用悲观锁定,从而阻塞另一个线程。 但是两个线程都可以读取导致测试失败的数据库记录。<br /> 这与您面临的情况非常接近。 如果这不起作用,请尝试此操作,我能想到的唯一方法是使用<a href="http://docs.jboss.org/hibernate/core/3.3/reference/en/html/querysql.html" target="_blank">本机 SQL 查询</a>,您可以使用 SELECT FOR UPDATE 查询在 <a href="http://www.postgresql.org/docs/8.2/static/sql-select.html#SQL-FOR-UPDATE-SHARE" target="_blank">postgres 数据库中实现悲观锁定</a>。</p>