Pregunta

¿Cuál es la mejor manera de administrar una conexión de base de datos en un servlet de Java?

Actualmente, simplemente abro una conexión en la función init () y luego la cierro en destroy () .

Sin embargo, me preocupa que " permanentemente " mantener una conexión de base de datos podría ser algo malo.

¿Es esta la forma correcta de manejar esto? Si no, ¿cuáles son las mejores opciones?

edite: para aclarar un poco más: he intentado simplemente abrir / cerrar una nueva conexión para cada solicitud, pero con las pruebas he visto problemas de rendimiento debido a la creación de demasiadas conexiones.

¿Hay algún valor en compartir una conexión a través de múltiples solicitudes? Las solicitudes para esta aplicación son casi todas " solo lectura " y llegar con bastante rapidez (aunque los datos solicitados son bastante pequeños).

¿Fue útil?

Solución

Realmente no estoy de acuerdo con el uso de Commons DBCP. Realmente deberías remitirte al contenedor para administrar la agrupación de conexiones por ti.

Ya que está usando los Servlets de Java, eso implica ejecutarse en un contenedor de Servlets, y todos los contenedores de Servlets principales con los que estoy familiarizado brindan administración de grupos de conexiones (la especificación de Java EE puede incluso requerirlo). Si resulta que su contenedor usa DBCP (como lo hace Tomcat), genial, de lo contrario, solo use lo que su contenedor proporcione.

Otros consejos

Como todos dicen, necesitas usar un grupo de conexiones. ¿Por qué? ¿Que pasa? Etc.

Lo que está mal con tu solución

Lo sé porque también pensé que alguna vez fue una buena idea. El problema es doble:

  1. Todas las hebras (las solicitudes de servlet se sirven con una secuencia por cada una) compartirán la misma conexión. Por lo tanto, las solicitudes se procesarán de una en una. Esto es muy lento, incluso si te sientas en un solo navegador y te apoyas en la tecla F5. Inténtalo: esto suena de alto nivel y abstracto, pero es empírico y comprobable.
  2. Si la conexión se interrumpe por algún motivo, no se volverá a llamar al método init (porque el servlet no se sacará de servicio). No intente manejar este problema poniendo un try-catch en el doGet o doPost, porque entonces estará en el infierno (como si no se lo pidiera).
  3. Contrariamente a lo que uno podría pensar, no tendrá problemas con las transacciones, ya que el inicio de la transacción se asocia con el hilo y no solo con la conexión. Puede que me equivoque, pero como de todos modos esta solución es mala, no se preocupe.

Por qué grupo de conexiones

Los grupos de conexiones te ofrecen muchas ventajas, pero sobre todo solucionan los problemas de

  1. Hacer una conexión de base de datos real es costoso. El grupo de conexiones siempre tiene algunas conexiones adicionales y te ofrece una de ellas.
  2. Si las conexiones fallan, el grupo de conexiones sabe cómo abrir una nueva
  3. Muy importante: cada hilo tiene su propia conexión. Esto significa que los hilos se manejan donde deberían estar: en el nivel de base de datos. Los DB son súper eficientes y pueden manejar solicitudes concurrentes con facilidad.
  4. Otras cosas (como la ubicación centralizada de cadenas de conexión JDBC, etc.), pero hay millones de artículos, libros, etc. sobre esto

Cuándo obtener una conexión

En algún lugar de la pila de llamadas iniciada en su delegado de servicio (doPost, doGet, doDisco, lo que sea) debe obtener una conexión y luego debe hacer lo correcto y devolverlo en un bloque final. Debo mencionar que el arquitecto principal de C # dijo una vez que debería usar los bloques finalmente 100 veces más que los bloques catch . Palabras más verdaderas nunca habladas ...

Qué grupo de conexiones

Estás en un servlet, por lo que debes usar el grupo de conexiones que proporciona el contenedor. Su código JNDI será completamente normal, excepto por cómo obtiene la conexión. Que yo sepa, todos los contenedores de servlets tienen grupos de conexión.

Algunos de los comentarios sobre las respuestas anteriores sugieren el uso de una API de grupo de conexiones en particular. Su WAR debería ser portátil y " simplemente desplegar. & Quot; Creo que esto es básicamente incorrecto. Si utiliza el grupo de conexiones que proporciona su contenedor, su aplicación se podrá implementar en contenedores que abarquen múltiples máquinas y todas esas cosas sofisticadas que proporciona la especificación de Java EE. Sí, los descriptores de implementación específicos del contenedor deberán escribirse, pero esa es la forma de EE, mon.

Un comentarista menciona que ciertos grupos de conexiones proporcionados por el contenedor no funcionan con los controladores JDBC (él / ella menciona Websphere). Eso suena totalmente inverosímil y ridículo, así que probablemente sea cierto. Cuando suceda algo así, arroja todo lo que se supone que debes hacer " En la basura y haz lo que puedas. Para eso nos pagan, a veces :)

Utilizaría Commons DBCP . Es un proyecto de Apache que administra el grupo de conexiones por ti.

Simplemente obtendrías tu conexión en tu doGet o doPost ejecutando tu consulta y luego cerrarías la conexión en un bloque final. (con.close () simplemente lo devuelve al grupo, en realidad no lo cierra).

DBCP puede administrar los tiempos de espera de conexión y recuperarse de ellos. La forma en que está haciendo las cosas actualmente si su base de datos se cae por un período de tiempo, tendrá que reiniciar su aplicación.

¿Estás agrupando tus conexiones? Si no es así, probablemente debería reducir la sobrecarga de abrir y cerrar sus conexiones.

Una vez que esté fuera del camino, solo mantén la conexión abierta todo el tiempo que sea necesario, como sugirió John.

La mejor manera, y actualmente estoy buscando en Google una mejor hoja de referencia, es usar grupos.

Al inicializar, creas un grupo que contiene X cantidad de objetos de conexión SQL a tu base de datos. Almacene estos objetos en algún tipo de lista, como ArrayList. Cada uno de estos objetos tiene un booleano privado para 'isLeased', un tiempo largo para el último uso y una conexión. Siempre que necesite una conexión, solicite una de la agrupación. La agrupación le dará la primera conexión disponible, verificando la variable isLeased, o creará una nueva y la agregará a la agrupación. Asegúrese de establecer la marca de tiempo. Una vez que haya terminado con la conexión, simplemente devuélvala al grupo, que establecerá isLeased en false.

Para evitar que las conexiones permanezcan en la base de datos, puede crear un subproceso de trabajo que ocasionalmente pasará por el grupo y ver cuándo fue la última vez que se utilizó una conexión. Si ha durado lo suficiente, puede cerrar esa conexión y eliminarla del grupo.

Los beneficios de usar esto, es que no tiene largos tiempos de espera esperando que un objeto Connection se conecte a la base de datos. Sus conexiones ya establecidas se pueden reutilizar tanto como desee. Y podrá establecer la cantidad de conexiones según el grado de ocupación de su aplicación.

Solo debe mantener abierta una conexión de base de datos durante el tiempo que la necesite, lo que dependerá de lo que esté haciendo dentro del alcance de sus métodos doGet / doPost .

Combínalo.

Además, si está haciendo JDBC en bruto, puede buscar algo que lo ayude a administrar Connection, PreparedStatement, etc. A menos que tenga muy apretado " ligereza " " Los requisitos, por ejemplo, usar el soporte JDBC de Spring, van a simplificar mucho su código, y no están obligados a usar ninguna otra parte de Spring.

Vea algunos ejemplos aquí:

http://static.springframework.org/spring /docs/2.5.x/reference/jdbc.html

Un grupo de conexión asociado con una fuente de datos debería hacer el truco. Puede obtener la conexión de la fuente de datos en el método de solicitud de servlet ( doget / dopost , etc.).

dbcp, c3p0 y muchos otros grupos de conexiones pueden hacer lo que está buscando. Mientras está agrupando conexiones, es posible que desee agrupar estados de cuenta y estados de preparación; Además, si eres un entorno READ HEAVY como indicaste, es posible que desees almacenar algunos de los resultados utilizando algo como ehcache.

BR,
~ A

Por lo general, encontrará que la apertura de conexiones por solicitud es más fácil de administrar. Eso significa que en el método doPost () o doGet () de su servlet.

Abrirlo en el init () lo pone a disposición de todas las solicitudes y ¿qué sucede cuando tiene solicitudes simultáneas?

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top