# #google-cloud-spanner #spring-cloud-gcp #interleave
Вопрос:
Я пытаюсь выполнить запрос по полю чередующейся таблицы с помощью ключа Spring Data. Сравнение идентификаторов автоматически выполняется Spring Data Spanner, когда он выполняет внутреннее соединение СТРУКТУРЫ МАССИВА, но я не могу добавить предложение WHERE в запрос чередующейся таблицы.
Рассматривая приведенный ниже пример:
CREATE TABLE Singers (
Id INT64 NOT NULL,
FirstName STRING(1024),
LastName STRING(1024),
SingerInfo BYTES(MAX),
) PRIMARY KEY (Id);
CREATE TABLE Albums (
SingerId INT64 NOT NULL,
Id INT64 NOT NULL,
AlbumTitle STRING(MAX),
) PRIMARY KEY (SingerId, Id),
INTERLEAVE IN PARENT Singers ON DELETE CASCADE;
Предположим, я хочу запросить всех певцов, где AlbumTitle
есть «Страх темноты», как я могу написать метод репозитория для достижения этой цели с помощью Spring Data Spanner?
Ответ №1:
Ваш пример, похоже, либо содержит пару опечаток, либо в остальном не совсем корректен:
- Во второй таблице есть столбец, который является первичным ключом.
Id
Это само по себе прекрасно, но при создании иерархии чередующихся таблиц рекомендуется префиксовать столбец первичного ключа именем таблицы. Так что было бы лучше назвать егоSingerId
. - В
Albums
таблице естьSingerId
столбец иId
столбец. Эти два столбца образуют первичный ключAlbums
таблицы. Это технически неверно (и сбивает с толку), а также причина, по которой я думаю, что ваш пример не совсем верен. ПосколькуAlbums
он чередуетсяSingers
,Albums
должен содержать те же столбцы первичного ключаSingers
, что и таблица, в дополнение к любым дополнительным столбцам, которые образуют первичный ключAlbums
. В этом случаеId
ссылается наSingers
таблицу, иSingerId
это дополнительный столбец вAlbums
таблице, который не имеет ничего общего сSingers
таблицей. Столбцы первичного ключа родительской таблицы также должны отображаться в том же порядке, что и в родительской таблице.
Поэтому пример модели данных следует изменить на:
CREATE TABLE Singers (
SingerId INT64 NOT NULL,
FirstName STRING(1024),
LastName STRING(1024),
SingerInfo BYTES(MAX),
) PRIMARY KEY (SingerId);
CREATE TABLE Albums (
SingerId INT64 NOT NULL,
AlbumId INT64 NOT NULL,
AlbumTitle STRING(MAX),
) PRIMARY KEY (SingerId, AlbumId),
INTERLEAVE IN PARENT Singers ON DELETE CASCADE;
С этого момента вы можете рассматривать SingerId
столбец в Albums
таблице как отношение внешнего ключа к a Singer
и относиться к нему так же, как к любой другой системе баз данных. Обратите также внимание, что для каждого певца может быть несколько альбомов, поэтому запрос …Я хочу опросить всех певцов, у которых название альбома «Страх темноты» несколько двусмысленно. Я бы скорее сказал:
Дайте мне всех певцов, у которых есть хотя бы один альбом с названием «Страх темноты».
Допустимым запросом для этого был бы:
SELECT *
FROM Singers
WHERE SingerId IN (
SELECT SingerId
FROM Albums
WHERE AlbumTitle='Fear of the Dark'
)
Комментарии:
1. Я понял твою точку зрения, и ты прав. Но моя проблема заключается в выполнении этого запроса с помощью Spring Data Spanner, потому что, по-видимому, я не могу добавить предложение WHERE в запрос чередующейся таблицы (все запросы репозитория автоматически генерируются Spring).
2. Я не совсем уверен, что вы имеете в виду под «запросом к чередующейся таблице». Для Spring Data Spanner отношения между Певцом и Альбомом должны быть во многом такими же, как и обычные отношения с внешним ключом. Кроме того, вы должны иметь возможность просто использовать обычный SQL-запрос для достижения желаемого. Видишь docs.spring.io/spring-cloud-gcp/docs/1.1.0.M1/reference/html/… для примера о том, как выполнить запрос. Если бы вы вставили в него запрос из моего ответа, он (теоретически) должен был бы вернуть именно то, что вы ищете.