有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java无法写入JSON:未能延迟初始化角色集合:

我的获取类型有错误,我不知道如何修复它!如果可以的话,请帮助我D.使用Java8

命令行运行程序:

    @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"])

。。。。。。。。。。。。。。。。。。。。 .................... .................... .................... .................... .................... 我喜欢阅读


共 (2) 个答案

  1. # 1 楼答案

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

    • 使用FetchType。渴望战略
    @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

  2. # 2 楼答案

    对于@OneToMany@ManyToMany,默认情况下hibernate使用延迟获取方法。i、 e.当您要求它获取父实体时,它不会加载子实体。所以你可以有两种简单的方法来解决这个问题

    1. Reservations上使用fetch=FetchType.EAGER

    只需在角色类中更新以下内容

    @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/