我首先想摆脱我的助教用来枚举用户可以拥有的一些角色的 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 <> ( );
}
我的目标如下:
到目前为止,我已经想出了以下几点:
@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,@Target,ElementType),我知道@Entity可以根据其@与枚举类型一起使用Target 注释,但到目前为止我还没有找到任何关于如何完成此操作的示例。
本质上,我想我有两个问题:
这是我的第一个问题,所以如果我做错了什么,我很抱歉。感谢您的帮助!
将枚举映射为
@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);
}