如何在Spring Spanner中实现双向关系?

时间:2018-12-25 03:47:52

标签: spring google-cloud-platform google-cloud-spanner

在代码中,我尝试在非拥有方以1-many关系使用@Interleaved以获得子列表。任何人都可以帮助解决以下问题:

  1. 如何实现双向关系,例如从孩子那里获得一对一,一对多关系的父母
  2. 关于多对多关系,什么是实现它的最佳实践以及如何实现双向关系。

非常感谢您。

2 个答案:

答案 0 :(得分:2)

Cloud Spanner当前不提供在非交错表之间强制外键约束的方法。您将必须在应用程序逻辑中强制执行此类约束。您可以使用DML statements in Cloud Spanner(具有在Cloud Spanner事务中读取和写入的功能)在插入时通过如下方式将这些约束插入表中来强制执行这些约束:

INSERT INTO Referenced(key1,value1) VALUES ('Referenced','Value1');
INSERT INTO Referencing(key2, value2, key1) 
SELECT 'Referencing', 'Value2', key1 FROM Referenced WHERE
key1 = 'Referenced'; 

在读写事务中运行两个语句将确保ReferencedReferencing表之间的PK-FK关系始终在插入时保持。您可能必须在应用程序逻辑中类似地修改更新请求/ SQL更新语句,以对更新实施PK-FK约束。

答案 1 :(得分:1)

对于一对多关系,当使用交错表时,子行的主键已包含其父级的主键,因此获取它很简单。父行。

CREATE TABLE parent (
    parent_key INT64 NOT NULL,
    ...
) PRIMARY KEY (parent_key);

CREATE TABLE child (
    parent_key INT64 NOT NULL,
    child_key INT64 NOT NULL,
    ...
) PRIMARY KEY (parent_key, child_key),
INTERLEAVE IN PARENT parent ON DELETE CASCADE;

如果由于某种原因您没有父级的键,而只有子级的键,那么为了提高效率,您需要为反向查找创建索引:

CREATE INDEX child_to_parent_index 
ON child (
    child_key
);

并在对父级执行查询时强制使用该索引:

SELECT 
    p.* 
FROM 
    parent as p 
JOIN 
    child@{FORCE_INDEX=child_by_id_index} AS c ON p.parent_key = c.parent_key 
WHERE 
    c.child_key = @CHILD_KEY_VALUE;

许多关系必须使用将table1-key链接到table2-key的“映射”表来实现。 您还将需要一个顶级索引来获得有效的反向查找,并在查询中使用上述的FORCE_INDEX指令。

正如@adi所提到的,外键约束必须由应用程序强制执行。

CREATE TABLE table1 (
    table1_key INT64 NOT NULL,
    ...
) PRIMARY KEY (table1_key);

CREATE TABLE table2 (
    table2_key INT64 NOT NULL,
    ...
) PRIMARY KEY (table2_key);

CREATE TABLE table1_table2_map (
    table1_key INT64 NOT NULL,
    table2_key INT64 NOT NULL,
) PRIMARY KEY (table1_key, table2_key);

CREATE INDEX table2_table1_map_index 
ON table1_table2_map (
    table2_key
) STORING (
    table1_key
);

您的应用程序将负责维护映射表的引用完整性-删除table1table2中的行时删除映射行

如果要使用交错表,则如果您的应用程序需要执行双向查找,则可能必须创建2个映射表-作为每个父级的子级,以便从两个方向查找映射都同样有效

CREATE TABLE table1 (
    table1_key INT64 NOT NULL,
    ...
) PRIMARY KEY (table1_key);

CREATE TABLE table2 (
    table2_key INT64 NOT NULL,
    ...
) PRIMARY KEY (table2_key);

CREATE TABLE table1_table2_map (
    table1_key INT64 NOT NULL,
    table2_key INT64 NOT NULL,
) PRIMARY KEY (table1_key, table2_key),
INTERLEAVE IN PARENT table1 ON DELETE CASCADE;

CREATE TABLE table2_table1_map (
    table2_key INT64 NOT NULL,
    table1_key INT64 NOT NULL,
) PRIMARY KEY (table2_key, table1_key),
INTERLEAVE IN PARENT table2 ON DELETE CASCADE; 

请注意,应用程序需要保持这些映射表的均为最新-例如,当从table1中删除一行时,应用程序必须获取引用的table2_key值并删除table2_table1_map的映射(反之亦然)。