用户、用户角色的数据库设计——多对多关系
Database design for User, UserRole - many to many relationship
在我的项目中,我有一个 User 实体和一个 UserRole 实体。
根据我的数据库设计,一个用户可以扮演多个角色,一个角色可以关联多个用户。我在系统中的用户角色是 USER 和 ADMIN。
需要将用户角色存储在 table 中,并且当用户在其相关 table.
中持久化时需要引用它们
但是,根据我实施的代码,每次我将用户插入数据库时,记录也会插入到用户角色 table 中。我需要的是将数据插入用户 table 和连接 table.
这些是我的实体。
用户:
@Entity
@Table(name="user")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id", nullable = false, updatable= false)
private Long id;
@Column(name = "email", nullable = false, unique = true)
private String email;
@Column(name = "first_name", nullable = false)
private String firstName;
@Column(name = "last_name", nullable = false)
private String lastName;
@Column(name = "password_hash", nullable = false)
private String passwordHash;
@ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@JoinTable(name = "user_with_role",
joinColumns = {@JoinColumn(name = "user_id", referencedColumnName = "id")},
inverseJoinColumns = {@JoinColumn(name = "role_id", referencedColumnName = "id")})
private List<UserRole> roles;
}
用户角色:
@Entity
@Table(name = "userrole")
public class UserRole {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id", nullable = false, updatable= false)
private long id;
@Column(name = "role_name")
@NotNull
@Enumerated(EnumType.STRING)
private Role roleName;
@ManyToMany(mappedBy = "roles", fetch = FetchType.LAZY)
private List<User> users;
}
这就是我将用户持久保存到数据库的方式。
List<UserRole> roles = new ArrayList<>();
UserRole ur_user = new UserRole();
ur_user.setRoleName(Role.USER);
UserRole ur_admin = new UserRole();
ur_user.setRoleName(Role.ADMIN);
roles.add(ur_user);
roles.add(ur_admin);
newUser.setRoles(roles);
entityManager.persist(newUser);
entityManager.flush();
这种机制适用于需要将关联实体与父实体一起输入数据库的情况。 (例如:员工联系电话)
在我的情况下,我真的不明白我应该如何编写代码才能在用户持久化时不插入到 UserRole table。
我应该如何编写代码。
另外,我想知道我应该在 User 实体中使用什么 CascadeType 。我放了 CascadeType.ALL
,但我知道根据上下文,那不是那个地方最好的类型。
嗯,关于 @ManyToMany
你应该对 CascadeType.REMOVE
非常谨慎,所以我将其定义为 CascadeType.PERSIST, CascadeType.MERGE
。
现在,您可以保留其余的映射,因为它们很好。
为了不保存角色,您必须先查询它们,而不是像您一样手动创建它们。对于持久性,提供的只是一些新的非托管实体,它会尝试在提交时持久化它们。
下面的例子利用了已经存在的 UserRole's
并且因此只有 User
被持久化(使用已经存在的依赖项):
UserRole ur_user = entityManager.getRoleByType(Role.USER);
UserRole ur_admin = entityManager.getRoleByType(Role.ADMIN);
roles.add(ur_user);
roles.add(ur_admin);
newUser.setRoles(roles);
entityManager.persist(newUser);
在我的项目中,我有一个 User 实体和一个 UserRole 实体。 根据我的数据库设计,一个用户可以扮演多个角色,一个角色可以关联多个用户。我在系统中的用户角色是 USER 和 ADMIN。
需要将用户角色存储在 table 中,并且当用户在其相关 table.
中持久化时需要引用它们但是,根据我实施的代码,每次我将用户插入数据库时,记录也会插入到用户角色 table 中。我需要的是将数据插入用户 table 和连接 table.
这些是我的实体。
用户:
@Entity
@Table(name="user")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id", nullable = false, updatable= false)
private Long id;
@Column(name = "email", nullable = false, unique = true)
private String email;
@Column(name = "first_name", nullable = false)
private String firstName;
@Column(name = "last_name", nullable = false)
private String lastName;
@Column(name = "password_hash", nullable = false)
private String passwordHash;
@ManyToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
@JoinTable(name = "user_with_role",
joinColumns = {@JoinColumn(name = "user_id", referencedColumnName = "id")},
inverseJoinColumns = {@JoinColumn(name = "role_id", referencedColumnName = "id")})
private List<UserRole> roles;
}
用户角色:
@Entity
@Table(name = "userrole")
public class UserRole {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id", nullable = false, updatable= false)
private long id;
@Column(name = "role_name")
@NotNull
@Enumerated(EnumType.STRING)
private Role roleName;
@ManyToMany(mappedBy = "roles", fetch = FetchType.LAZY)
private List<User> users;
}
这就是我将用户持久保存到数据库的方式。
List<UserRole> roles = new ArrayList<>();
UserRole ur_user = new UserRole();
ur_user.setRoleName(Role.USER);
UserRole ur_admin = new UserRole();
ur_user.setRoleName(Role.ADMIN);
roles.add(ur_user);
roles.add(ur_admin);
newUser.setRoles(roles);
entityManager.persist(newUser);
entityManager.flush();
这种机制适用于需要将关联实体与父实体一起输入数据库的情况。 (例如:员工联系电话)
在我的情况下,我真的不明白我应该如何编写代码才能在用户持久化时不插入到 UserRole table。
我应该如何编写代码。
另外,我想知道我应该在 User 实体中使用什么 CascadeType 。我放了 CascadeType.ALL
,但我知道根据上下文,那不是那个地方最好的类型。
嗯,关于 @ManyToMany
你应该对 CascadeType.REMOVE
非常谨慎,所以我将其定义为 CascadeType.PERSIST, CascadeType.MERGE
。
现在,您可以保留其余的映射,因为它们很好。 为了不保存角色,您必须先查询它们,而不是像您一样手动创建它们。对于持久性,提供的只是一些新的非托管实体,它会尝试在提交时持久化它们。
下面的例子利用了已经存在的 UserRole's
并且因此只有 User
被持久化(使用已经存在的依赖项):
UserRole ur_user = entityManager.getRoleByType(Role.USER);
UserRole ur_admin = entityManager.getRoleByType(Role.ADMIN);
roles.add(ur_user);
roles.add(ur_admin);
newUser.setRoles(roles);
entityManager.persist(newUser);