我成功地在AUTO_SERVER模式下使用H2數據庫,以便透明地在網絡上的多個桌面客戶端之間共享數據庫文件。 這樣一個服務器在客戶端和所有其他客戶端從tcp服務器讀取選出。使用H2數據庫服務器如何將更改通知給客戶端(JMS消息傳送)
我缺少的是客戶端或服務器如何通知所有其他桌面客戶端數據庫中的某些內容已更改。 現在我正在使用JGroups渠道讓所有客戶互相交流,但這是另一個失敗點,另一個與H2並行運行的領導者選舉算法。
沒有其他方法嗎? 我已閱讀了某些數據庫支持的JMS(Java消息服務Java API)。任何提示H2?
感謝
編輯:
下面的代碼是當前的答案的適應,如果我第一次開始發件人(設置ARGS爲「發件人」),他連接的服務器的H2數據庫,然後在遠程機器上執行Receiver(將args設置爲「receiver」),並將它們作爲客戶端連接。
然而只有服務器收到通知,客戶端不會收到任何東西。
這從我目前所知道的情況來看是有意義的:只在服務器上調用觸發器,在客戶端或服務器上調用從客戶端或服務器調用的用戶定義函數,但不在所有連接到的客戶端(和服務器)數據庫。
那麼是否有一種方法可以調整以下方式來通知所有連接的數據庫更改實例?
import java.io.File;
import java.sql.*;
import java.util.concurrent.atomic.AtomicLong;
import org.h2.tools.TriggerAdapter;
public class TestSimpleDB2
{
public static void main(String[] args) throws Exception
{
//final String url = "jdbc:h2:mem:test;multi_threaded=true";
final String url = "jdbc:h2:" + File.separator + "mnt/testdir/PlanIGS" + File.separator
+ "persondb;create=true;AUTO_SERVER=TRUE;multi_threaded=true";
Connection conn = DriverManager.getConnection(url);
Statement stat = conn.createStatement();
boolean isSender = false;
args = new String[]
{
"sender"
};
for (String arg : args)
{
if (arg.contains("receiver"))
{
System.out.println("receiver starting");
isSender = false;
}
else if (arg.contains("sender"))
{
System.out.println("sender starting");
isSender = true;
}
}
if (isSender)
{
stat.execute("create alias wait_for_change for \""
+ TestSimpleDB2.class.getName()
+ ".waitForChange\"");
stat.execute("create table test(id identity)");
stat.execute("create trigger notifier "
+ "before insert, update, delete, rollback "
+ "on test call \""
+ TestSimpleDB2.Notifier.class.getName() + "\"");
Thread.sleep(1000);
for (int i = 0; i < 10; i++)
{
System.out.println("Sender: I change something...");
stat.execute("insert into test values(null)");
Thread.sleep(2000);
}
}
else
{
new Thread()
{
public void run()
{
try
{
Connection conn = DriverManager.getConnection(url);
for (int i = 0; i < 10; i++)
{
conn.createStatement().execute(
"call wait_for_change(100000)");
System.out.println("Receiver: event received");
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
}.start();
}
conn.close();
}
static AtomicLong modCount = new AtomicLong();
public static void waitForChange(long maxWaitMillis)
{
synchronized (modCount)
{
try
{
modCount.wait(maxWaitMillis);
}
catch (InterruptedException e)
{
// ignore
}
}
}
public static class Notifier extends TriggerAdapter
{
public void fire(Connection conn, ResultSet oldRow, ResultSet newRow)
throws SQLException
{
modCount.incrementAndGet();
synchronized (modCount)
{
modCount.notifyAll();
}
}
}
}
確定所有客戶端都連接到同一個數據庫嗎?我可能會用'create = false'來替換'create = true'來確保。另外,你可以檢查文件'persondb.lock.db'中的內容嗎?它是一個純文本文件,應該包含服務器地址和一個隨機密鑰(以及其他一些數據)。 –