2011-09-02 25 views
12

Duplicar posibles:
when to close Connection, Statement, PreparedStatement and ResultSet in JDBCBuenas prácticas: JDBC de conexión

He escrito un simple envoltorio para una conexión JDBC y funciona pero quiero mejorarlo con las mejores prácticas como sea posible. Básicamente tiene métodos como open(), close(), isOpened(), select(), insert(), update(), delete() y batch(). Por simplicidad, solo publicaré aquí los primeros 4 métodos.

public class Query{ 
    private Connection con; 
    private PreparedStatement ps; 
    private ResultSet rs; 

    //Database.open() returns a Connection ready to use 
    public void open (Database database) throws DatabaseException, SQLException{ 
     if (!isOpened()){ 
      con = database.open(); 
     } 
    } 

    public void close() throws SQLException{ 
     if (isOpened()){ 
      if (ps != null) ps.close(); 
      con.close(); 
      con = null; 
     } 
    } 

    public boolean isOpened(){ 
     return con != null; 
    } 

    //The query string is the query without the word "select" and can use placeholders (?) 
    //The args param it's just an array owith the values of this placeholders 
    public ResultSet select (String query, Object[] args) throws SQLException{ 
     if (ps != null) ps.close(); 

     if (isOpened()){ 
      ps = con.prepareStatement ("select " + query); 
      if (args != null){ 
       for (int i=0; i<args.length; i++){ 
        ps.setObject (i+1, args[i]); 
       } 
      } 
      rs = ps.executeQuery(); 
     } 

     return rs; 
    } 
} 

Notas:

  • El mismo objeto de consulta pueden ser reutilizados, para la apertura y el cierre de ejemplo ella, y después de abrir de nuevo.
  • No estoy cerrando la conexión para cada consulta, sólo estoy cerrando la declaración preparada (esto es correcto o que puede dejar el preparado declaración abrió debido a que el objeto de conexión de la cerrará?)
  • Cuando cerrar el Connection, todos los PreparedStatement sy sus ResultSet s también están cerrados, ¿verdad?

Uso:

Database database; 

//Database initialization 

Query query = new Query(); 


query.open (database); 

ResultSet rs = query.select ("* from user where name=?", new String[]{ "MyName" }); 
doSomethingWithResult1 (rs); 

//Connection is not closed here 

ResultSet rs = query.select ("coordx from point where coordy=? and coordz=?", new Float[]{ 0.1, 0.2 }); 
doSomethingWithResult2 (rs); 

query.close(); 


query.open (database); 

ResultSet rs = query.select ("* from user where name=?", new String[]{ "MyName" }); 
doSomethingWithResult1 (rs); 

//Connection is not closed here 

ResultSet rs = query.select ("coordx from point where coordy=? and coordz=?", new Float[]{ 0.1, 0.2 }); 
doSomethingWithResult2 (rs); 

query.close(); 

¿Qué opinas? ¿Debo cerrar y abrir la conexión después de cada consulta? ¿Puedo dejar abierto PreparedStatement después de cada consulta en la misma conexión? Es un buen diseño?

+7

Cerrar y volver a abrir las conexiones para cada consulta es una mala idea. Hacer una conexión es realmente, muy caro. – bdares

+1

¿Entonces puedo dejar abierto PreparedStatement o debería cerrarlo para cada consulta? –

+0

Puede dejar todo abierto hasta que termine de usar la base de datos. Al cerrar una conexión se rastreará y cerrará todas las cosas (declaraciones, resultados) que generó. – bdares

Respuesta

12

Tiene que cerrar PreparedStatement después de que haya terminado con él y antes de crear uno nuevo en la misma conexión. He tenido problemas graves porque no cerré PreparedStatements. Resultó que en el servidor de la base de datos había recursos asignados que solo se liberaban después de una llamada explícita de PreparedStatement.close().

Como comentó bdares, la conexión debe abrirse y cerrarse con la menor frecuencia posible.

1

mejor paectise es: utilizar un solo objeto de conexión para todas las consultas si esas queires son parte del mismo método y para cada consulta cerrar el PreparedStatement, después de su uso.

1

Utilice un grupo de conexiones. Entonces no sigues creando

+0

El grupo de conexiones se crea cuando inicializo la base de datos. La conexión que devuelve mi método database.open() es una conexión de un grupo porque estoy usando un origen de datos. –

5

La agrupación de conexiones

Utilice un pool de conexiones. Cada transacción en su aplicación obtendrá una conexión de este grupo, ejecutará todas las cosas necesarias, revertirá o confirmará y cerrará la conexión (devolverá la conexión al grupo).

Podría darle Objeto Query una referencia al grupo y abrir recibirá la conexión y se cerrará cerrándolo (devolviéndolo de hecho).

Declaración preparada

intente volver a utilizar su declaración preparada para consultas similares. De esta forma, el DB reutilizará el plan de consulta anterior y será más rápido. Tiene mucho sentido si está ejecutando muchas consultas de la misma forma.

¿Cómo?

  • Mantener última PS abierta
  • Si cierra la conexión o lo que sea, cerrarla
  • si se consulta por la misma cadena de consulta que la reutilización anterior, el PS se salvó
  • si no es el mismo cadena de consulta ... ciérrela y cree una nueva