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

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

Este es el objeto de conexión:

 private static Connection conn = null; 

Tiene solo una instancia (singleton).

Además, tengo métodos que ejecutan consultas, como la búsqueda de un usuario en el archivo db:

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

Este método usa el objeto estático Connection . Mi pregunta es, ¿es seguro mi uso en el hilo estático Connection objeto Connection ? ¿O puede causar problemas cuando muchos usuarios llaman al método searchUser ?

¿Mi uso en el subproceso estático Connection Connection es seguro?

¡Absolutamente no!

De esta forma, 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 del hilo no es su único problema, la pérdida de recursos también es su otro problema. Mantiene una única conexión abierta durante toda la vida de la aplicación. La base de datos promedio recuperará la conexión siempre que se haya abierto durante un tiempo prolongado, que generalmente está entre 30 minutos y 8 horas, dependiendo de la configuración de DB. Entonces, si su aplicación web se ejecuta más tiempo que eso, la conexión se pierde y ya no podrá ejecutar consultas.

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

Siempre debe adquirir y cerrar la conexión, la statement y el conjunto de resultados en el ámbito más corto posible , preferiblemente dentro del mismo bloque try-with-resources como donde está 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 ResultSet aquí. Si todavía no está en Java 7, utilice un bloque try-finally en el que cierre manualmente los recursos que se pueden cerrar en el orden inverso al que los adquirió.

Si te preocupa conectar el rendimiento, entonces deberías usar la agrupación de conexiones. Esto está incorporado en muchos servidores de aplicaciones Java EE e incluso servletcontainers barebones como Tomcat lo admite. Simplemente cree un origen de datos JNDI en el servidor y deje que su aplicación web lo tome como DataSource . De forma transparente, ya es un grupo de conexiones.

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 conexión, ¿cómo debo recuperarla?
  • ¿Estoy utilizando la agrupación de conexiones JDBC?
  • Mostrar JDBC ResultSet en HTML en la página JSP usando el patrón MVC y DAO
  • DAO tutorial con JDBC

Si solo está ejecutando Select consultas (el searchUser suena como solo seleccionar datos) no habrá problemas, aparte de la contención de hilos.

Por lo que yo sé, una Connection solo puede manejar una consulta a la vez, por lo que al usar una sola instancia, esencialmente serializará el acceso a la base de datos. Pero esto no necesariamente significa que siempre es seguro acceder a una base de datos como esta en un entorno de múltiples hilos. Aún podría haber problemas si los accesos simultáneos se entrelazan.