jdbc查询序列_JDBC –模拟序列
jdbc查詢序列
也許我們每個人在程序員的生活中至少遇到過一次這個問題- 如何模擬數據庫序列? 在下面,您可能會發現我對該問題解決方案的各種了解。
假設我們有一個接口定義了所需的API,用于返回整數序列:
public interface Sequences { int nextValue(String sequenceName) throws SQLException; }并以以下形式實現此API:
class SequencesService implements Sequences { private static final String SQL_QUERY = "SELECT SEQ_NAME, SEQ_VALUE FROM SEQUENCE WHERE SEQ_NAME = ? FOR UPDATE" ; private final DataSource dataSource; SequencesService( final DataSource dataSource) { this .dataSource = dataSource; } @Override public int nextValue( final String sequenceName) throws SQLException { final long threadId = Thread.currentThread().getId(); try ( final Connection connection = dataSource.getConnection()) { connection.setAutoCommit( false ); try ( final PreparedStatement statement = connection.prepareStatement( SQL_QUERY, TYPE_SCROLL_SENSITIVE, CONCUR_UPDATABLE)) { statement.setString( 1 , sequenceName); try ( final ResultSet resultSet = statement.executeQuery()) { System.out.println( String.format( "[%d] - select for update" , threadId)); int nextValue = 1 ; if (resultSet.next()) { nextValue = 1 + resultSet.getInt( 2 ); resultSet.updateInt( 2 , nextValue); resultSet.updateRow(); } else { resultSet.moveToInsertRow(); resultSet.updateString( 1 , sequenceName); resultSet.updateInt( 2 , nextValue); resultSet.insertRow(); } System.out.println( String.format( "[%d] - next val: %d" , threadId, nextValue)); return nextValue; } } finally { System.out.println(String.format( "[%d] - commit" , threadId)); "[%d] - commit" , threadId)); connection.commit(); } } } }您必須原諒我兩件事:) –我添加println的用法是為了生成一些視覺反饋;)并且缺少詳細的解釋說明此解決方案的工作原理;)我只想提一下線索是準備好的語句的處理方式創建并處理結果集:updateRow / moveToInsertRow / insertRow用法;)(有關詳細信息,請參見本文底部的鏈接)。
我編寫了簡單的測試用例來觀察和驗證此代碼,例如:
@Autowired private Sequences sequences; private Callable<Integer> callable() { return () -> { System.out.println(String.format( "[%d] - starting" , Thread.currentThread().getId())); "[%d] - starting" , Thread.currentThread().getId())); return sequences.nextValue( "My Sequence" ); }; } @Test public void test() throws Exception { final ExecutorService executor = Executors.newFixedThreadPool( 3 ); final CompletionService<Integer> completion = new ExecutorCompletionService<>(executor); for ( int i = 0 ; i < 3 ; i++) { completion.submit(callable()); } ????for ( int completed = 1 ; completed <= 3 ; completed++) { final Future<Integer> result = completion.take(); System.out.println(String.format( "Result %d - %d" , completed, result.get())); assertEquals(Integer.valueOf(completed), result.get()); } } 運行上述代碼時,輸??出將如下所示(括號中為線程的ID):
[16] –開始 [18] –開始 [17] –開始 [17] –選擇要更新 [17] –下一個值:1 [17] –提交 [18] –選擇要更新 結果1-1 [18] –下一個值:2 [18] –提交 [16] –選擇要更新 [16] –下一個值:3 [16] –提交 結果2 – 2 結果3 – 3
這段代碼僅用于演示目的:) –如果您想在項目中做類似的事情,則可能更愿意將其用于ex。 Spring Framework的@Transactional批注,而不是手動的事務處理,甚至JPA都將這項工作委托給JDBC。 例如,在Hibernate中,您可以這樣進行操作:
import org.hibernate.Session; ... entityManager.unwrap(Session. class ) .doReturningWork(connection -> { ... code derived from my example ... });甜點的幾個鏈接:
- 更新ResultSet對象(JDBC)中的行
- 在ResultSet對象(JDBC)中插入行
- 聲明式事務管理和使用@Transactional (Spring Framework)
- ReturningWork(JPA,Hibernate)
…,我差點忘了;)– GitHub存儲庫保存了我所有的這篇文章的代碼經驗
翻譯自: https://www.javacodegeeks.com/2019/08/jdbc-emulating-sequence.html
jdbc查詢序列
創作挑戰賽新人創作獎勵來咯,堅持創作打卡瓜分現金大獎總結
以上是生活随笔為你收集整理的jdbc查询序列_JDBC –模拟序列的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 怎么更换轮播图片(怎么更换轮播图片背景)
- 下一篇: junit junit_穿越JUnit流