10

現在、Hibernate を使用して mysql データベースに情報を挿入する Web サービスがあります。この情報の一部は、別の「インポート」アプリケーションで処理する必要があります。このアプリケーションを Web サービスからトリガーする必要はありません。そのため、Web サービスは Web サービスに依存しておらず、その逆も同様です。

「インポート」アプリケーションからデータベースの変更 (具体的には挿入) を「リッスン」してから、アクションの実行を開始する方法はありますか。トリガーを調べましたが、これらはアプリケーションの Hibernate セッションの変更に対してのみ機能し、「外部」の変更に対しては機能しないようです。

編集*

要するに、私がしたい答えです。データベース/テーブル自体を変更しない Java アプリケーションから、(任意のソースからの) mysql データベース/テーブルへの変更を監視することは可能ですか?

バウンティの更新*

Java アプリケーションを使用して MySQL テーブル/データベースに加えられた変更を監視する方法を説明できる人に賞金を授与します。変更を監視する Java アプリケーションは、変更を適用するアプリケーションではありません。変更のソースは何でもかまいません。

4

6 に答える 6

11

データベースに追加のテーブルとトリガーを作成することを気にせず、監視するJavaアプリケーションがトリガーを具体的に受け取るのではなくデータベースをポーリングする必要があると仮定すると、このようなことはかなり簡単に達成できると思います。

監視したいテーブルが次のようなものであると仮定します。

CREATE TABLE ToMonitor ( id INTEGER PRIMARY KEY, value TEXT );

次に、変更を追跡するテーブルと、そのテーブルにデータを入力するトリガーを作成します。

CREATE TABLE InsertedRecords( value TEXT );
CREATE TRIGGER trig AFTER INSERT ON account
FOR EACH ROW INSERT INTO InsertedRecords( value ) VALUES ( NEW.value );

これにより、ToMonitor で発生するすべての挿入が InsertedRecords テーブルに取り込まれます。

次に、監視アプリを定期的に設定しSELECT * from InsertedRecords、適切なアクションを実行してから、記録を消去するだけです。InsertedRecords

編集: C/C++ コーディングを少し気にしない場合は、こちらの手順に従って、監視アプリケーションをトリガーするカスタム SQL 関数を作成し、その SQL 関数を内部から呼び出すこともできます。作成したトリガー。

于 2012-07-14T19:25:25.697 に答える
5

mysqlバイナリログを読むことができます。ここでいくつかの情報を見つけることができます。Java パーサー別のパーサーがありますが、未完成としてマークされています) また、別の言語 (たとえば、perl ) を使用して同様のパーサーを探し、それらを Java で書き直すこともできます。mysql-proxy
もご覧ください。

于 2012-07-14T19:03:51.910 に答える
3

テーブル'table1'の変更を監視したいとします。

CREATE TABLE `table1` (
    `id` INT(10) NOT NULL AUTO_INCREMENT,
    `value` VARCHAR(50) NULL DEFAULT NULL,
    PRIMARY KEY (`id`)
)
COLLATE='latin1_swedish_ci'
ENGINE=InnoDB
AUTO_INCREMENT=10;

上記は、自動インクリメントである「id」列を含む「table1」を作成するためのクエリです。

変更を保存するために別のテーブルを作成します。クエリを以下に示します

CREATE TABLE `changes` (
    `id` INT(10) NOT NULL AUTO_INCREMENT,
    `changes` VARCHAR(200) NULL DEFAULT '0',
    `change_time` TIMESTAMP NULL DEFAULT NULL,
    `tablename` VARCHAR(50) NULL DEFAULT NULL,
    `changed_id` VARCHAR(10) NULL DEFAULT NULL,
    PRIMARY KEY (`id`)
)
COLLATE='latin1_swedish_ci'
ENGINE=InnoDB
AUTO_INCREMENT=21;

ここで、最初のテーブルにトリガーを作成します。つまり、'table1'クエリを以下に示します。

delimiter |
create trigger trg_table1 AFTER INSERT ON table1
FOR EACH ROW BEGIN
DECLARE lastid INT DEFAULT 0;
SELECT max(id) INTO lastid from table1;
insert into changes values(null,'insert',now(),'table1',lastid);
end;
|
delimiter ;

これで、「table1」に何かを挿入しようとすると、その詳細が変更テーブルに自動的に挿入されます。変更テーブルの変更は、変更のタイプを示します。つまり、insert、updateなどchange_timeは、変更が発生する時刻を示します。tablenameは、変更が発生するテーブルを示します。changed_idは、「table1」に新しく挿入された行のIDを示します。

次に、「changes」テーブルから継続的に読み取るJavaプログラムを作成します。'changes'テーブルの新しいエントリは、データベースに何かが起こったことを意味します。'changes'テーブルの各レコードから、挿入操作が行われたテーブルを理解できます。そして、これに基づいて、適切なアクションを実行できます。適切な操作を実行した後、その行を「変更」テーブルから削除します。

データベース内のテーブルごとにトリガーを作成できます(上記のように)...'changes'テーブルの'tablename'列から、どのテーブルで挿入が発生したかを理解できます。

于 2012-07-17T14:33:32.710 に答える
3

あなたが尋ねたことではないことはわかっています(したがって、これは適切な答えではありません)が、「DBにアプリに通知させる」という考えを捨てることを検討すると、アプリ間の通信にJMSを使用するのに最適なケースになります.

変更を開始したアプリは、2 番目のアプリケーションによってサブスクライブされた JMS トピックにメッセージを発行できます。最初にデータベースを変更すると、トピックにメッセージが表示されます。次に、この新しいイベントを見て、それに応じて行動します。2 番目のアプリがデータベースに到達する必要がないように、メッセージで差分を公開することもできます。

データベースを「ハッキング」してデータを保存する以上のことを行うことでこれに対処することには少し反対です. エコシステムに 3 番目のアプリを追加することを想像してください。2 番目のアプリで行ったことを複製する必要がありますが、今度は 3 番目のアプリを複製する必要があります。手順を文書化していないと、道に迷う可能性があります。

これら 2 つのアプリ間で JMS サーバーを使用するだけの場合は、このトピックをリッスンするだけの 3 つ目のアプリを将来確実に追加できます (データベースへの書き込みアクセス権がある場合は、新しいメッセージを発行します)。アプリは、そこに別のアプリがあることを知る必要さえありません。データベースでもありません。

于 2012-07-17T08:12:03.980 に答える
2

Q4M のようなキューイング ソリューションを使用することもできますが、あなたの状況ではやり過ぎかもしれません。しかし、次のことができます。

MySQL データベースで、挿入先のテーブルにタイムスタンプ列を追加します。「インポート」アプリケーションでは、java.util.timer または cron などの外部スケジューラを使用します。これらのいずれかを使用して、タイムスタンプ列が null である挿入テーブルを読み取るタスクをトリガーします。それらの行に対して適切なアクションを実行し、タイムスタンプ列に値を設定します。NULL タイム スタンプを持つ行がない場合、新しい挿入はありません。シンプルですが、うまくいきます。

パフォーマンス上の理由から、タイムスタンプ列にインデックスを追加することができます。

于 2012-07-14T19:37:23.083 に答える