Như những người khác đã nói, mã của bạn về cơ bản là chính xác mặc dù bên ngoài try
là không cần thiết. Dưới đây là một vài suy nghĩ.
DataSource
Các câu trả lời khác ở đây là đúng và tốt, chẳng hạn như Câu trả lời được chấp nhận bởi bpgergo. Nhưng không ai trong số cho thấy việc sử dụng DataSource
, thường được khuyến nghị sử dụng DriverManager
trong Java hiện đại.
Vì vậy, để hoàn thiện, đây là một ví dụ hoàn chỉnh lấy ngày hiện tại từ máy chủ cơ sở dữ liệu. Cơ sở dữ liệu được sử dụng ở đây là Postgres . Bất kỳ cơ sở dữ liệu khác sẽ làm việc tương tự. Bạn sẽ thay thế việc sử dụng org.postgresql.ds.PGSimpleDataSource
bằng một triển khai DataSource
phù hợp với cơ sở dữ liệu của bạn. Việc triển khai có thể được cung cấp bởi trình điều khiển cụ thể của bạn hoặc nhóm kết nối nếu bạn đi theo tuyến đường đó.
Một DataSource
triển khai không cần phải đóng, bởi vì nó không bao giờ được mở ra. A DataSource
không phải là tài nguyên, không được kết nối với cơ sở dữ liệu, vì vậy nó không giữ kết nối mạng cũng như tài nguyên trên máy chủ cơ sở dữ liệu. A DataSource
chỉ đơn giản là thông tin cần thiết khi thực hiện kết nối với cơ sở dữ liệu, với tên hoặc địa chỉ mạng của máy chủ cơ sở dữ liệu, tên người dùng, mật khẩu người dùng và các tùy chọn khác nhau mà bạn muốn chỉ định khi cuối cùng kết nối được thực hiện. Vì vậy, DataSource
đối tượng triển khai của bạn không đi vào trong ngoặc đơn thử tài nguyên của bạn.
Thử tài nguyên lồng nhau
Mã của bạn sử dụng đúng các câu lệnh try-with-resource lồng nhau.
Lưu ý trong mã ví dụ bên dưới rằng chúng tôi cũng sử dụng cú pháp try-with-resource hai lần , một cái được lồng bên trong cái kia. Bên ngoài try
định nghĩa hai tài nguyên: Connection
và PreparedStatement
. Bên trong try
xác định ResultSet
tài nguyên. Đây là một cấu trúc mã phổ biến.
Nếu một ngoại lệ được ném từ bên trong và không bị bắt ở đó, ResultSet
tài nguyên sẽ tự động bị đóng (nếu nó tồn tại, không phải là null). Sau đó, PreparedStatement
sẽ được đóng lại, và cuối cùng Connection
là đóng cửa. Các tài nguyên được tự động đóng theo thứ tự ngược lại trong đó chúng được khai báo trong các báo cáo thử tài nguyên.
Mã ví dụ ở đây là quá đơn giản. Như đã viết, nó có thể được thực thi với một câu lệnh try-with-resource duy nhất. Nhưng trong một công việc thực tế, bạn có thể sẽ thực hiện nhiều công việc hơn giữa các cặp try
cuộc gọi lồng nhau . Ví dụ: bạn có thể trích xuất các giá trị từ giao diện người dùng hoặc POJO, sau đó chuyển các giá trị đó để đáp ứng các ?
trình giữ chỗ trong SQL của bạn thông qua các lệnh gọi đến PreparedStatement::set…
các phương thức.
Ghi chú cú pháp
Dấu chấm phẩy
Lưu ý rằng dấu chấm phẩy theo dõi câu lệnh tài nguyên cuối cùng trong ngoặc đơn của tài nguyên thử với là tài nguyên là tùy chọn. Tôi đưa nó vào công việc của mình vì hai lý do: Tính nhất quán và nó có vẻ hoàn chỉnh, và nó giúp việc sao chép một cách dễ dàng hơn mà không phải lo lắng về dấu chấm phẩy cuối dòng. IDE của bạn có thể gắn cờ dấu chấm phẩy cuối cùng là không cần thiết, nhưng không có hại gì khi để nó.
Java 9 - Sử dụng các vars hiện có trong tài nguyên dùng thử
Điểm mới trong Java 9 là sự cải tiến cho cú pháp thử tài nguyên. Bây giờ chúng ta có thể khai báo và điền vào các tài nguyên bên ngoài dấu ngoặc đơn của try
câu lệnh. Tôi chưa thấy điều này hữu ích cho các tài nguyên JDBC, nhưng hãy ghi nhớ nó trong công việc của bạn.
ResultSet
nên tự đóng, nhưng có thể không
Trong một thế giới lý tưởng, ResultSet
nó sẽ tự đóng lại như tài liệu hứa hẹn:
Một đối tượng result Set được tự động đóng khi đối tượng Statement tạo ra nó được đóng lại, được thực thi lại hoặc được sử dụng để lấy kết quả tiếp theo từ một chuỗi nhiều kết quả.
Thật không may, trong quá khứ, một số trình điều khiển JDBC đã thất bại trong việc thực hiện lời hứa này. Kết quả là, nhiều lập trình viên JDBC đã học cách đóng rõ ràng tất cả các tài nguyên JDBC của họ Connection
, bao gồm cả PreparedStatement
, và ResultSet
quá. Cú pháp thử tài nguyên hiện đại đã giúp thực hiện dễ dàng hơn và với mã nhỏ gọn hơn. Lưu ý rằng nhóm Java đã đi sâu vào việc đánh dấu ResultSet
là AutoCloseable
và tôi khuyên chúng ta nên sử dụng điều đó. Việc sử dụng một tài nguyên thử với tất cả các tài nguyên JDBC của bạn làm cho mã của bạn tự ghi lại nhiều tài liệu hơn theo ý định của bạn.
Mã ví dụ
package work.basil.example;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.time.LocalDate;
import java.util.Objects;
public class App
{
public static void main ( String[] args )
{
App app = new App();
app.doIt();
}
private void doIt ( )
{
System.out.println( "Hello World!" );
org.postgresql.ds.PGSimpleDataSource dataSource = new org.postgresql.ds.PGSimpleDataSource();
dataSource.setServerName( "1.2.3.4" );
dataSource.setPortNumber( 5432 );
dataSource.setDatabaseName( "example_db_" );
dataSource.setUser( "scott" );
dataSource.setPassword( "tiger" );
dataSource.setApplicationName( "ExampleApp" );
System.out.println( "INFO - Attempting to connect to database: " );
if ( Objects.nonNull( dataSource ) )
{
String sql = "SELECT CURRENT_DATE ;";
try (
Connection conn = dataSource.getConnection() ;
PreparedStatement ps = conn.prepareStatement( sql ) ;
)
{
… make `PreparedStatement::set…` calls here.
try (
ResultSet rs = ps.executeQuery() ;
)
{
if ( rs.next() )
{
LocalDate ld = rs.getObject( 1 , LocalDate.class );
System.out.println( "INFO - date is " + ld );
}
}
}
catch ( SQLException e )
{
e.printStackTrace();
}
}
System.out.println( "INFO - all done." );
}
}
try (ResultSet rs = ps.executeQuery()) {
vì đối tượng Kết quả được tự động đóng bởi đối tượng Statement đã tạo ra nó