gpt4 book ai didi

java - 尝试实现 JWT 安全性时 Hibernate 出现 StackOverflowError

转载 作者:行者123 更新时间:2023-12-04 10:00:40 24 4
gpt4 key购买 nike

我是这个主题的新手,当我尝试授权时,我不断收到“java.lang.StackOverflowError:null”。我在 postman 中收到内部服务器错误,在控制台中我收到 stackoveflowerror。
这是我的 AuthenticationController:


@PostMapping("/signup")
public ResponseEntity<?> registerUser(@Valid @RequestBody SignUpRequest signUpRequest) {
if (userService.existsByEmail(signUpRequest.getEmail())) {
throw new BadRequestException("email already exists");
}
User user = UserMapper.INSTANCE.registerRequestoUser(signUpRequest);
user.setPassword(passwordEncoder.encode(user.getPassword()));
Optional<Role> optionalRole = roleService.getByName("user");

if (optionalRole.isPresent()) {
Role userRole = optionalRole.get();
user.addRole(userRole);
Optional<User> optionalUser = userService.create(user);
if (optionalUser.isPresent()) {
User result = optionalUser.get();
URI location = ServletUriComponentsBuilder
.fromCurrentContextPath().path("/api/v1/users/email/{email}")
.buildAndExpand(result.getEmail()).toUri();

return ResponseEntity.created(location).body("User registered successfully");
}

}
return (ResponseEntity<?>) ResponseEntity.badRequest();
}

我的 SignUpRequest 类:

public class SignUpRequest {
@NotBlank
private String firstName;

@NotBlank
private String lastName;

@NotBlank
@Email
private String email;

@NotBlank
@Size(min = 8, max = 20)
private String password;

private Set<String> roles;

我的用户实体和我的角色实体:
@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User extends BaseEntity {

private String firstName;

private String lastName;

@Email(message = "Email should be valid")
private String email;

@Size(min = 3, max = 100, message
= "password must be between 3 and 50 characters")
private String password;

@OneToMany(mappedBy = "user",
cascade = {CascadeType.PERSIST, CascadeType.MERGE,
CascadeType.DETACH, CascadeType.REFRESH})
private Set<Appointment> appointments;


@ManyToMany(targetEntity = Role.class,
cascade = {CascadeType.ALL},
fetch = FetchType.EAGER)
@JoinTable(
name = "user_role",
joinColumns = {@JoinColumn(name = "user_id")},
inverseJoinColumns = {@JoinColumn(name = "role_id")}
)
private Set<Role> roles;
@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Role extends BaseEntity {

@NotNull
private String name;

@ManyToMany(mappedBy = "roles")
private Set<User> users;

public String getName() {
return name;
}

这是我的 postman 请求
{
"firstName":"name",
"lastName":"name",
"email": "an@gmail.com",
"password": "thepassword123",
"roles": ["user"]

}

这是堆栈跟踪中的一段:
at at com.project.rushhour.entity.User.hashCode(User.java:15) ~[classes/:na]
...
at at com.project.rushhour.entity.Role.hashCode(Role.java:15) ~[classes/:na]
...


at com.project.rushhour.entity.User.hashCode(User.java:15) ~[classes/:na]
...
at com.project.rushhour.entity.Role.hashCode(Role.java:15) ~[classes/:na]
...


at com.project.rushhour.entity.User.hashCode(User.java:15) ~[classes/:na]
...
at com.project.rushhour.entity.Role.hashCode(Role.java:15) ~[classes/:na]
...



我认为错误出现在程序试图解析角色时的某个地方,但不确定到底是什么问题。 jwt的东西设置正确,只是逻辑不对

最佳答案

问题的原因是,您有从用户到角色以及从角色到用户的关系。但是您还没有明确定义 hashCode 方法。您使用@Data 注释。默认情况下,Lombok 生成包含实体所有属性的 hashCode 方法。

hashCode 通常计算如下:

h = hashCode(property1);
h = h*31 + hashCode(property2);
h = h*31 + hashCode(property3);
h = h*31 + hashCode(property4);
h = h*31 + hashCode(property5);
...

在User上调用hashCode时,如果计算属性firstName、lastName等的hash码,还要加上属性roles的hash码。角色哈希码的计算包括计算每个角色元素的哈希码。

但是哈希码的计算 Role 包括计算属性 users 的哈希码,它对每个 User 元素调用 hashCode() 。正如我们在上面看到的,用户的哈希码将再次 coll 角色的哈希码。等等。直到堆栈容量被使用。然后你得到 StackOverflowError。

你怎么能避免呢?从 hashCode() 方法中排除递归。手动实现 hashCode() 。或者告诉 Lombok 从 hashCode() 中排除基于关系的属性。

我更希望 Lombok 仍然为我生成一切。所以我会告诉 Lombok 在生成 hashCode() 和 equals() 时忽略 User 实体中的属性角色和 Role 实体中的属性用户。因此,您的代码如下所示:
public class User extends BaseEntity {

private String firstName;

private String lastName;

...
@EqualsAndHashCode.Exclude
private Set<Role> roles;

...
}

public class Role extends BaseEntity {

...
private String name;

...
@EqualsAndHashCode.Exclude
private Set<User> users;

...

}

为什么注解称为 EqualsAndHashCode?因为 hashCode() 和 equals() 应该始终同步更改以实现所谓的 hashCode - equals 契约。

关于java - 尝试实现 JWT 安全性时 Hibernate 出现 StackOverflowError,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61837621/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com