簡體   English   中英

使用 PlatformTransactionManager 完成事務后才提交插入

[英]Inserts not committed until after transaction completes using PlatformTransactionManager

我需要確保在執行存儲過程期間提交插入。 使用 Spring Boot Starter Data JPA 1.5,這是JpaTransactionManager的默認行為。 使用 Spring Boot 2.x,在存儲過程完成執行之前不會提交插入。

因此,使用 Spring Boot 2.x 事務管理調用此存儲過程,將不會在 1 分鍾后插入:

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

    WAITFOR DELAY '00:01';
end
GO

但是使用 Spring Boot 1.5 事務管理調用它,會立即插入,這正是我所需要的。

這是代碼。 交易經理:

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

回購:

public interface TestRepository extends Repository<String, Long> {

    @Procedure("test_insert")
    void testInsert();

}

測試用例:

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

    @Autowired
    private TestRepository testRepo;

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

}

我使用的是 SQL Server 2016,它的默認事務級別設置為 READ COMMITTED。

如何確保在執行期間立即提交存儲過程中的插入?

更新

經過更多研究,我發現使用 Spring 的事務管理器時,我處於隱式事務模式。 但是當我不使用它時,我處於自動提交狀態。 換句話說, select @@OPTIONS & 2使用 Spring 的事務管理器返回2 ,沒有它返回0 所以,我認為這解釋了為什么我在插入提交時看到差異。 如果這是對的,那么我只需要知道如何設置自動提交。 默認模式必須使用 Spring 或 SQL Server jdbc 驅動程序更改(我使用的是 4.2,現在使用的是 8.2.0.jre8)。

更新 2

為什么某些其他進程可以在存儲過程完成之前看到對 mytempTable 的插入很重要? 因為在生產存儲過程中,它執行插入,調用某個服務(我相信從該行中選擇數據並將數據插入另一個表),然后 sp waitfor數據出現在服務插入的表中。 所以,在服務看不到insert的情況下,存儲過程掛起,等待服務插入到另一個表中。

我認為解決方案是不使用顯式事務,而讓 SQL Server 默認為自動提交。 不幸的是,這也意味着如果存儲過程出現問題,則不會回滾。 但鑒於存儲過程和服務是我無法更改的第三方組件,我想這是我唯一的選擇。 仍然想知道為什么 Spring Boot 1.5 和 2.x 或 JDBC 驅動程序之間的行為不同。

更新 3

事實證明,Spring Boot 1.5 和 2.x 或 JDBC 驅動程序版本之間的行為沒有區別。 也就是說,直到事務完成后才會發生插入。 我觀察到行為差異的原因與我在舊項目中使用 Spring Boot 1.5 進行測試有關,而舊項目是一個復合項目,與我的 Spring Boot 2 不同,它具有兩個數據源和兩個事務管理器。 x項目。 不知道為什么會在舊項目中立即發生插入,但確實如此。

無論如何,查看 SQL Server 日志,我可以確認無論 Spring/JDBC 版本如何,它都會在自動提交模式打開時立即插入。

如果執行存儲過程遵循標准實體操作的“事務-后寫”模式,那么正常行為是 SQL 語句排隊直到事務完成。

Spring Data 存儲庫默認是事務性的,因此即使在您的測試中沒有顯式@Transactional(transactionManager="transactionManager")事務也在運行。

https://vladmihalcea.com/a-beginners-guide-to-jpahibernate-flush-strategies/ (假設您在這里使用 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
    }   
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM