hibernate - 具有额外多对多关系的 JPA 多对多
问题描述
我需要支持涉及以下实体的场景(使用 JPA):
- 用户
- 帐户
- 角色
一个用户可以有多个帐户,并且一个帐户可以在多个用户之间共享,这是迄今为止的标准@ManyToMany 关系。
一个用户可以为每个帐户拥有一组不同的角色,一个角色可以在多个用户之间共享。
我遵循了这种做法,它解释了一种将多对多关联与额外列映射的方法,但我不确定我是否明白。
用户实体:
@Entity
@Table(name = "users")
public class User implements Serializable {
@Id
@Column(name = "id", unique = true, nullable = false)
@GeneratedValue(generator = "uuid")
@GenericGenerator(name = "uuid", strategy = "org.hibernate.id.UUIDGenerator")
private String id;
@Column(name = "email", nullable = false)
private String email;
@Column(name = "full_name", nullable = false)
private String fullName;
@OneToMany(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true)
private Set<UserAccount> usersAccounts;
public User() {
usersAccounts= Sets.newHashSet();
}
public User(String email, String fullName) {
this();
this.email = email;
this.fullName = fullName;
}
public void addAccont(Account account) {
UserAccount userAccount = new UserAccount(this, account);
accounts.add(userAccount);
account.getUsers().add(userAccount);
this.accounts.add(userAccount);
}
public void removeAccont(Account account) {
for (Iterator<UserAccount> iterator = accounts.iterator(); iterator.hasNext(); ) {
UserAccount userAccount = iterator.next();
if (userAccount.getUser().equals(this) &&
userAccount.getAccount().equals(account)) {
iterator.remove();
userAccount.getAccount().getUsers().remove(userAccount);
userAccount.setUser(null);
userAccount.setAccount(null);
}
}
}
//Getters Setters..
}
账户实体:
@Entity
@Table(name = "accounts")
public class Account implements Serializable {
@Id
@Column(name = "id", unique = true, nullable = false)
@GeneratedValue(generator = "uuid")
@GenericGenerator(name = "uuid", strategy = "org.hibernate.id.UUIDGenerator")
private String id;
@Column(name = "name", nullable = false)
private String name;
@Column(name = "billing_address", nullable = false)
private String billingAddress;
@OneToMany(mappedBy = "account", cascade = CascadeType.ALL, orphanRemoval = true)
private Set<UserAccount> usersAccounts;
public Account() {
usersAccounts= Sets.newHashSet();
}
//Getters Setters..
}
用户帐户实体:
@Entity
@Table(name = "users_accounts")
public class UserAccount implements Serializable {
@EmbeddedId
private UserAccountId id;
@ManyToOne(
fetch = FetchType.LAZY,
cascade = {
CascadeType.PERSIST,
CascadeType.MERGE
})
private User user;
@ManyToOne(
fetch = FetchType.LAZY,
cascade = {
CascadeType.PERSIST,
CascadeType.MERGE
})
private Account account;
@ManyToMany(
fetch = FetchType.LAZY,
cascade = {
CascadeType.PERSIST,
CascadeType.MERGE
})
@JoinTable(
name = "users_accounts_roles",
joinColumns = {
@JoinColumn(name = "user_id", referencedColumnName = "user_id"),
@JoinColumn(name = "account_id", referencedColumnName = "account_id"),
},
inverseJoinColumns = @JoinColumn(name = "role_id", referencedColumnName = "id")
)
private Set<Role> roles;
private UserAccount() {}
public UserAccount(@NotNull User user, @NotNull Account account) {
this.user = user;
this.account = account;
roles = Sets.newHashSet();
this.id = new UserAccountId(user.getId(), account.getId());
}
//Getters Setters..
}
用户帐号 ID:
@Embeddable
public class UserAccountId implements Serializable {
@Column(name = "user_id")
private String userId;
@Column(name = "account_id")
private String accountId;
private UserAccountId() {
}
public UserAccountId(
String userId,
String accountId) {
this.userId = userId;
this.accountId = accountId;
}
//Getters Setters..
}
我正在创建一个新用户并尝试将其保存到数据库:
User user = new User("some.email@mail.com", "John Doe");
userRepository.save(savedEntity);
我收到 JpaSystemException:
Caused by: java.sql.SQLException: Field 'user_account_account_id' doesn't have a default value
查看休眠的创建表语句,我看到:
create table users
(
id varchar(255) not null
primary key,
email varchar(255) not null,
full_name varchar(255) not null,
user_account_account_id varchar(255) not null,
user_account_user_id varchar(255) not null,
constraint UK_exxyrhm7e34pwn8dvem8wxuxu
unique (user_account_account_id, user_account_user_id),
constraint FKhti2663qxk7qo15f7gfnnaj7r
foreign key (user_account_account_id, user_account_user_id) references users_accounts (account_id, user_id)
)
engine = InnoDB;
我不清楚标记为据我从我的实体了解的可以在没有帐户的情况下创建用户的user_account_account_id
列。user_account_user_id
not null
为什么表是这样创建的?我怎样才能让它工作?
解决方案
这是对的/有意义的吗?
您的解决方案将起作用,只是它听起来是一个非常复杂的模型。您确定多对多关联不应该在Role
and Account
(而不是UserAccount
)之间吗?换句话说,会根据使用的不同而Account
有不同吗?Roles
User
另外,我在您建议的映射中发现了一个问题。你可能想要:
@JoinTable(
name = "users_accounts_roles",
joinColumns = {
@JoinColumn(name = "user_id", referencedColumnName = "user_id"),
@JoinColumn(name = "account_id", referencedColumnName = "account_id"),
},
inverseJoinColumns = @JoinColumn(name = "role_id", referencedColumnName = "id")
)
(因为在 中没有id
要引用的列UserAccount
;相反,有两个主键列)
推荐阅读
- react-native - 闪屏后 iPad 屏幕旋转 180 度
- javascript - 推迟 signalR 长轮询请求
- botframework - 如何开始:将 Microsoft bot 框架功能嵌入到具有拖放配置功能的应用程序中?
- reactjs - 创建 React App:安装时未创建 src 和公用文件夹
- regex - 在大数据框中搜索和替换非数字数据的最佳方法
- sql-server - 什么数据类型对应于 Oracle 18C 中的 TIME(在 SQL Server 中)?
- mongodb - 如何将数据推送到数组mongodb
- python - Python 脚本中的未知语法会带来索引错误。你能读一下吗?(并解释一下?)
- android - RecyclerView 不更新
- keyboard - Ctrl + Z 键盘快捷键通常如何实际工作?