簡體   English   中英

Spring JDBCTemplate 與 Hikari 數據源批量更新行為異步

[英]Spring JDBCTemplate with Hikari datasource batch update behaving asynchronously

我正在開發一個 web 應用程序,我在其中顯示一些用戶可以采取行動的信息。 采取行動后,列表應更新並在網頁中反映這些更改。 我已經讓所有單獨的部分都在工作,但是將它們連接在一起會導致問題。

這里基本上是檢索代碼:

public List<Entry> findEntriesForIdByStatus(Long id, Status status) {

    MapSqlParameterSource paramSource = new MapSqlParameterSource();

    paramSource.addValue("id", id);

    if (null == status) {
        return template.query(FIND_ALL_ENTRIES_QUERY, paramSource, entryResultSetExtractor);
    }

    paramSource.addValue("status", status.getCode());

    List<Entry> entryWithStatus = springJdbcTemplate.query(FIND_ENTRIES_FOR_STATUS_QUERY, 
            paramSource,
            entryResultSetExtractor);

    return equipmentWithStatus;
}

和更新代碼:

@Transactional("myTransactionManager")
public void expire(CustomObject customObj) {
    Timestamp expirationTime = Timestamp.valueOf(dateTimeFactory.now());

    Long id = customObj.getId();
    List<Entry> entryList = customObj.getEntryList();

    SqlParameterSource[] params = new MapSqlParameterSource[entryList.size()];
    for (int i = 0; i < entryList.size(); i++) {
        Entry entry = entryList.get(i);
        MapSqlParameterSource paramSource = new MapSqlParameterSource("id", id)
                .addValue("fieldA", entry.getFieldA())
                .addValue("fieldB", entry.getFieldB())
                .addValue("expirationTime", expirationTime);
        params[i] = paramSource;
    }

    springJdbcTemplate.batchUpdate(EXPIRE_QUERY, params);
}

模板是由 Spring Boot 管理的 SpringJDBCNamedParameterTemplate,數據源是 com.zaxxer.hikari.HikariDataSource 的實例。

在頁面加載並返回正確數據時調用檢索方法。 運行 expire 方法時,正確的記錄過期,兩個方法都執行成功。 最初我使用 excludeMap (rxjs/angular 7) 將它們鏈接在前端,但它不一致。 有時,過期后的檢索會返回,就好像過期沒有發生一樣,有時會。 但是,無論結果如何,如果我刷新頁面,結果將是空的,正如預期的那樣。 我將其切換為在后端鏈接調用以查看它是否有幫助,並且它開始返回結果,就好像過期並沒有一直發生一樣,但是在頁面刷新時,它按預期工作。

這是后端的鏈接:

public @ResponseBody List<Entry> expireEntries(@RequestBody CustomObj customObj) {
    entryService.expire(customObj, WebUtil.getCurrentUser());
    System.out.println(LocalDateTime.now().toString() + ": about to retrieve");
    List<Entry> entries = entryService.findEntriesByStatus(customObj.getId(), Status.NA);
    System.out.println(LocalDateTime.now().toString() + ": it's done retrieving");
    return equips;
}

這些服務幾乎只是調用 DAO,中間沒有太多。 日志記錄 output 類似於以下內容:

沒用

2019-09-19T13:33:50.998:即將刪除
2019-09-19T13:33:51.050:刪除完成
2019-09-19T13:33:51.246:即將檢索
13:33:51.465 [http-nio-8080-exec-3] INFO EntryDAO - 查詢父級 27,狀態 = NA 返回 364,耗時 219 毫秒
13:33:51.466 [http-nio-8080-exec-3] INFO EntryService - 查詢父級 27 和狀態 NA 返回 364
2019-09-19T13:33:51.466:已完成檢索

工作過

2019-09-19T13:38:13.752:即將刪除
2019-09-19T13:38:13.798:刪除完成
2019-09-19T13:38:14.112:即將檢索
13:38:14.120 [http-nio-8080-exec-5] INFO EntryDAO - 查詢父級 27,狀態 = NA 返回 0,耗時 8 毫秒
13:38:14.120 [http-nio-8080-exec-5] INFO EntryService - 查詢父級 27 和狀態 NA 返回 0
2019-09-19T13:38:14.120:已完成檢索

這些是從前端鏈接的時候開始的,但是移動到后端之后,它是相同的,只是“刪除完成”和“即將檢索”的時間更接近,通常在一兩毫秒內。 在更新和檢索之間添加 2 秒睡眠似乎可以解決問題。 我嘗試鎖定行以進行更新並使用 Spring 的 @Transactional 注釋使方法具有事務性,但似乎都沒有幫助。

據我所知,似乎正在觸發批量更新,但 Java 方法在數據庫中實際完成更新之前返回。 因此,當檢索查詢執行時,它會獲取更新前的數據。 有沒有人能夠確認這是這種行為,如果是,有沒有辦法修復它而不僅僅是用 Thread.sleep 破解它?

編輯:這是事務管理器的 bean 定義。

@Bean(name = "myDbProperties")
@Primary
@ConfigurationProperties(prefix = "spring.datasource.mydb")
public DataSourceProperties dbProperties() {
    return new DataSourceProperties();
}

@Primary
@Bean(name = "myDataSource")
@ConfigurationProperties(prefix = "spring.datasource.mydb.configuration")
public DataSource dataSource(@Qualifier("myDbProperties") DataSourceProperties dbProperties) {
    return dbProperties.initializeDataSourceBuilder().build();
}

@Bean
@Primary
@Qualifier("myTransactionManager")
public PlatformTransactionManager loadauthTransactionManager(
        @Qualifier("myDataSource") DataSource datasource) {
    return new DataSourceTransactionManager(datasource);
}

事實證明,這是一個過度思考的案例,解決方案實際上非常簡單。 讀取查詢sysdate between create and delete 結果是介於兩者之間,並且因為查詢發生在由於 sysdate = delete 而返回的任何 sysdate 的最小時間增量結果內。 將其切換到where systimestamp >= create and systimestamp < delete解決了這個問題。

暫無
暫無

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

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