2016-12-11 117 views
1

我已經在後端Web服務中使用JOOQ一段時間了。在許多這些服務中,在將數據保存到數據庫之後(或者更好地說,在成功提交數據之後),我們通常希望向卡夫卡寫入關於持久記錄的一些消息,以便其他服務知道這些事件。JOOQ中的提交鉤子

我基本上在尋找的是:有沒有辦法讓我用JOOQ的DSLContext對象註冊post-commit鉤子或回調,所以我可以在事務成功提交時運行一些代碼?

我知道了ExecuteListenerExecuteListenerProvider接口的,但據我可以告訴void end(ExecuteContext ctx)方法(這是所謂的生命週期使用的結束)提交事務時不叫。它在每個查詢之後都被調用。

下面是一個例子:讓我相信這不是爲commit鉤子

Pre insert. 
End method triggered. 
Post insert. 

public static void main(String[] args) throws Throwable { 
    Class.forName("org.postgresql.Driver"); 
    Connection connection = DriverManager.getConnection("<url>", "<user>", "<pass>"); 
    connection.setAutoCommit(false); 

    DSLContext context = DSL.using(connection, SQLDialect.POSTGRES_9_5); 
    context.transaction(conf -> { 
     conf.set(new DefaultExecuteListenerProvider(new DefaultExecuteListener() { 
      @Override 
      public void end(ExecuteContext ctx) { 
       System.out.println("End method triggered."); 
      } 
     })); 

     DSLContext innerContext = DSL.using(conf); 
     System.out.println("Pre insert."); 
     innerContext.insertInto(...).execute(); 
     System.out.println("Post insert."); 
    }); 

    connection.close(); 
} 

這似乎總是打印。

有沒有可能是一個JOOQ大師,可以告訴我,如果有支持JOOQ中的提交鉤子?如果是這樣,請指出我正確的方向?

+1

嘗試組合'TransactionProvider','RecordListener'和'ExecuteListener'。您可以在本地線程中捕獲c/u/d記錄,並根據最外層事務的完成情況丟棄或發佈。 –

回答

1

ExecuteListener SPI是聽單查詢執行,即這個生命週期:

innerContext.insertInto(...).execute(); 

這是不是你要找的東西。相反,你應該實施你自己的TransactionProvider(可能委託給jOOQ的DefaultTransactionProvider)。然後你可以在實際提交邏輯之前實現你想要的任何邏輯。

請注意,jOOQ 3.9還將提供一個新的TransactionListener SPI(see #5378)以方便此操作。

+0

從'DSLContext'中獲取'TransactionProvider',投射它,然後附加一個回調可能有點麻煩,但是我已經設法使它正常工作。非常感謝Lukas!順便說一句,期待在3.9中新的'TransactionListener',但我注意到你只能設置監聽器。爲什麼不允許在運行時添加它們? –

+0

@MichaeldeJong是的,該回調解決方案將很好地工作。爲什麼你認爲你將無法在運行時添加監聽器? –

+0

也許我錯了(可能),但看看[代碼](https://github.com/jOOQ/jOOQ/commit/4e1f458e6c1f0e1e7e695f84890956fb8cc30ecd#diff-5b0bc82019c25f8bf90f60d2b2177b17R806),每次你調用這個方法時,它會取代任何之前設置。我知道它是關於'TransactionListenerProvider'而不是'TransactionListener'的,但是如果你想在事務中添加/註冊一個,你需要首先獲取任何提供者的註冊信息,然後將新的信息添加到一個調整大小的數組中,然後調用'set(TransactionListenerProvider ...)'方法吧? –