【发布时间】:2022-01-20 17:36:40
【问题描述】:
我是数据库和事务的新手。我发现了很多不同的最新信息,目前正在尝试整理我的想法。 关于上下文,我正在尝试使用 SQL Server 测试当前的隔离级别,但没有成功。
为此,我将 Spring Transaction 与 Eclipse Link 一起使用。我找到了一些关于 Spring 事务的信息 (https://www.marcobehler.com/guides/spring-transaction-management-transactional-in-depth)。不过还是有works unit的概念,现在不知道用的是什么(https://wiki.eclipse.org/Introduction_to_EclipseLink_Transactions_(ELUG)#Unit_of_Work_Architecture)
我要测试的内容: 我有一个实体用户(id、firstname、lastname)。我在表 id = 1, firstname = foo lastname = bar 中有一个条目
我有服务和交易。恕我直言,SQL Server 的默认设置是隔离 READ_COMMIT
@Transactional
public User updateUser(){
User updateUser = new User(1, "new firstname", "new lastname");
User updatedUser = userRepository.save(updateUser); --> em.merge
return updatedUser;
}
到目前为止一切顺利。我现在不明白。我在返回中设置了一个断点。 同时我打开了第二个 SQL 客户端并执行了以下 SQL。
SET IMPLICIT_TRANSACTIONS ON
UPDATE
User
SET
lastname = 'complete new',
WHERE
id = 1
COMMIT TRAN
我期望的是 SQL 语句将等待 Spring 事务完成。 BUT目前不是这样,只是简单的执行了SQL语句。
然后姓在表中姓氏“全新”然后我恢复断点,然后姓氏是“新姓氏”。这种行为我无法理解。这是正常的还是因为eclipse链接的单元工作?
【问题讨论】:
-
将
em.flush()添加到您的存储库save以查看任何内容。现在的情况是,数据库没有机会获得写锁,因为 JPA 会延迟 SQL 直到事务提交。 -
Mhm 在事务 spring 之后会执行一个 commit。这是一个弹簧数据存储库,为什么我需要刷新?
-
EclipseLink 缓冲需要尽可能长时间执行的 SQL 语句,以减少 RDBMS 中的锁定时间。在您的特定情况下,当 Spring Data JPA 提交事务时,JDBC 驱动程序将收到 UPDATE 语句。您可以通过在 EclispeLink 中启用 SQL 日志记录来验证它:stackoverflow.com/q/2374395/17695211
-
启用 SQL 日志记录后,您会看到断点处的控制台中不会有任何 SQL 调试输出。它会出现在返回之后。如果您真的想看到锁定效果,您需要使用
@PersistenceContext-injectedEntityManager编写没有 Spring Data JPA 的存储库,并调用EntityManager.flush这会将 EclipseLink 的 SQL 语句缓冲区刷新到 JDBC 驱动程序 在断点之前. -
或者(如果您喜欢冒险的话),您可以尝试在 EclipseLink 源代码中寻找执行相应
PreparedStatement的位置,并在其后设置断点。
标签: java sql-server eclipselink spring-transactions