¿Es seguro utilizar una instancia estática de java.sql.Connection en un sistema multiproceso?

Resuelto Asher Saban asked hace 12 años • 2 respuestas

Estoy ejecutando una aplicación web en Tomcat. Tengo una clase que maneja todas las consultas de base de datos. Esta clase contiene el Connectionobjeto y los métodos que devuelven los resultados de la consulta.

Este es el objeto de conexión:

private static Connection conn = null;

Tiene una sola instancia (singleton).

Además, tengo métodos que ejecutan consultas, como buscar un usuario en la base de datos:

public static ResultSet searchUser(String user, String pass) throws SQLException

Este método utiliza el Connectionobjeto estático. Mi pregunta es, ¿es Connectionseguro mi uso en subprocesos de objetos estáticos? ¿O puede causar problemas cuando muchos usuarios llamen al searchUsermétodo?

Asher Saban avatar Feb 24 '12 16:02 Asher Saban
Aceptado

¿Es seguro mi uso en subprocesos de objetos de conexión estáticos?

¡Absolutamente no!

De esta manera, la conexión se compartirá entre todas las solicitudes enviadas por todos los usuarios y, por lo tanto, todas las consultas interferirán entre sí. Pero la seguridad de los subprocesos no es su único problema, la fuga de recursos también es el otro problema. Mantienes una única conexión abierta durante toda la vida útil de la aplicación. La base de datos promedio recuperará la conexión cada vez que haya estado abierta durante demasiado tiempo, lo que suele oscilar entre 30 minutos y 8 horas, según la configuración de la base de datos. Entonces, si su aplicación web se ejecuta durante más tiempo, la conexión se perderá y ya no podrá ejecutar consultas.

Este problema también se aplica cuando esos recursos se mantienen como una staticvariable que no es de instancia de una instancia de clase que se reutiliza varias veces.

Siempre debes adquirir y cerrar la conexión, la declaración y el conjunto de resultados en el alcance más corto posible , preferiblemente dentro del mismo try-with-resourcesbloque donde estás ejecutando la consulta de acuerdo con el siguiente modismo JDBC:

public User find(String username, String password) throws SQLException {
    User user = null;

    try (
        Connection connection = dataSource.getConnection();
        PreparedStatement statement = connection.prepareStatement("SELECT id, username, email FROM user WHERE username=? AND password=md5(?)");
    ) {
        statement.setString(1, username);
        statement.setString(2, password);

        try (ResultSet resultSet = statement.executeQuery()) {
            if (resultSet.next()) {
                user = new User();
                user.setId(resultSet.getLong("id"));
                user.setUsername(resultSet.getString("username"));
                user.setEmail(resultSet.getString("email"));
            }
        }
    }       

    return user;
}

Tenga en cuenta que no debe devolver un ResultSetaquí. Debe leerlo inmediatamente y asignarlo a una clase que no sea JDBC y luego devolverlo, para que pueda ResultSetcerrarse de forma segura.

Si aún no está en Java 7, utilice un try-finallybloque en el que cierre manualmente los recursos que se pueden cerrar en el orden inverso al que los adquirió. Puede encontrar un ejemplo aquí: ¿ Con qué frecuencia se deben cerrar Connection, Statement y ResultSet en JDBC?

Si le preocupa el rendimiento de la conexión, entonces debería utilizar la agrupación de conexiones. Esto está integrado en muchos servidores de aplicaciones Java EE e incluso los contenedores de servlet básicos como Tomcat lo admiten. Simplemente cree una fuente de datos JNDI en el servidor y deje que su aplicación web la obtenga como archivo DataSource. De forma transparente ya es un grupo de conexiones. Puede encontrar un ejemplo en el primer enlace de la lista a continuación.

Ver también:

  • ¿Cómo debo conectarme a la base de datos/fuente de datos JDBC en una aplicación basada en servlet?
  • Cuando mi aplicación pierde la conexión, ¿cómo debo recuperarla?
  • ¿Estoy utilizando la agrupación de conexiones JDBC?
  • Muestre JDBC ResultSet en HTML en la página JSP usando el patrón MVC y DAO
  • Tutorial DAO con JDBC
BalusC avatar Feb 24 '2012 13:02 BalusC

Si solo está ejecutando Selectconsultas ( searchUserparece que solo selecciona datos), no habrá problemas, aparte de la contención del hilo.

Hasta donde yo sé, a Connectionsolo puede manejar una consulta a la vez, por lo que al usar una sola instancia esencialmente serializarás el acceso a la base de datos. Pero esto no significa necesariamente que siempre sea seguro acceder a una base de datos como esta en un entorno de subprocesos múltiples. Es posible que aún haya problemas si los accesos simultáneos se entrelazan.

TPete avatar Feb 24 '2012 11:02 TPete