2010-02-27 12 views
5

Estoy atascado en algún momento en el que necesito obtener cambios en la base de datos en un código Java. La solicitud es obtener cualquier registro actualizado, agregado o eliminado en cualquier tabla de db; debe ser reconocido por el programa Java. ¿Cómo podría implementarse JMS? o un hilo de Java?sondeo de base de datos utilizando Java

Actualización: Gracias a todos por su apoyo, en realidad estoy usando Oracle como DB y el taller Weblogic 10.3. En realidad, quiero obtener las actualizaciones de una tabla en la que solo he leído el permiso, chicos, ¿qué sugieres? No puedo actualizar la base de datos. Lo único que puedo hacer es leer el DB y, si hay algún cambio en la tabla, debo obtener la información/notificación de que se han agregado/eliminado o actualizado ciertas filas de datos.

+0

La actualización está copiada del truco: http://stackoverflow.com/questions/2363697/database-polling-using-java-closed – BalusC

+0

Oracle's Change Data Capture, tal vez? –

+0

Solo si está trabajando con Oracle DB: [http://stackoverflow.com/questions/21177723/how-to-call-java-class-from-oracle-trigger](http://stackoverflow.com/ preguntas/21177723/how-to-call-java-class-from-oracle-trigger) –

Respuesta

8

A menos que la base de datos pueda enviar un mensaje a Java, deberá tener un hilo que sondee.

Un modelo mejor y más eficiente sería aquel que dispara eventos en los cambios. Una base de datos que tenga Java funcionando dentro (por ejemplo, Oracle) podría hacerlo.

+1

¿Cuál es un ejemplo de un producto que dispara eventos en cambios? Nunca he visto eso. Suena como un disparador de base de datos, pero en lugar de ejecutar SQL (es decir, PL/SQL), ejecuta una clase Java que implementa alguna interfaz. –

+0

Corrija, y en lugar de escribir su propio sistema de subprocesamiento, utilice los ejecutores de Java, que le simplificarán la vida. –

3

Hemos logrado esto en nuestra empresa agregando activadores a las tablas de la base de datos que llaman a un ejecutable para emitir un mensaje Tib Rendezvous, que es recibido por todas las aplicaciones Java interesadas.

Sin embargo, la forma ideal de hacer esto en mi humilde opinión es tener el control total de todas las escrituras de bases de datos a nivel de aplicación y notificar a cualquier parte interesada en este punto (a través de multidifusión, Tib, etc.). En realidad, esto no siempre es posible cuando tienes varios sistemas dispares.

+0

+1 para "control completo de todas las escrituras de base de datos en el nivel de aplicación". Un servicio debe poseer y controlar sus propios datos. – duffymo

+2

El punto principal de un DBMS es proporcionar acceso a los datos para múltiples aplicaciones de una manera uniforme. Esto incluye aplicaciones que aún no se han pensado, y mucho menos implementadas. Impide la posibilidad de que una sola aplicación controle todos los datos. O bien, si produce una sola aplicación que realiza todas las operaciones de la base de datos, entonces está utilizando el 'DBMS real' como motor de almacenamiento y la 'única aplicación' como la interfaz DBMS para todas las aplicaciones. Pero está cerca de ser redundante. –

+0

@Jonathan Leffer - No, no necesariamente. El punto principal de un DBMS es la persistencia. Si las aplicaciones futuras e impensadas necesitan datos, pueden pasar por el propietario para obtenerlos. De eso se tratan los servicios.Esa es la opinión de Werner Vogels, CTO de Amazon: http://queue.acm.org/detail.cfm?id=1142065 – duffymo

6

Lo hacemos al sondear la base de datos utilizando una tarea del temporizador EJB. En esencia, tenemos un estado archivado que actualizamos cuando procesamos esa fila.

Así que el hilo del temporizador EJB llama a un procedimiento que toma las filas que están marcadas como "sin tratar".

Sucio, pero también muy simple y robusto. Especialmente, después de un bloqueo o algo así, todavía puede retomar desde donde se estrelló sin demasiada complejidad.

La desventaja es la carga desperdiciada en la base de datos, y también el tiempo de respuesta será limitado (probablemente requiera unos segundos).

1

Supongo que está hablando de una situación en la que todo puede actualizar una tabla. Si por alguna razón estás hablando de una situación en la que solo la aplicación Java estará actualizando la tabla, eso es diferente. Si solo está usando Java, puede poner este código en su DAO o EJB haciendo la actualización (es mucho más limpio que usar un desencadenador en este caso).

1

Una forma alternativa de hacerlo es canalizar todas las llamadas a la base de datos a través de una API de servicio web, o quizás una API JMS, que realiza las llamadas a la base de datos real. Los procesos podrían registrarse allí para recibir una notificación de actualización de la base de datos.

1

Depende de si la base de datos en cuestión lo admite. También deberá tener en cuenta los gastos generales. Muchas inserciones/actualizaciones también significan muchas notificaciones y tu código Java tiene que manejarlas consistentemente, de lo contrario surgirán.

Si el modelo de datos lo permite, simplemente agregue una columna adicional que contiene una marca de tiempo que se actualiza en cada inserción/actualización. La mayoría de los DB principales admiten una actualización automática de la columna en cada inserción/actualización.No sé qué servidor de base de datos que está utilizando, así que voy a dar solamente un ejemplo-dirigida de MySQL:

CREATE TABLE mytable (
    id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, 
    somevalue VARCHAR(255) NOT NULL, 
    lastupdate TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, 
    INDEX (lastupdate) 
) 

De esta manera usted no tiene que preocuparse acerca de cómo insertar/actualizar el lastupdate mismo. Puede hacer un INSERT INTO mytable (somevalue) VALUES (?) o UPDATE mytable SET somevalue = ? WHERE id = ? y el DB hará la magia.

Después de asegurarse que el tiempo del servidor de base de datos y el tiempo de aplicación Java son los mismos, sólo puede disparar un subproceso en segundo plano (utilizando Timer con TimerTask o ScheduledExecutorService con Runnable o Callable), que hace más o menos esto:

Date now = new Date(); 
statement = connection.prepareStatement("SELECT id FROM mytable WHERE lastupdate BETWEEN ? AND ?"); 
statement.setDate(1, this.lastTimeChecked); 
statement.setDate(2, now); 
resultSet = statement.executeQuery(); 
while (resultSet.next()) { 
    // Handle accordingly. 
} 
this.lastTimeChecked = now; 

Actualización: según la actualización de la pregunta, resulta que no tiene control sobre la base de datos. Bueno, entonces no tienes muchas opciones buenas/eficientes. O bien actualice la lista completa en la memoria Java con todos los datos de DB sin verificar/comparar los cambios (probablemente la manera más rápida), o genere dinámicamente una consulta SQL basada en los datos actuales que excluyen los datos actuales de los resultados.

0

Tenemos un requisito similar. En nuestro caso, tenemos un sistema heredado que no queremos afectar negativamente el rendimiento en la tabla de transacciones existente.

Aquí es mi propuesta:

  1. Una nueva mesa de trabajo con pk a la transacción e insertar fecha y hora
  2. Una nueva tabla de auditoría que tiene mismas columnas como las columnas de tabla de transacciones + auditoría
  3. Trigger en la tabla de transacción a volcar todo insertar/actualizar/eliminar en una tabla de auditoría
  4. Proceso Java para sondear la tabla de trabajo, unirse a la tabla de auditoría, publicar el evento en cuestión y eliminarlo de la tabla de trabajo.

Pregunta es: ¿Qué se utiliza para las encuestas? Es el exceso de cuarzo? ¿Cómo se puede reducir la frecuencia de sondeo en función de la carga de DB actual?

Cuestiones relacionadas