2010-02-27 11 views
5

Sono bloccato in qualche punto in cui ho bisogno di ottenere modifiche al database in un codice Java. La richiesta è di ottenere qualsiasi record aggiornato, aggiunto, cancellato in qualsiasi tabella di db; dovrebbe essere riconosciuto dal programma Java. Come potrebbe essere implementato JMS? o un thread Java?polling del database utilizzando Java

Aggiornamento: Grazie ragazzi per il vostro supporto in realtà sto utilizzando Oracle come DB e workshop Weblogic 10.3. In realtà voglio ricevere gli aggiornamenti da una tabella in cui ho solo permesso di leggere, quindi ragazzi, cosa suggerite tutti. Non riesco ad aggiornare il DB. L'unica cosa che posso fare è leggere il DB e se c'è qualche cambiamento nella tabella devo ottenere l'informazione/notifica che certe righe di dati sono state aggiunte/cancellate o aggiornate.

+0

L'aggiornamento è copypasted dal dupe: http://stackoverflow.com/questions/2363697/database-polling-using-java-closed – BalusC

+0

Oracle Data Change Capture, forse? –

+0

Solo se si lavora con un DB Oracle: [http://stackoverflow.com/questions/21177723/how-to-call-java-class-from-oracle-trigger](http://stackoverflow.com/ domande/21177723/how-to-call-java-class-from-oracle-trigger) –

risposta

8

A meno che il database non possa inviare un messaggio a Java, è necessario disporre di una discussione che esegue il polling.

Un modello migliore e più efficiente sarebbe quello che attiva gli eventi sui cambiamenti. Un database che ha Java in esecuzione all'interno (ad esempio, Oracle) potrebbe farlo.

+1

Che cos'è un esempio di un prodotto che genera eventi sulle modifiche? Non l'ho mai visto. Sembra un trigger del database, ma invece di eseguire SQL (es: PL/SQL), esegue una classe Java che implementa alcune interfacce. –

+0

Correggere e invece di scrivere il proprio sistema di threading, utilizzare Java's Executors, che renderà la vita molto più semplice. –

3

Abbiamo ottenuto questo risultato nella nostra azienda aggiungendo trigger a tabelle di database che chiamano un eseguibile per emettere un messaggio Tib Rendezvous, che viene ricevuto da tutte le applicazioni Java interessate.

Tuttavia, il modo ideale per fare questo IMHO è quello di avere il controllo completo di tutte le scritture del database a livello di applicazione e di notificare a questo punto tutte le parti interessate (tramite multi-cast, Tib, ecc.). In realtà, questo non è sempre possibile se si dispone di un numero di sistemi diversi.

+0

+1 per "controllo completo di tutte le scritture del database a livello di applicazione". Un servizio dovrebbe possedere e controllare i propri dati. – duffymo

+2

Il punto principale di un DBMS è fornire accesso ai dati per più applicazioni in modo uniforme. Ciò include applicazioni che sono ancora non pensate e molto meno implementate. Evita la possibilità che una singola applicazione abbia il controllo di tutti i dati. Oppure, se si produce una singola applicazione che esegue tutte le operazioni del database, si utilizza il 'DBMS reale' come motore di archiviazione e la 'singola applicazione' come interfaccia DBMS per tutte le applicazioni. Ma è vicino al ridondante. –

+0

@Jonathan Leffer - No, non necessariamente. Il punto principale di un DBMS è la persistenza. Se il futuro, senza che le applicazioni richiedano dati, possono passare attraverso il proprietario per ottenerlo. Ecco di cosa si tratta.Questa è la visione di Werner Vogels, CTO di Amazon: http://queue.acm.org/detail.cfm?id=1142065 – duffymo

6

Lo facciamo eseguendo il polling del DB utilizzando un'attività del timer EJB. In sostanza, abbiamo uno stato archiviato che aggiorniamo quando abbiamo elaborato quella riga.

Quindi il thread del timer EJB chiama una procedura che recupera le righe contrassegnate come "non trattate".

Sporco, ma anche molto semplice e robusto. Soprattutto, dopo un incidente o qualcosa del genere, può ancora riprendere da dove si è schiantato senza troppa complessità.

Lo svantaggio è il carico sprecato sul DB e anche il tempo di risposta sarà limitato (probabilmente sono necessari secondi).

1

Suppongo che tu stia parlando di una situazione in cui tutto può aggiornare un tavolo. Se per qualche motivo stai invece parlando di una situazione in cui solo l'applicazione Java aggiornerà la tabella che è diversa. Se stai usando solo Java puoi inserire questo codice nel tuo DAO o EJB facendo l'aggiornamento (è molto più pulito che usare un trigger in questo caso).

1

Un modo alternativo per eseguire questa operazione è incanalare tutte le chiamate di database tramite un'API del servizio Web o forse un'API JMS, che esegue le chiamate effettive al database. I processi possono registrarsi lì per ottenere una notifica di un aggiornamento del database.

1

In effetti, dipende dal fatto che il database in questione lo supporti. Dovrai anche prendere in considerazione il sovraccarico. Molti degli inserimenti/aggiornamenti significano anche molte notifiche e il tuo codice Java deve gestirli in modo coerente, altrimenti si riempirà di bolle.

Se il modello dati lo consente, è sufficiente aggiungere una colonna aggiuntiva contenente un timestamp che viene aggiornato su ogni inserimento/aggiornamento. La maggior parte dei DB principali supporta un aggiornamento automatico della colonna su ogni inserimento/aggiornamento.Non so quale server di DB che si sta utilizzando, quindi darò solo un esempio MySQL mirato:

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) 
) 

In questo modo non c'è bisogno di preoccuparsi di inserire/aggiornamento del lastupdate da soli. Puoi semplicemente fare un INSERT INTO mytable (somevalue) VALUES (?) o UPDATE mytable SET somevalue = ? WHERE id = ? e il DB farà la magia.

dopo aver verificato che l'ora del server DB e il tempo di applicazione Java sono gli stessi, si può solo sparare un thread in background (utilizzando Timer con TimerTask, o ScheduledExecutorService con Runnable o Callable), che fa più o meno questo:

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; 

Aggiornamento: come da aggiornamento della domanda risulta che non si ha alcun controllo sul DB. Bene, allora non hai molte opzioni buone/efficienti. Aggiorna l'intero elenco nella memoria Java con tutti i dati dal DB senza verificare/confrontare le modifiche (probabilmente il modo più veloce) o generare dinamicamente una query SQL basata sui dati correnti che esclude i dati correnti dai risultati.

0

Abbiamo un requisito simile. Nel nostro caso abbiamo un sistema legacy che non vogliamo influenzare negativamente le prestazioni sulla tabella delle transazioni esistente.

Ecco la mia proposta:

  1. Un nuovo tavolo di lavoro con PK di transazione e inserire timestamp
  2. Una nuova tabella di controllo che ha le stesse colonne della tabella delle transazioni + revisione colonne
  3. trigger sul tavolo transazione scaricare tutti gli inserimenti/aggiornamenti/eliminazioni in una tabella di controllo
  4. Processo Java per eseguire il polling della tabella di lavoro, partecipare alla tabella di controllo, pubblicare l'evento in questione ed eliminarlo dalla tabella di lavoro.

La domanda è: cosa usi per il polling? Il quarzo è eccessivo? Come si può ridimensionare la frequenza di polling in base al carico attuale del DB?

Problemi correlati