2008-10-27 18 views
25

¿Cuál es la mejor manera de administrar una conexión de base de datos en un servlet de Java?La mejor manera de administrar la conexión de base de datos para 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" aferrado a una conexión de base de datos podría ser algo malo.

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

editar: 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 entre varias solicitudes? Las solicitudes de esta aplicación son casi todas de "solo lectura" y se realizan con bastante rapidez (aunque los datos solicitados son bastante pequeños).

+0

Deberías marcar la pregunta de Jack Leow como correcta. Las cosas J2EE (o como lo llamen en 2009) usan un servidor de aplicaciones por alguna razón ... De todos modos, lo bueno es que si haces lo que estás diciendo arriba con init y destruye, creo que el servlet se acumulará secuencialmente las solicitudes DB, por lo que varios hilos irán despacio (ly). –

+0

Cambiaré la respuesta aceptada ya que la comunidad gobierna :) Sin embargo, desearía que hubiese habido más explicación. Cuando hice esta pregunta hace meses, era novato de toda la escena de "java webapp" y su respuesta realmente no explicaba de qué estaba hablando. –

+0

El problema es que es wiki de la comunidad, por lo que no se otorgan puntos. Voy a escribir una pequeña respuesta a continuación, también. –

Respuesta

14

realidad no estoy de acuerdo con el uso de los Comunes DBCP. En realidad, debe remitir al contenedor para administrar la agrupación de conexiones por usted.

Dado que utiliza Servlets Java, eso implica ejecutarlo en un contenedor Servlet, y todos los principales Servlets con los que estoy familiarizado brindan administración del grupo de conexiones (la especificación Java EE puede incluso requerirlo). Si su contenedor usa DBCP (como lo hace Tomcat), genial, de lo contrario, simplemente use lo que su contenedor le proporcione.

+0

¡Absolutamente! Por el amor de Dios, delegue esto en el contenedor y simplemente implemente una búsqueda JNDI en el recurso. NO HAY NINGUNA razón para estar haciendo esto solo. –

+2

Supongo que depende de cómo se implemente su aplicación. Nos implementamos en muchos servidores de aplicaciones diferentes y es más fácil tratar con DBCP que aprender una forma diferente de configurar pools de conexión para cada servidor de aplicaciones. De cualquier manera está bien, sin embargo. También he tenido algunos servidores de aplicaciones que no funcionan con unidades jdbc (Websphere) – ScArcher2

+2

Estoy de acuerdo con ScArcher2. Prefiero que la aplicación sea independiente y no confíe en la configuración externa para poder ejecutarla. ¡Idealmente uno debería poder desplegar una guerra y estar listo! –

1

Solo debe mantener abierta una conexión de base de datos el tiempo que lo necesite, lo que depende de lo que haga, probablemente dentro del alcance de sus métodos doGet/doPost.

+0

Además, destroy() no se garantiza que se llame –

+0

La aplicación en la que estoy trabajando tiene una solicitud muy frecuente de muchos clientes, ¿no se corre el riesgo de utilizar todas las conexiones de la base de datos? (¿o simplemente crear demasiados para ser rápido?) Solo pido una aclaración, no tratando de refutar tu respuesta. –

+0

Claro, debe usar un grupo de conexiones si quiere que su aplicación se escale. De esta forma tienes el control sobre el máximo. número de conexiones. –

2

¿Estás uniendo tus conexiones? De lo contrario, probablemente deba reducir la sobrecarga de abrir y cerrar sus conexiones.

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

2

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

Al inicializarse, crea un grupo que contiene X cantidad de objetos de conexión SQL a su 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 largo para el tiempo en que se utilizó por última vez y una conexión. Siempre que necesite una conexión, solicita una del grupo. El grupo le dará la primera conexión disponible, verificando la variable isLeased, o creará una nueva y la agregará al grupo. Asegúrese de establecer la marca de tiempo. Una vez que haya terminado con la conexión, simplemente regrésela al grupo, que se configurará como Deficiente a falso.

Para evitar tener conexiones constantemente, ate la base de datos, puede crear un hilo de trabajo que ocasionalmente irá a través del grupo y verá cuándo fue la última vez que se usó una conexión. Si ha sido lo suficientemente largo, puede cerrar esa conexión y eliminarla del grupo.

Las ventajas 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 el número de conexiones según cuán ocupada piense que será su aplicación.

0

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

Al abrirlo en init(), se pone a disposición de todas las solicitudes y ¿qué sucede cuando tiene solicitudes simultáneas?

4

Yo usaría Commons DBCP. Es un proyecto de Apache que administra el grupo de conexiones por usted.

Usted acaba de obtener su conexión en su doGet o doPost ejecutar su consulta y luego cerrar la conexión en un bloque finally. (con.close() simplemente lo devuelve al grupo, en realidad no lo cierra).

DBCP puede gestionar los tiempos de espera de conexión y recuperarse de ellos. De la forma en que actualmente está haciendo las cosas si su base de datos deja de funcionar durante un período de tiempo, tendrá que reiniciar su aplicación.

1

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

dbcp, c3p0 y muchas otras agrupaciones de conexiones pueden hacer lo que usted está buscando. Mientras está agrupando conexiones, es posible que desee agrupar las Declaraciones y las Declaracionesprecisas; Además, si usted es un entorno de LEER PESADO como usted indicó, es posible que desee almacenar en caché algunos de los resultados usando algo como ehcache.

BR,
~ Un

1

Pool it.

Además, si está realizando JDBC sin procesar, podría buscar algo que lo ayude a administrar Connection, PreparedStatement, etc. A menos que tenga requisitos de "ligereza" muy ajustados, con el soporte JDBC de Spring, por ejemplo, se va a simplifica mucho tu código, y no estás obligado a usar ninguna otra parte de Spring.

ver algunos ejemplos aquí:

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

22

Como dice todo el mundo, es necesario utilizar un pool de conexiones. ¿Por qué? ¿Que pasa? Etc.

¿Qué está mal con su solución

sé que esto ya que yo también pensé que era una buena idea en otro tiempo. El problema es doble:

  1. Todos los hilos (las solicitudes servlet se sirven con un hilo por cada uno) compartirán la misma conexión. Por lo tanto, las solicitudes se procesarán de a una por vez. Esto es muy lento, incluso si simplemente te sientas en un solo navegador y te apoyas en la tecla F5. Pruébalo: 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 pondrá fuera de servicio). No trates de manejar este problema colocando un try-catch en doGet o doPost, porque entonces estarás en el infierno (escribiendo un servidor de aplicaciones sin que te pregunten).
  3. Al contrario de lo que se podría pensar, no tendrás problemas con las transacciones, ya que el inicio de la transacción se asocia con el hilo y no solo con la conexión. Podría estar equivocado, pero como esta es una mala solución de todos modos, no te preocupes.

Por qué conjunto de conexiones

piscinas de conexión le dan un montón de ventajas, pero sobre todo los que resuelven los problemas de

  1. Establecimiento de una conexión de base de datos real es costoso. El grupo de conexiones siempre tiene algunas conexiones adicionales y le da uno de esos.
  2. Si las conexiones fallan, el grupo de conexiones sabe cómo abrir una nueva
  3. Muy importante: cada hilo obtiene su propia conexión. Esto significa que el enhebrado se maneja donde debería estar: en el nivel DB. Los DB son muy eficientes y pueden manejar solicitudes concurrentes con facilidad.
  4. Otras cosas (como la centralización de localización de JDBC conectar cuerdas, etc.), pero hay millones de artículos, libros, etc. en este

Cuando para 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 finally. Debo mencionar que el arquitecto principal de C# dijo una vez que debería usar finally bloques 100x más que catch bloques. Palabras más verdaderas nunca hablan ...

Qué piscina

Estás en un servlet, por lo que debe utilizar la agrupación de conexiones del contenedor ofrece conexión. Su código JNDI será completamente normal, excepto por cómo obtiene la conexión. Hasta donde yo sé, todos los contenedores de servlets tienen grupos de conexiones.

Algunos de los comentarios sobre las respuestas anteriores sugieren el uso de una API de grupo de conexión en particular. Tu WAR debería ser portátil y "simplemente implementar". Creo que esto es básicamente incorrecto Si utiliza el grupo de conexiones proporcionado por su contenedor, su aplicación se podrá implementar en contenedores que abarcan varias máquinas y todas esas cosas elegantes que ofrece la especificación de Java EE. Sí, los descriptores de despliegue específicos del contenedor deberán escribirse, pero ese es el modo EE, mon.

Un comentarista menciona que ciertas agrupaciones de conexiones provistas por contenedor no funcionan con controladores JDBC (menciona Websphere). Eso suena totalmente descabellado y ridículo, por lo 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 :)

Cuestiones relacionadas