【问题标题】:How to fix failed to lazily initialize a collection如何修复无法延迟初始化集合
【发布时间】:2022-01-06 18:21:23
【问题描述】:

当我尝试从数据库中获取有关用户的数据时,我收到以下错误:

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。有什么方法可以解决我的问题?我在 stackoverflow 上阅读了我的问题的解决方案,但它对我没有帮助。

我的 CommonUser 类:

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()?
  • @pL4Gu33 是的。我转移到服务,一切正常。谢谢!

标签: java spring spring-boot hibernate jpa


【解决方案1】:

这是因为您正在访问 User 的 toString() 中的 cmets,但 cmets 尚未初始化,并且加载用户的事务已关闭。

通常有两种解决方法:

  1. 在加载此用户时使用fetch join 来获取 cmets

  2. 增加事务边界以覆盖控制器的 show() 方法,这样当您在其中访问 user.toString() 时,加载用户的事务仍然处于活动状态且尚未关闭:

@Transactional
public String show() {
    return userService.currentUser().toString();
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-12-19
    • 1970-01-01
    • 2019-05-21
    • 2014-05-14
    • 2020-05-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多