Как реализовать двунаправленные отношения в Spring Spanner? - PullRequest
0 голосов
/ 25 декабря 2018

В коде я попытался с @Interleaved в отношении 1-много на стороне, не являющейся владельцем, получить список дочерних элементов.Может ли кто-нибудь помочь с приведенными ниже вопросами:

  1. Как реализовать двунаправленные отношения, например, получить родителя от ребенка для отношений 1-1, 1-многие
  2. Что касается отношений многие-многие, какие из них лучше всегометоды его реализации и способы реализации двунаправленных отношений.

Большое спасибо.

Ответы [ 2 ]

0 голосов
/ 04 января 2019

Для отношения 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;

Многие-многие отношения должны были бы быть реализованы с использованием связывания таблицы 'mapping'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
);

Ваше приложение будет отвечать за сохранение ссылочной целостности таблицы сопоставления - удаление строк сопоставления при удалении строк в table1 или table2

Есливы хотите использовать таблицы с чередованием, тогда, если вашему приложению необходимо выполнить двунаправленный поиск, вам, возможно, придется создать 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; 

Обратите внимание, что приложению необходимо поддерживать обе этих таблиц сопоставления в актуальном состоянии - т.е. при удалении строки из таблицы1 приложение должно получить ссылочные значения table2_key и удалитьсопоставления из table2_table1_map (и наоборот).

0 голосов
/ 02 января 2019

Cloud Spanner в настоящее время не предлагает способ применения ограничений внешнего ключа между неперемеженными таблицами.Вам придется применять такие ограничения в логике вашего приложения.Вы можете использовать операторы DML в 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'; 

Выполнение двух операторов в транзакции чтения-записи гарантирует, что отношение PK-FK между таблицей Referenced и Referencing всегда поддерживается во время вставки.Возможно, вам придется аналогичным образом изменить запросы на обновление / операторы обновления SQL в логике приложения, чтобы применить ограничение PK-FK для обновлений.

...