@Entity 为什么以及如何与枚举类型一起使用?

问题描述 投票:0回答:1

我首先想摆脱我的助教用来枚举用户可以拥有的一些角色的 ERole 枚举类型。看起来像这样:

public enum ERole {
    CUSTOMER,
    MANAGER,
    ADMIN
}

因为我们正在学习 Spring Boot,所以我的 TA 在数据库中持久化这些角色的方式是这样的:

@Entity
@RequiredArgsConstructor
@AllArgsConstructor
@Builder
@Data
public class Role {
    @Id
    @GeneratedValue( strategy = GenerationType.IDENTITY )
    private Integer id;

    @Enumerated( EnumType.STRING )
    @Column( length = 20 )
    private ERole name;
}

需要“角色”表,因为一个用户可以拥有多个角色。使用“用户”和“角色”表之间的多对多关系。

@Entity
@Table ( uniqueConstraints = { @UniqueConstraint ( columnNames = { "username", "email" } ) } )
@RequiredArgsConstructor
@AllArgsConstructor
@Builder
@Data
public class User {

    @Id
    @GeneratedValue ( strategy = GenerationType.IDENTITY )
    private Long id;

    @Column ( nullable = false, length = 20 )
    private String username;

    @Column ( nullable = false, length = 50 )
    private String email;

    @Column ( nullable = false, length = 120 )
    private String password;

    @ManyToMany ( fetch = FetchType.LAZY )
    @JoinTable ( name = "user_roles",
            joinColumns = @JoinColumn ( name = "user_id" ),
            inverseJoinColumns = @JoinColumn ( name = "role_id" ) )
    private Set <Role> roles = new HashSet <> ( );
}

我的目标如下:

  1. 只有一个Role枚举/类,我可以在其中定义我的Role类型
  2. 自动创建“角色”表
  3. 将这些 Role 类型自动插入到“角色”表中,并使用自动生成的唯一 ID
  4. 能够为我的Role枚举/类创建JpaRepository

到目前为止,我已经想出了以下几点:

@Entity
public enum MyRole {
    CUSTOMER,
    MANAGER,
    ADMIN;

    @Id
    @GeneratedValue ( strategy = GenerationType.IDENTITY )
    private Integer id;
}

和 MyRoleRepository,如下所示:

public interface MyRoleRepository extends JpaRepository <MyRole, Integer> {
}

但我收到此错误:

org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'myRoleRepository' defined in org.example.springskeleton.user.MyRoleRepository defined in @EnableJpaRepositories declared on JpaRepositoriesRegistrar.EnableJpaRepositoriesConfiguration: Unable to make field private final java.lang.String java.lang.Enum.name accessible: module java.base does not "opens java.lang" to unnamed module @4988d8b8

从我通过文档搜索的内容(@Entity@TargetElementType),我知道@Entity可以根据其@与枚举类型一起使用Target 注释,但到目前为止我还没有找到任何关于如何完成此操作的示例。

本质上,我想我有两个问题:

  1. 有更好的方法来完成我的助教想做的事情吗?
  2. 如果是这样,我拥有枚举实体的想法是否是更好的方法/甚至可能?

这是我的第一个问题,所以如果我做错了什么,我很抱歉。感谢您的帮助!

java spring-boot jpa spring-data-jpa
1个回答
0
投票

将枚举映射为

@Entity
是没有意义的,因为枚举是具有静态值的类型,这些静态值在加载枚举时初始化。您无法在运行时将新值加载到枚举中。这不是你必须这样做的方式。

实现所需功能的一种方法是拥有

User
实体、
Role
实体和
Roles
枚举。该枚举将包含角色表中的所有角色值,并且还包含角色的数据库 ID 的属性。这非常重要,因为当您启动应用程序时,您需要知道枚举的每个角色的 id。这样您就可以将枚举值与
Role
实体值关联起来。您还可以向
Roles
枚举添加其他属性(即角色的描述)。

public enum Roles {
    CUSTOMER(1L),
    MANAGER(2L),
    ADMIN(3L);

    private Long id;

    private Roles(Long id) {
        this.id = id;
    }

    public Long getId() {
        return id;
    }
}

Role
实体必须与数据库的所有字段(id、name等)进行映射。您不需要将附加字段与枚举值映射。使用这种方法,您必须从
Role
实体中删除自动 id 生成。如果要对角色使用枚举,则假设数据库的角色值将来不会频繁更改。而且当您在枚举中声明值时,您还需要知道角色的 id,因此不需要自动生成 id。

public class Role {
    @Id
    private Integer id;

    @Column( length = 20 )
    private String name;
} 

User
实体大部分是相同的。您可以添加一些
@Transient
方法来帮助您进行角色检查,或者拥有一个带有实用方法的服务类来帮助您处理角色操作。例如,您可以添加一个方法来使用枚举检查用户是否具有角色:

@Transient
public boolean hasRole(Roles role) {
    return roles.stream().anyMatch(r -> r.getId().equals(role.getId());
}

您可以有一个服务方法,为用户添加枚举角色,隐藏

Role
类的内部使用:

public void addRoleToUser(Roles role, User user) {
    Role roleToAdd = roleRepository.findById(role.getId());
    user.getRoles().add(roleToAdd);
}
© www.soinside.com 2019 - 2024. All rights reserved.