Spring Data JDBC: присоединиться к отношениям, не принадлежащим владельцу

У меня есть две совокупные корневые сущности в моей базе данных, сначала Organization с Volunteer и Moderators.

Таблицы:

create table organizations
(
    id   uuid primary key default uuid_generate_v4(),
    name varchar(255) not null,
    slug varchar(64)  not null unique
);

create table organization_moderators
(
    id              uuid primary key default uuid_generate_v4(),
    user_id         uuid not null,
    organization_id uuid not null,
    is_owner        boolean          default false,
    unique (user_id, organization_id),
    foreign key (user_id) references users (id) on delete cascade,
    foreign key (organization_id) references organizations (id) on delete cascade
);

create table organization_volunteers
(
    id              uuid primary key default uuid_generate_v4(),
    user_id         uuid not null,
    organization_id uuid not null,
    unique (user_id, organization_id),
    foreign key (user_id) references users (id) on delete cascade,
    foreign key (organization_id) references organizations (id) on delete cascade
);

Сущности:

@Value
@Table("organizations")
public class Organization {
    @Id
    @JsonIgnore
    UUID id;

    @Column("name")
    String name;

    @Column("slug")
    String slug;

    @MappedCollection(idColumn = "organization_id")
    Set<Moderator> moderators;

    @MappedCollection(idColumn = "organization_id")
    Set<Volunteer> volunteers;
}

@Value
@Table("organization_moderators")
public class Moderator {
    @Id
    @JsonIgnore
    UUID id;

    @Column("user_id")
    UUID userId;

    @Column("is_owner")
    boolean isOwner;
}

@Value
@Table("organization_volunteers")
public class Volunteer {
    @Id
    @JsonIgnore
    UUID id;

    @JsonIgnore
    @Column("user_id")
    UUID userId;
}

И во-вторых, пользовательский совокупный корень.

Стол:

create table users
(
    id            uuid primary key default uuid_generate_v4(),
    username      varchar(32)  not null unique,
    email_address varchar(255) not null unique,
    password      varchar(128) not null
);

Сущность:

@Value
@Table("users")
public class User {
    @Id
    UUID id;

    @Column("username")
    String username;

    @Column("email_address")
    String emailAddress;

    @Column("password")
    String password;
}

Для запроса, который я хочу выполнить, я хотел бы захватить организацию и ее добровольцев, а с добровольцами я хотел бы включить имя пользователя из таблицы пользователей. Как мне сделать это с помощью Spring Data JDBC? Я понимаю, что User не может быть частью совокупного корня Organization, но это все еще данные, которые я хотел бы запросить за один раз.


person Jesse Brands    schedule 20.02.2021    source источник


Ответы (1)


Первый вопрос для меня: почему вы хотите это сделать? Дело не в том, что запрос совершенно необоснован, но может оказаться, что его лучше решить, добавив некоторое кеширование в пользовательский репозиторий.

Но давайте предположим, что мы согласились с тем, что запрошенный вами путь - это то, что вам нужно.

Я вижу две альтернативы этому:

  1. создать альтернативный агрегат организации, который содержит модифицированный вариант класса Volunteer, который напрямую ссылается на класс User. Важная часть - никогда не пытаться сохранять такие Organization. Поэтому я рекомендую не наследовать репозиторий от CrudRepository, а только от Repository и включать только те методы чтения, которые вам действительно нужны, и никаких методов записи.

  2. Вы всегда можете написать cumstom Query и ResultSetExtractor, чтобы загружать данные именно так, как вы хотите.

Помните, что Spring Data JDBC пытается упростить некоторые вещи, но при этом позволяет вам делать с JDBC все, что вы хотите.

person Jens Schauder    schedule 21.02.2021
comment
Спасибо, вариант №2 - это то, к чему я пришел, и я считаю, что это наиболее правильный способ решения проблемы. Я не рассматривал кеширование, но эти данные не очень «горячие», так что я не хочу этого делать. - person Jesse Brands; 22.02.2021