java - 用户、用户角色的数据库设计——多对多关系

标签 java hibernate jpa many-to-many entitymanager

在我的项目中,我有一个用户实体和一个用户角色实体。 根据我的数据库设计,一个用户可以扮演多个角色,一个角色可以关联多个用户。我在系统中拥有的用户角色是 USER 和 ADMIN。

需要将用户角色存储在表中,并且当用户持久化到其相关表中时需要引用它们。

但是,根据我实现的代码,每次我将用户插入数据库时​​,记录也会插入到用户角色表中。我需要的是将数据插入用户表和连接表。

这些是我的实体。

用户:

@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 表。

在我的情况下我应该如何编写代码。 另外,我想知道我应该在 User 实体中使用什么 CascadeType 。我已经放置了 CascadeType.ALL,但我知道根据上下文,这不是那个地方的最佳类型。

最佳答案

关于@ManyToMany,你肯定对CascadeType.REMOVE非常谨慎,所以我将其定义为CascadeType.PERSIST, CascadeType.MERGE.

现在,您可以保留其余的映射,因为它们很好。 为了不保存角色,您必须先查询它们,而不是像您一样手动创建它们。对于持久性,提供的只是一些新的非托管实体,它会尝试在提交时持久化它们。

以下示例利用了已经存在的 UserRole 的,并且由于只有 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);

关于java - 用户、用户角色的数据库设计——多对多关系,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43846652/

相关文章:

Java 实体 - 为什么我需要一个空的构造函数?

Java Spring JPA 关系 @OneToMany 与第三列

java - 如何将 google 身份验证 token (在 iOS 中获得)传递到 google-app-engine Web servlet?

java - 为什么有些java类在构造时好像有返回值?

java - 无法将 boolean 值更改为 true

java - Spring 事务上下文包装?

Java Swing 应用程序留下痕迹的 gif 动画

java - Hibernate中使用List时放置List Index

Hibernate 查询不返回完整对象

java - 将持久化实体更改为同级子类