无法写入 JSON:延迟初始化角色集合失败:

Could not write JSON: failed to lazily initialize a collection of role:

我在获取类型时遇到错误,我不知道如何解决!如果可以,请帮助我。 :D。使用 java 8

命令行运行程序:

    @Autowired CustomTableRepository tr;
    @Autowired UserRepository ur;
    @Autowired RoleRepository rr;
    @Bean
    CommandLineRunner commandLineRunner() {
        return args -> {
            tr.save(new CustomTable(null, true, null));
            tr.save(new CustomTable(null, true, null));
            tr.save(new CustomTable(null, true, null));
            tr.save(new CustomTable(null, true, null));
            tr.save(new CustomTable(null, true, null));

            ur.save(new User(null, "cpthermes", "thanatos", 123987456l, 3123231l, null,null));
            ur.save(new User(null, "moni1008", "milky", 123987456l, 31232131l, null, null));
            ur.save(new User(null, "mario", "zoro123", 1231231l, 32123l, null, null));

            
        };
    }

模特类:

@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Reservation {
    
    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE)
    private Long id;
    private Boolean accepted;
    @ManyToOne
    @JoinColumn(name = "user_id")
    private User user;
    @OneToOne
    @JoinColumn(name = "table_id")
    private CustomTable table;
    private LocalTime time;
}



@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE)
    private Long id;
    private String username;
    private String password;
    private Long number;
    private Long balance;
    @OneToMany(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true)
    private List<Reservation> reservations;
    @ManyToMany
    private Collection<Role> roles;
}

@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Role {
    @Id
    @GeneratedValue
    private Long id;
    private String type;
}

错误:

Could not write JSON: failed to lazily initialize a collection of role: com.mile.pc.mile.restoraunt.app.model.User.reservations, could not initialize proxy - no Session; nested exception is com.fasterxml.jackson.databind.JsonMappingException: failed to lazily initialize a collection of role: com.mile.pc.mile.restoraunt.app.model.User.reservations, could not initialize proxy - no Session (through reference chain: java.util.ArrayList[0]->com.mile.pc.mile.restoraunt.app.model.User["reservations"])
org.springframework.http.converter.HttpMessageNotWritableException: Could not write JSON: failed to lazily initialize a collection of role: com.mile.pc.mile.restoraunt.app.model.User.reservations, could not initialize proxy - no Session; nested exception is com.fasterxml.jackson.databind.JsonMappingException: failed to lazily initialize a collection of role: com.mile.pc.mile.restoraunt.app.model.User.reservations, could not initialize proxy - no Session (through reference chain: java.util.ArrayList[0]->com.mile.pc.mile.restoraunt.app.model.User["reservations"])

....... ................................... ................................... ................................... ................................... ................................... 喜欢读书。

问题是在 Spring 尝试将您的实体转换为 JSON 时,Hibernate 无法从数据库中检索延迟加载的 reservations。您有几种可能性来解决这个问题:

  • 使用FetchType.EAGER策略
@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE)
    private Long id;
    private String username;
    private String password;
    private Long number;
    private Long balance;
    @OneToMany(fetch = FetchType.EAGER, mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true)
    private List<Reservation> reservations;
    @ManyToMany
    private Collection<Role> roles;
}
  • 在您的自定义存储库方法中使用连接提取:
@Query(value = "SELECT u FROM User u JOIN FETCH u.reservations")
List<User> findAllUsers();

您可以在以下在线资源中阅读有关此问题的更多信息:https://www.baeldung.com/hibernate-initialize-proxy-exception

对于 @OneToMany@ManyToMany hibernate 默认使用惰性获取方法。即当您要求它获取父实体时,它根本不会加载您的子实体。所以你可以有两种更简单的方法来克服这个问题。

  1. Reservations上使用fetch=FetchType.EAGER

只需在下面更新角色class。

@OneToMany(fetch = FetchType.EAGER, mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true)
    private List<Reservation> reservations;

但请注意性能问题。当您请求 Role 实体时,Hibernate 将始终加载 Reservation 实体。如果这不是您的应用程序关心的问题,您可以轻松地进行此操作。

  1. 使用JOIN FETCH方法

使用 join fetch 定义 @Query 方法并使用它而不是预定义的 find() 方法。通过这种方式,您可以询问 hibernate 要加载哪些其他表 每当您要求加载父实体时。

@Query(value = "SELECT u FROM User u JOIN FETCH u.reservations")
List<User> findUsersWithReservations();

下面的文章有关于它的更多详细信息以及一些其他方法。

https://thorben-janssen.com/lazyinitializationexception/