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 trylà 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 DriverManagertrong 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.PGSimpleDataSourcebằng một triển khai DataSourcephù 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 DataSourcetriển khai không cần phải đóng, bởi vì nó không bao giờ được mở ra. A DataSourcekhô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 DataSourcechỉ đơ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: Connectionvà PreparedStatement. Bên trong tryxác định ResultSettà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 ở đó, ResultSettài nguyên sẽ tự động bị đóng (nếu nó tồn tại, không phải là null). Sau đó, PreparedStatementsẽ được đóng lại, và cuối cùng Connectionlà đó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 trycuộ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 trycâ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, ResultSetnó 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à ResultSetquá. 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 ResultSetlà AutoCloseablevà 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ó