在沒有連接池的情況下在單一連接中使用PreparedStatements時,開發人員經常面臨創建新語句的困境每個DML/SQL 操作的實例或重複使用現有實例。在這裡,我們分析了兩種方法的優缺點,並探索了一種提高效率和可擴展性的替代解決方案。
第一種方法涉及為每個操作重新建立一個新的PreparedStatement實例,確保每個語句都沒有先前執行的任何殘留參數或狀態。然而,這種方法可能會導致效能下降,尤其是在多執行緒環境中。
第二種方法透過重複使用單一PreparedStatement實例來解決這些問題,並在每次執行之前清除其參數。雖然這種方法效率更高,但缺乏第一種方法的優雅和簡單性。
執行多個 DML/SQL 操作的更最佳化解決方案是採用批次處理。該技術涉及收集一系列操作並將它們作為對資料庫的單一請求來執行。批次顯著減少了建立和關閉多個PreparedStatement實例的開銷。
<code class="java">public void executeBatch(List<Entity> entities) throws SQLException { try ( Connection connection = dataSource.getConnection(); PreparedStatement statement = connection.prepareStatement(SQL); ) { for (Entity entity : entities) { statement.setObject(1, entity.getSomeProperty()); // ... statement.addBatch(); } statement.executeBatch(); } }</code>
在執行批次數量過多的場景下,限制批次大小可以進一步提升效能。
<code class="java">public void executeBatch(List<Entity> entities) throws SQLException { try ( Connection connection = dataSource.getConnection(); PreparedStatement statement = connection.prepareStatement(SQL); ) { int i = 0; for (Entity entity : entities) { statement.setObject(1, entity.getSomeProperty()); // ... statement.addBatch(); i++; if (i % 1000 == 0 || i == entities.size()) { statement.executeBatch(); // Execute every 1000 items. } } } }</code>
透過在同一個方法區塊中使用try-with-resources 語句來取得和關閉連線以及PreparedStatement,可以緩解執行緒安全性問題:
<code class="java">try ( Connection connection = dataSource.getConnection(); PreparedStatement statement = connection.prepareStatement(SQL); ) { // ... }</code>
在交易場景中,停用連線上的自動提交,僅在所有批次完成後提交事務,以確保資料一致性。
<code class="java">public void executeBatch(List<Entity> entities) throws SQLException { try (Connection connection = dataSource.getConnection()) { connection.setAutoCommit(false); try (PreparedStatement statement = connection.prepareStatement(SQL)) { // ... try { connection.commit(); } catch (SQLException e) { connection.rollback(); throw e; } } } }</code>
透過利用批次執行並遵守正確的連接管理技術,開發人員可以利用PreparedStatements的強大功能,同時最大限度地提高效率和可擴展性,即使在多執行緒環境中也是如此。
以上是ReadyStatement重用:重用還是不重用?深入探討效率和可擴展性的詳細內容。更多資訊請關注PHP中文網其他相關文章!