java - 用户注册后,Hibernate 在角色表中添加了不必要的行
问题描述
我正在尝试通过用户注册向我的 webapp 添加功能。Webapp 基于 spring boot、hibernate 和 mysql 数据库,前端是 angular。通常,用户创建过程正常工作,用户数据通过 json 正确地从前端发送到后端并保存到 shop_user 表中的数据库中(包括所有用户数据,如姓名、姓氏、地址等),但它没有'T 有角色栏。
我也有表“角色”,应该是:
id name
1 USER
2 ADMIN
并加入表 user_role,它由表 shop_user 中的 user_id 和表 role 中的角色 id 组成,所以它应该如下所示:
id_user id_role
1 2
2 1
3 1
在网站上创建用户时,默认将角色设置为 USER 是硬编码的。这似乎工作得很好,因为它在 shop_user 中添加了一个新行,并在 user_role 中添加了一行,但是......它还在“角色”表中创建了一个新行。
所以最后'角色'表看起来像这样:
id name
1 ADMIN
2 USER
3 USER
4 USER
5 USER
99 USER
`
虽然这不是阻止应用程序工作的阻塞错误,但不幸的是,它不是“应该工作”......因为表应该只包含两个角色行(将来可能还有其他角色行),但不能相乘为每个用户!
这是用户的有缺陷的代码:
用户
@Entity
@Table(name = "shop_user")
public class User extends AbstractEntity {
@Column
private String firstName;
@Column
private String lastName;
@Column
private String addressLine;
@Column
private String city;
@Column
private String country;
@Column
private String zipCode;
@Column
private String phoneNumber;
@Column
private String email;
@Column
private String password;
@ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
@JoinTable(name = "user_role",
joinColumns = @JoinColumn(name = "id_user", referencedColumnName = "id"),
inverseJoinColumns = @JoinColumn(name = "id_role", referencedColumnName = "id"),
uniqueConstraints = {@UniqueConstraint(columnNames = {"id_user", "id_role"})})
private List<Role> roles;
public User() {
}
public User(User user) {
setId(user.getId());
this.firstName = user.getFirstName();
this.lastName = user.getLastName();
this.addressLine = user.getAddressLine();
this.city = user.getCity();
this.country = user.getCountry();
this.zipCode = user.getZipCode();
this.phoneNumber = user.getPhoneNumber();
this.email = user.getEmail();
this.password = user.getPassword();
this.roles= user.getRoles();
}
public List<Role> getRoles() {
return roles;
}
public void setRoles(List<Role> roles) {
this.roles = roles;
}
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public String getAddressLine() {
return addressLine;
}
public void setAddressLine(String addressLine) {
this.addressLine = addressLine;
}
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
public String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
public String getZipCode() {
return zipCode;
}
public void setZipCode(String zipCode) {
this.zipCode = zipCode;
}
public String getPhoneNumber() {
return phoneNumber;
}
public void setPhoneNumber(String phoneNumber) {
this.phoneNumber = phoneNumber;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
}
角色实现:
角色
@Entity
@Table(name = "role")
public class Role extends AbstractEntity {
@Column
private String name;
@ManyToMany(mappedBy = "roles", cascade = CascadeType.PERSIST)
private List<User> users;
public Role(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<User> getUsers() {
return users;
}
public void setUsers(List<User> users) {
this.users = users;
}
}
抽象实体:
抽象实体
@MappedSuperclass
public abstract class AbstractEntity implements Persistable<Long> {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
public void setId(Long id) {
this.id = id;
}
@Override
public Long getId() {
return id;
}
@Override
public boolean isNew() {
return id == null;
}
}
用户服务:
用户服务实现
@Service
public class UserServiceImpl extends AbstractServiceImpl<User, UserDTO> implements UserService {
private final UserRepository userRepository;
private final UserConverter userConverter;
public UserServiceImpl(UserRepository userRepository, UserConverter
userConverter) {
this.userRepository = userRepository;
this.userConverter = userConverter;
}
@Override
protected JpaRepository<User, Long> getRepository() {
return userRepository;
}
@Override
protected Converter<User, UserDTO> getConverter() {
return userConverter;
}
@Override
@Transactional
public User registerUser(User user) {
List<Role> roles = new LinkedList<>();
roles.add(new Role("USER"));
user.setRoles(roles);
return userRepository.save(user);
}}
我几乎可以肯定这涉及到 Hibernate 和对象创建中的关系映射,但不能完全弄清楚......
任何帮助将不胜感激,谢谢!
解决方案
问题在这里:
@Override
@Transactional
public User registerUser(User user) {
List<Role> roles = new LinkedList<>();
roles.add(new Role("USER"));
user.setRoles(roles);
return userRepository.save(user);
}}
由于关系 User -> Role 是级联持久化的,因此(新)角色new Role("USER")
也会持久化,并且您最终会为每个用户创建一个新角色,而不是重用现有角色。
解决方案是检查名称 = USER 的角色是否存在。如果不存在,则插入它。否则将现有的添加到roles
集合中。
推荐阅读
- python - 使用 .format() 动态替换 json 值
- c++ - 从 Winapi 中的命名管道读取行
- react-navigation - 为什么从插值器中删除了“react-native-reanimated”?
- javascript - 如何在 axios get 请求中同时传递数据和标头?
- haskell - haskell 使用 Foldl 的 Elem 函数自己的版本
- javascript - 从 jQuery 转换为 Vanilla JS 后 CSS 转换不起作用
- reactjs - React MUI Collapse not working with ToggleButtonGroup
- python - How to write content of an array to a text file, one data on each line?
- r - How can I append a result in a vector without overwriting? (loop)
- flutter - Flutter:更新滚动视图物理而不重建