如何修复延迟初始化集合失败
How to fix failed to lazily initialize a collection
当我尝试从数据库获取有关用户的数据时,出现以下错误:
Request processing failed; nested exception is org.hibernate.LazyInitializationException: failed
to lazily initialize a collection of role: com.hramyko.finalapp.entity.CommonUser.comments, could not initialize
proxy - no Session
我知道这发生在我的会话关闭之前,但我不想使用 eager fetch。有什么方法可以解决我的问题?我在 Whosebug 上阅读了我的问题的解决方案,但它对我没有帮助。
我的普通用户class:
package com.hramyko.finalapp.entity;
import javax.persistence.Entity;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import java.util.Date;
import java.util.List;
import java.util.Objects;
@Entity
@Table(name = "common_users")
public class CommonUser extends User {
@OneToMany(mappedBy = "author")
private List<Comment> comments;
public CommonUser() {
}
public CommonUser(User user) {
super(user.getEmail(), user.getPassword(), user.getFirstName(), user.getLastName(),
user.getCreatedAt(), user.getRole(), user.getStatus());
this.id = user.getId();
}
public CommonUser(String email, String password, String firstName,
String lastName, Date createdAt, Role role, Status status, List<Comment> comments) {
super(email, password, firstName, lastName, createdAt, role, status);
this.comments = comments;
}
public List<Comment> getComments() {
return comments;
}
public void setComments(List<Comment> comments) {
this.comments = comments;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (!super.equals(o)) return false;
CommonUser that = (CommonUser) o;
return Objects.equals(comments, that.comments);
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), comments);
}
@Override
public String toString() {
return "CommonUser{" +
"id=" + id +
", email='" + email + '\'' +
", firstName='" + firstName + '\'' +
", lastName='" + lastName + '\'' +
", comments=" + comments +
", createdAt=" + createdAt +
", role=" + role +
'}';
}
}
服务:
@Transactional
@Override
public User currentUser() {
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
String username;
if (principal instanceof UserDetails) {
username = ((UserDetails) principal).getUsername();
} else {
username = principal.toString();
}
return userRepository.findUserByEmail(username);
}
@Transactional
@Override
public User findUserByEmail(String email) {
userValidator.validateEmail(email);
return userRepository.findUserByEmail(email);
}
控制器:
@PreAuthorize("hasAnyAuthority('user.read', 'user.write', 'user.delete')")
@GetMapping("my_account")
public String show() {
return userService.currentUser().toString();
}
这是因为您正在访问用户 toString()
中的评论,但评论尚未初始化并且加载用户的事务已关闭。
通常有两种解决方法:
使用fetch join加载此用户时也获取评论
增加事务边界以覆盖控制器的 show() 方法,这样当您在其中访问 user.toString()
时,加载用户的事务仍然处于活动状态且尚未关闭:
@Transactional
public String show() {
return userService.currentUser().toString();
}
当我尝试从数据库获取有关用户的数据时,出现以下错误:
Request processing failed; nested exception is org.hibernate.LazyInitializationException: failed
to lazily initialize a collection of role: com.hramyko.finalapp.entity.CommonUser.comments, could not initialize
proxy - no Session
我知道这发生在我的会话关闭之前,但我不想使用 eager fetch。有什么方法可以解决我的问题?我在 Whosebug 上阅读了我的问题的解决方案,但它对我没有帮助。
我的普通用户class:
package com.hramyko.finalapp.entity;
import javax.persistence.Entity;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import java.util.Date;
import java.util.List;
import java.util.Objects;
@Entity
@Table(name = "common_users")
public class CommonUser extends User {
@OneToMany(mappedBy = "author")
private List<Comment> comments;
public CommonUser() {
}
public CommonUser(User user) {
super(user.getEmail(), user.getPassword(), user.getFirstName(), user.getLastName(),
user.getCreatedAt(), user.getRole(), user.getStatus());
this.id = user.getId();
}
public CommonUser(String email, String password, String firstName,
String lastName, Date createdAt, Role role, Status status, List<Comment> comments) {
super(email, password, firstName, lastName, createdAt, role, status);
this.comments = comments;
}
public List<Comment> getComments() {
return comments;
}
public void setComments(List<Comment> comments) {
this.comments = comments;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
if (!super.equals(o)) return false;
CommonUser that = (CommonUser) o;
return Objects.equals(comments, that.comments);
}
@Override
public int hashCode() {
return Objects.hash(super.hashCode(), comments);
}
@Override
public String toString() {
return "CommonUser{" +
"id=" + id +
", email='" + email + '\'' +
", firstName='" + firstName + '\'' +
", lastName='" + lastName + '\'' +
", comments=" + comments +
", createdAt=" + createdAt +
", role=" + role +
'}';
}
}
服务:
@Transactional
@Override
public User currentUser() {
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
String username;
if (principal instanceof UserDetails) {
username = ((UserDetails) principal).getUsername();
} else {
username = principal.toString();
}
return userRepository.findUserByEmail(username);
}
@Transactional
@Override
public User findUserByEmail(String email) {
userValidator.validateEmail(email);
return userRepository.findUserByEmail(email);
}
控制器:
@PreAuthorize("hasAnyAuthority('user.read', 'user.write', 'user.delete')")
@GetMapping("my_account")
public String show() {
return userService.currentUser().toString();
}
这是因为您正在访问用户 toString()
中的评论,但评论尚未初始化并且加载用户的事务已关闭。
通常有两种解决方法:
使用fetch join加载此用户时也获取评论
增加事务边界以覆盖控制器的 show() 方法,这样当您在其中访问
user.toString()
时,加载用户的事务仍然处于活动状态且尚未关闭:
@Transactional
public String show() {
return userService.currentUser().toString();
}