2013-07-22 11 views
15

Mi chiedo se il codice seguente utilizza correttamente le risorse try-with.Java implicita try-with-resources

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

Gli argomenti non sono importanti, l'unica cosa importante è:

  • new QueryBuilder().build(); restituisce un PreparedStatement.

Capisco perfettamente che rs sarà chiuso, ma sarà il PreparedStatement essere chiuso anche, e in caso affermativo, per quale motivo? Perché il ResultSet si chiude o a causa delle try-with-resources?

risposta

19

PreparedStatement#close() chiude automaticamente qualsiasi set di risultati associato, ma il contrario non è vero perché le istruzioni sono riutilizzabili dopo che i set di risultati sono stati chiusi.

sguardo al javadoc di ResultSet#close():

Nota: un oggetto ResultSet viene automaticamente chiusa dal oggetto Statement che lo ha generato quando l'oggetto Statement è chiuso

E poi Statement#close():

Nota: Quando un oggetto Statement viene chiuso, viene chiuso anche l'oggetto ResultSet corrente, se ne esiste uno.

Questo utilizzo sembra molto scadente a me:

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

Se eseguita abbastanza volte vi saranno perdite di tutti i cursori disponibili, perché i cursori sono associati con la non Statement con ResultSet.

Quindi, per chiudere il sottostante PreparedStatement con try-with-resources statement, basta dichiarare all'interno del try dichiarazione:

Un'istruzione try-con-risorse è parametrizzato con le variabili (dette risorse) inizializzate prima dell'esecuzione del blocco try e chiuso automaticamente.

Guardate this answer from assylias, dichiarare il PreparedStatement così come ResultSet all'interno dell'istruzione try.

Poiché non si sta cercando una perdita di memoria , ma una perdita di risorse. La memoria di PreparedStatement verrà raccolta alla fine e la memoria verrà liberata, poiché non viene più referenziata dopo l'esecuzione del metodo dato il modo in cui è inizializzata, tuttavia, le risorse in attesa di Statement non vengono chiuse.

2

Come affermato correttamente, rs verrà chiuso.Ciò significa che il metodo close() verrà invocato su rs. Quindi la dichiarazione try-with-ressource non chiude esplicitamente lo PreparedStatement nel tuo caso.

Se è chiuso altrimenti (nel contesto della rs.close()) è un po 'difficile da dire senza conoscere l'attuazione ;-)

EDIT

Come @TheNewIdiot correttamente scoperto, la tua PreparedStatement vinto' essere chiuso

9

È possibile includere diverse risorse nel tentativo, e saranno tutti chiusi - che è necessaria se si desidera che il PreparedStatement da chiudere:

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

ho avuto che (e avremo di nuovo ora), ma stavo cercando di evitare tw o dichiarazioni diverse. – skiwi

+0

+1 Mi hai battuto in questo modo :-) –

+0

@skiwi In realtà trovo di dividerlo in due dichiarazioni più leggibili, non meno. – assylias

3

Secondo la documentazione here - tryResourceClose, come ho letto, è specifico per le risorse che sono declared.

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

lettura, più in basso si vede:

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) 
) { 

suggerisco la risposta corretta a voi problema è il seguente:

try{ 
    PreparedStatement statement = new QueryBuilder(connection, tableName(), getPaths(), searchQuery()) 
     .add(constraint).build(); 
    ResultSet rs = statement.executeQuery()) 
}