2013-07-22 20 views
15

Tôi tự hỏi liệu mã sau có sử dụng các tài nguyên thử một cách chính xác hay không.Java ngầm thử với các nguồn lực

try (ResultSet rs = new QueryBuilder(connection, tableName(), getPaths(), searchQuery()).add(constraint).build().executeQuery()) { 
    while (rs.next()) { 
     beans.add(createBean(rs)); 
    } 
} 

Các đối số là không quan trọng, điều quan trọng duy nhất là:

  • new QueryBuilder().build(); trả về một PreparedStatement.

Tôi hoàn toàn hiểu rằng rs sẽ bị đóng, nhưng PreparedStatement cũng sẽ bị đóng và nếu có, vì lý do gì? Bởi vì ResultSet đóng hoặc vì tài nguyên thử?

Trả lời

19

PreparedStatement#close() sẽ tự động đóng mọi tập hợp kết quả được liên kết nhưng ngược lại không đúng bởi vì các câu lệnh có thể sử dụng được sau khi bộ kết quả của chúng được đóng lại.

Nhìn vào javadoc của ResultSet#close():

Lưu ý: Một đối tượng ResultSet được tự động đóng lại bởi các đối tượng Statement mà tạo ra nó khi mà đối tượng Statement được đóng

Và sau đó Statement#close():

Lưu ý: Khi một đối tượng Statement được đóng lại, đối tượng ResultSet hiện tại của nó, nếu một đối tượng tồn tại, cũng bị đóng.

sử dụng này trông rất crappy với tôi:

ResultSet rs=conn.createStatement().executeQuery(); 

Nếu thực hiện đủ thời gian nó sẽ bị rò rỉ tất cả các con trỏ có sẵn, bởi vì con trỏ có liên quan đến Statement không phải với ResultSet.

Do đó để đóng tiềm ẩn PreparedStatement với try-with-resources statement, chỉ cần khai báo nó trong try tuyên bố:

Một câu lệnh try-với-nguồn lực là tham số với các biến số (được gọi là nguồn lực) được khởi tạo trước khi thực hiện khối thử và tự động đóng.

Nhìn vào this answer from assylias, khai báo PreparedStatement cũng như ResultSet bên trong tuyên bố try.

Vì bạn không tìm kiếm lỗ hổng bộ nhớ , mà là rò rỉ tài nguyên. Bộ nhớ của PreparedStatement sẽ được thu thập cuối cùng và bộ nhớ của nó được giải phóng, vì nó không được tham chiếu nữa sau khi thực hiện phương pháp của bạn theo cách nó được khởi tạo, tuy nhiên, các tài nguyên do Statement giữ lại không bị đóng.

2

Như bạn đã nêu chính xác, rs sẽ bị đóng.Điều này có nghĩa là phương thức close() sẽ được gọi trên rs. Vì vậy, câu lệnh try-with-ressource không khai báo một cách rõ ràng PreparedStatement trong trường hợp của bạn.

Nếu nó đóng cửa khác (trong ngữ cảnh của rs.close()) là loại khó để nói mà không biết thực hiện ;-)

EDIT

Như @TheNewIdiot một cách chính xác phát hiện ra, PreparedStatement won của bạn' t được đóng lại.

9

Bạn có thể bao gồm một số nguồn lực trong lần thử, và tất cả họ sẽ đóng cửa - đó là cần thiết nếu bạn muốn PreparedStatement phải đóng cửa:

try (PreparedStatement ps = new QueryBuilder(connection, tableName(), getPaths(), searchQuery()).add(constraint).build(); 
     ResultSet rs = ps.executeQuery();) { 
    while (rs.next()) { 
     beans.add(createBean(rs)); 
    } 
} 
+0

Tôi đã có mà (và sẽ có một lần nữa bây giờ), nhưng tôi đã cố gắng tránh tw o các tờ khai khác nhau. – skiwi

+0

+1 Bạn đánh bại tôi với nó :-) –

+0

@skiwi Tôi thực sự tìm thấy tách nó trong hai báo cáo dễ đọc hơn, không ít hơn. – assylias

3

Theo tài liệu here - tryResourceClose, như tôi đọc nó, nó dành riêng cho các tài nguyên là declared.

The try-with-resources statement is a try statement that declares one or more resources.

Đọc tiếp tục xuống bạn thấy:

You may declare one or more resources in a try-with-resources statement. The following example retrieves the names of the files packaged in the zip file zipFileName and creates a text file that contains the names of these files:

try (
     java.util.zip.ZipFile zf = 
     new java.util.zip.ZipFile(zipFileName); 
    java.io.BufferedWriter writer = 
     java.nio.file.Files.newBufferedWriter(outputFilePath, charset) 
) { 

Tôi đề nghị câu trả lời đúng để bạn phát hành được những điều sau đây:

try{ 
    PreparedStatement statement = new QueryBuilder(connection, tableName(), getPaths(), searchQuery()) 
     .add(constraint).build(); 
    ResultSet rs = statement.executeQuery()) 
} 
Các vấn đề liên quan