Đây là Main.java
:Có cách nào tốt hơn để sử dụng try-with-resource và PreparedStatement không?
package foo.sandbox.db;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class Main {
public static void main(String[] args) {
final String SQL = "select * from NVPAIR where name=?";
try (
Connection connection = DatabaseManager.getConnection();
PreparedStatement stmt = connection.prepareStatement(SQL);
DatabaseManager.PreparedStatementSetter<PreparedStatement> ignored = new DatabaseManager.PreparedStatementSetter<PreparedStatement>(stmt) {
@Override
public void init(PreparedStatement ps) throws SQLException {
ps.setString(1, "foo");
}
};
ResultSet rs = stmt.executeQuery()
) {
while (rs.next()) {
System.out.println(rs.getString("name") + "=" + rs.getString("value"));
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
Và đây là DatabaseManager.java
package foo.sandbox.db;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Statement;
/**
* Initialize script
* -----
* CREATE TABLE NVPAIR;
* ALTER TABLE PUBLIC.NVPAIR ADD value VARCHAR2 NULL;
* ALTER TABLE PUBLIC.NVPAIR ADD id int NOT NULL AUTO_INCREMENT;
* CREATE UNIQUE INDEX NVPAIR_id_uindex ON PUBLIC.NVPAIR (id);
* ALTER TABLE PUBLIC.NVPAIR ADD name VARCHAR2 NOT NULL;
* ALTER TABLE PUBLIC.NVPAIR ADD CONSTRAINT NVPAIR_name_pk PRIMARY KEY (name);
*
* INSERT INTO NVPAIR(name, value) VALUES('foo', 'foo-value');
* INSERT INTO NVPAIR(name, value) VALUES('bar', 'bar-value');
*/
public class DatabaseManager {
/**
* Class to allow PreparedStatement to initialize parmaters inside try-with-resource
* @param <T> extends Statement
*/
public static abstract class PreparedStatementSetter<T extends Statement> implements AutoCloseable {
public PreparedStatementSetter(PreparedStatement pstmt) throws SQLException {
init(pstmt);
}
@Override
public void close() throws Exception {
}
public abstract void init(PreparedStatement pstmt) throws SQLException;
}
/* Use local file for database */
private static final String JDBC_CONNECTION = "jdbc:h2:file:./db/sandbox_h2.db;MODE=PostgreSQL";
static {
try {
Class.forName("org.h2.Driver"); // Init H2 DB driver
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* @return Database connection
* @throws SQLException
*/
public static Connection getConnection() throws SQLException {
return DriverManager.getConnection(JDBC_CONNECTION, "su", "");
}
}
Tôi đang sử dụng cơ sở dữ liệu H2 vì đơn giản vì nó là một tập tin dựa một trong đó là dễ dàng để tạo và thử nghiệm trên.
Vì vậy, mọi thứ hoạt động và tài nguyên được dọn sạch như mong đợi, tuy nhiên tôi chỉ cảm thấy có thể có cách sạch hơn để đặt tham số PreparedStatement
từ bên trong khối try-with-resources (và tôi không muốn sử dụng lồng nhau) thử/nắm bắt các khối như những cái nhìn 'lúng túng'). Có lẽ đã tồn tại một lớp trợ giúp trong JDBC mà chỉ thực hiện điều này, nhưng tôi đã không thể tìm ra được nó.
Tốt hơn là với hàm lambda để khởi tạo PreparedStatement
nhưng vẫn yêu cầu phân bổ đối tượng AutoCloseable
để nó có thể nằm trong tài nguyên thử.
Bản sao có thể có của [Làm cách nào tôi nên sử dụng try-with-resources với JDBC?] (Http://stackoverflow.com/questions/8066501/how-should-i-use-try-with-resources-with-jdbc) –
Tôi hy vọng sẽ tìm cách để thực hiện init cho PreparedStatement bằng cách sử dụng lambda thay vì một cá thể lớp, gần giống như truyền các tham số vào PreparedStatement. – AlexC