Spring 数据 JDBC:加入非拥有关系
Spring Data JDBC: Join on non-owned relationship
我的数据库中有两个聚合根实体,第一个是 Organization
和 Volunteer
以及 Moderators
。
Tables:
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;
}
其次,用户聚合root。
Table:
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;
}
对于我想做的查询,我想获取一个组织及其志愿者,并且我想在志愿者中包含用户 table 的用户名。我如何使用 Spring 数据 JDBC 执行此操作?我知道 User
不能成为 Organization
的聚合根的一部分,但这仍然是我想一次性查询的数据。
我的第一个问题是:你为什么要这样做?
并不是说这个请求完全不合理,可能是在用户仓库中加入一些缓存会更好的解决
但假设我们同意您要求的方式是可行的方式。
我看到有两种选择:
创建一个替代组织聚合,其中包含 Volunteer
class 的修改变体,它直接引用 User
class。重要的是永远不要试图保存这种 Organization
。因此,我建议不要从 CrudRepository
继承存储库,而仅从 Repository
继承存储库,并且只包含您实际需要的阅读方法,而不包含写入方法。
您始终可以编写一个 cumstom Query
和一个 ResultSetExtractor
以完全按照您想要的方式加载数据。
记住 Spring 数据 JDBC 试图让一些事情变得简单,同时仍然允许你用 JDBC 做任何你想做的事。
我的数据库中有两个聚合根实体,第一个是 Organization
和 Volunteer
以及 Moderators
。
Tables:
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;
}
其次,用户聚合root。
Table:
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;
}
对于我想做的查询,我想获取一个组织及其志愿者,并且我想在志愿者中包含用户 table 的用户名。我如何使用 Spring 数据 JDBC 执行此操作?我知道 User
不能成为 Organization
的聚合根的一部分,但这仍然是我想一次性查询的数据。
我的第一个问题是:你为什么要这样做? 并不是说这个请求完全不合理,可能是在用户仓库中加入一些缓存会更好的解决
但假设我们同意您要求的方式是可行的方式。
我看到有两种选择:
创建一个替代组织聚合,其中包含
Volunteer
class 的修改变体,它直接引用User
class。重要的是永远不要试图保存这种Organization
。因此,我建议不要从CrudRepository
继承存储库,而仅从Repository
继承存储库,并且只包含您实际需要的阅读方法,而不包含写入方法。您始终可以编写一个 cumstom
Query
和一个ResultSetExtractor
以完全按照您想要的方式加载数据。
记住 Spring 数据 JDBC 试图让一些事情变得简单,同时仍然允许你用 JDBC 做任何你想做的事。