Sql server 在使用PlatformTransactionManager完成事务之前未提交的插入

Sql server 在使用PlatformTransactionManager完成事务之前未提交的插入,sql-server,spring-boot,transactions,spring-data-jpa,spring-data,Sql Server,Spring Boot,Transactions,Spring Data Jpa,Spring Data,我需要确保在执行存储过程期间提交插入。使用SpringBootStarter数据JPA1.5,这是JpaTransactionManager的默认行为。对于SpringBoot2.x,在存储过程完成执行之前不会提交插入 因此,使用Spring Boot 2.x transaction mgmt调用此存储过程不会在1分钟后插入: CREATE procedure [dbo].[test_insert] as begin insert into myTempTable(col1) v

我需要确保在执行存储过程期间提交插入。使用SpringBootStarter数据JPA1.5,这是
JpaTransactionManager
的默认行为。对于SpringBoot2.x,在存储过程完成执行之前不会提交插入

因此,使用Spring Boot 2.x transaction mgmt调用此存储过程不会在1分钟后插入:

CREATE procedure [dbo].[test_insert]
as
begin
    insert into myTempTable(col1)
    values ("1");

    WAITFOR DELAY '00:01';
end
GO
但是使用SpringBoot1.5事务管理调用它,将立即插入,这正是我所需要的

这是密码。事务管理器:

@Bean
public PlatformTransactionManager transactionManager(EntityManagerFactory entityManagerFactory) {
    JpaTransactionManager transactionManager = new JpaTransactionManager();
    transactionManager.setEntityManagerFactory(entityManagerFactory);
    return transactionManager;
} 
回购:

我使用的是SQL Server 2016,其默认事务级别设置为READ COMMITTED

如何确保在执行过程中立即提交存储过程中的插入

更新

经过进一步研究,我发现使用Spring的事务管理器,我处于隐式事务模式。但当我不使用它时,我会自动提交。换句话说,
select@@OPTIONS&2
返回带Spring事务管理器的
2
,不带事务管理器的
0
。所以,我认为这就解释了为什么我在插入提交时看到了差异。如果是这样,那么我只需要知道如何设置自动提交。默认模式必须在Spring或SQLServerJDBC驱动程序中更改(我使用的是4.2,现在使用的是8.2.0.jre8)

更新2

为什么在存储过程完成之前,其他一些进程可以看到插入到MyTestable中很重要?因为在生产存储过程中,它执行插入操作,调用某个服务(我认为该服务从该行选择数据并将数据插入另一个表),然后sp
waitfor
数据出现在服务插入的表中。因此,在服务看不到insert的情况下,存储过程将挂起,等待服务插入到另一个表中

我认为解决方案是不使用显式事务,只让SQLServer默认为自动提交。不幸的是,这也意味着,如果存储过程中出现问题,就不能回滚。但是由于存储过程和服务是我不能更改的第三方组件,我想这是我唯一的选择。仍然想知道为什么SpringBoot1.5和2.x或JDBC驱动程序之间的行为有所不同

更新3

事实证明,SpringBoot1.5和2.x以及JDBC驱动程序版本之间的行为没有区别。也就是说,在事务完成之前,插入不会发生。我观察到行为差异的原因与以下事实有关:我在一个旧项目中使用Spring Boot 1.5进行测试,并且旧项目是一个具有两个数据源和两个事务管理器的复合项目,与我的Spring Boot 2.x项目不同。不确定为什么会这样,或者是什么会使insert在旧项目中立即发生,但它确实发生了


无论如何,通过查看SQL Server日志,我可以确认,无论Spring/JDBC版本如何,当自动提交模式打开时,它会立即插入。

如果执行存储过程遵循标准实体操作的“事务后写”模式,则SQL语句的正常行为是排队,直到事务完成

Spring数据存储库在默认情况下是事务性的,因此即使在测试中没有显式的
@transactional(transactionManager=“transactionManager”)
,事务仍在运行

(假设您在这里使用Hibernate,但在其他JPA实现中可能使用类似的概念)

尝试此操作可触发立即刷新:

@RunWith(SpringRunner.class)
@SpringBootTest
@Transactional(transactionManager="transactionManager")
public class InsertRepositoryTest {

    @Autowired
    private TestRepository testRepo;

    @PersistenceContext 
    primate EntityManager em;

    @Test
    public void testInsert() throws SQLException {
        testRepo.testInsert();
        em.flush(); //write all buffered SQL statements
    }   
}

从文档开始-不是java开发人员,但看起来您的存储库正在事务中包装sql连接。SQK服务器将跟踪此事务。您要么点击该侧,要么将SP更改为读取未限制的更改,否则会有回滚事务的危险。这将是对SP的一个更改(查看那里的选项-您可以说READUNCOMMITTED)。谢谢TomTom。我对OP提供了一些更新。我认为问题在于服务(存储过程调用了该服务,我在
waitfor
期间通过SSMS select查询模拟了该服务)看不到插入。我无法控制那项服务。所以,我不能告诉它读未提交。因此,我想我将在不使用显式txn的情况下调用sp,并让SQL Server默认使用自动提交模式(该模式将在sp中的每个语句之后提交)。这意味着没有回滚,但我想我别无选择。仍然想知道Spring/JDBC驱动程序发生了什么变化。这是不正确的。如果未定义任何事务,则每个命令都是单独的事务。我反复使用它,通过组合一个循环来删除大量数据,并在存储过程中删除事务之外的前X百万行。然后,您描述的行为分解为“for every command”语义,问题显然与此无关。如果没有定义事务??测试正在事务中运行:
@Transactional(transactionManager=“transactionManager”)
???当提问者在更新3中注意到这种行为时,为什么会进行向下投票?也就是说,在事务完成之前,插入从未发生过?看起来您的存储库正在事务中包装sql连接Spring数据存储库在默认情况下是事务性的,因此即使在测试之外,SP也将在事务中包装。所有Spring数据存储库在默认情况下都是事务性的吗?这似乎表明这只是事务性的。但是我的存储库正在扩展
存储库
。如果我指示从不传播,插入的txn将立即发生
@Transactional(传播=传播.never,transactionManager=“apxTransactionManager”)
@RunWith(SpringRunner.class)
@SpringBootTest
@Transactional(transactionManager="transactionManager")
public class InsertRepositoryTest {

    @Autowired
    private TestRepository testRepo;

    @Test
    public void testInsert() throws SQLException {
        testRepo.testInsert();
    }   

}
@RunWith(SpringRunner.class)
@SpringBootTest
@Transactional(transactionManager="transactionManager")
public class InsertRepositoryTest {

    @Autowired
    private TestRepository testRepo;

    @PersistenceContext 
    primate EntityManager em;

    @Test
    public void testInsert() throws SQLException {
        testRepo.testInsert();
        em.flush(); //write all buffered SQL statements
    }   
}