解决 Java 嵌入式 SQL 数据库中的排他关系

Posted

技术标签:

【中文标题】解决 Java 嵌入式 SQL 数据库中的排他关系【英文标题】:Solving an exclusive relationship in a java embedded SQL database 【发布时间】:2014-11-12 09:30:30 【问题描述】:

我正在尝试构建一个需要将数据存储在 SQL 数据库中的 Java 程序,该数据库需要嵌入到我的应用程序中,以便我可以在任何 PC 上执行该应用程序并且数据保持不变。

那么,我的范式如下。

MAIN TABLE 与四个表有四个关系。它们的每一边都是 (0:N),所以一个例子是:

MAIN_TABLE (0:n) ------ (0:n) TABLE_1

TABLE_2、TABLE_3 和 TABLE_4 的例子相同。

直到这里一切正常,当“Main_Table”只能有一个关系时,问题就出现了,即“table_1”或“table_2”或“table_3”或“table_4”。他们永远不可能是其中的两个或更多。为了解决 N:M 关系,引入了“alpha”、“beta”、“gamma”和“lambda”表,其中一个处理每个 TABLE_X 与 MAIN_TABLE 的关系。

有人告诉我使用触发器来检查 MAIN_TABLE 上的一行是否已经与其他三个表有关系,如果为真,则中止插入,如下所示:

DELIMITER $$
CREATE TRIGGER checker1
BEFORE INSERT ON alpha
FOR EACH ROW
BEGIN
  DECLARE count INTEGER;
  SELECT count(MAINTABLEid) INTO count FROM beta WHERE beta.MAINTABLEid= NEW.MAINTABLEid;
  IF count > 0 THEN SIGNAL SQLSTATE '45000' SET message_text = 'THE ROW IS ALREADY CONNECTED TO ANOTHER TABLE.';
  END IF;
  SELECT count(MAINTABLEid) INTO count FROM gamma WHERE gamma.MAINTABLEid= NEW.MAINTABLEid;
  IF count > 0 THEN SIGNAL SQLSTATE '45000' SET message_text = 'THE ROW IS ALREADY CONNECTED TO ANOTHER TABLE.';
  END IF;
  SELECT count(MAINTABLEid) INTO count FROM lambda WHERE lamba.MAINTABLEid= NEW.MAINTABLEid;
  IF count > 0 THEN SIGNAL SQLSTATE '45000' SET message_text = 'THE ROW IS ALREADY CONNECTED TO ANOTHER TABLE.';
  END IF;
END;$$
DELIMITER ;

我尝试使用 Derby 和 HSQL,但它们都不支持“DELIMITER”命令,并且如果不更改分隔符,则无法保存触发器,因为它遇到分号进程停止。

我可以使用哪个数据库来解决这个问题,或者我如何使用 Derby 或 HSQL 来解决这个问题?我的程序将用 Java 编写,数据库应该可以控制几乎所有情况。

提前谢谢你。

【问题讨论】:

【参考方案1】:

经过大量研究,我确定我需要使用 HSQLDB 主要有两个原因: Derby 只允许只有一个 sql 查询的触发器。第二个原因避免创建触发器序列,因为 Derby 也不允许任何 declare 子句。 HSQLDB 允许所有这些,顺便说一下,HSQLDB 上的触发语句是这样的:

create trigger triggerName before insert on alpha
    referencing new row as nuovo
        for each row
            begin atomic
                declare varCount int;
                set varCount=(select count(beta.MAINTABLEid) from beta where beta.MAINTABLEid=nuovo.MAINTABLEid);
                if varCount>0 then signal sqlstate '45000' set message_text='The row is already referenced.';
                end if;
--repeat SET and IF lines to check gamma and lambda tables
                end

【讨论】:

以上是关于解决 Java 嵌入式 SQL 数据库中的排他关系的主要内容,如果未能解决你的问题,请参考以下文章

为啥选择/读取会导致排他(X)锁?

mysql 排他关系的可能性

java oracle sql spark啥关系

第三章 关系数据库语言 SQL 总结

还原数据库出现“未获得排他訪问”解决方法(杀死数据库连接的存储过程sqlserver)

关于mysql 共享锁和排他锁 互斥问题?