La conexión la deberias mantener abierta mientras usas el ResultSet, asi que el esquema asi como lo tienes no es muy fiable. Y las conexiones a base de datos NUNCA deben dejarse en manos del Garbage Collector, NUNCA

.
Lo habitual es un pseudo-codigo tal que asi
Código:
Connection theConnection = null;
try
{
theConnection = // obtener conexion
theConnection.setAutoCommit(false);
... // Trabajar con conexion
theConnection.commit();
}
catch(Exception e)
{
if(theConnection!=null)
{
try
{
theConnection.rollback()
}
catch(SQLException e)
{
// Informar de error haciendo rollback
// BDD podría quedar inconsistente así
// que es un error GRAVE
}
}
}
finally
{
// Aqui cerramos los result set, statements
// o demas objetos dependientes de la conexion
// Siempre dentro de su propio try/catch, como
// el de la conexion
if(theConnection!=null)
{
try
{
theConnection.close()
}
catch(SQLException e)
{
// Informar de error cerrando conexion
// La conexión podría quedar abierta así
// que es un error GRAVE
}
}
}
Este codigo incluye tratamiento de transacciones, que a veces se puede obviar (si haces solo un select, por ejemplo). Y lo habitual es copiar todos los resultados del ResultSet en un vector, cerrar el ResultSet, cerrar la conexión y despues devolver el Vector (o List). Esa es la forma más segura y con el codigo de arriba bien escrito, no se te queda una conexión o resultset abierto de ninguna forma.
En una aplicación web que tiene que estar ejecutandose 24h al dia sin parar y recibiendo muchas peticiones con posibles fallos temporales en la red etc... es muy importante hacerlo como toca o acabas creando demasiadas conexiones, dejando cursores abiertos o similares y entonces pum
Nota: El código de arriba lo he hecho de cabeza, asi que no es de extrañar que haya algun error por el que no compile o así, pero tampoco voy a hacerlo todo