【问题标题】:Could not write JSON无法写入 JSON
【发布时间】:2018-01-08 15:25:19
【问题描述】:

您好,我是休眠新手。我在春天使用 JSON。我想以 JSON 格式显示用户的详细信息,但那里出现了一些错误。 我的错误是:

HTTP 状态 500 - 内部服务器错误

输入异常报告

消息内部服务器错误

描述服务器遇到了一个内部错误,导致它无法完成这个请求。

异常

org.springframework.http.converter.HttpMessageNotWritableException:无法写入 JSON:无法延迟初始化角色集合:com.nishan.lifestyle.entity.User.pictureList,无法初始化代理 - 无会话;嵌套异常是 com.fasterxml.jackson.databind.JsonMappingException:未能延迟初始化角色集合:com.nishan.lifestyle.entity.User.pictureList,无法初始化代理 - 无 Session(通过引用链:java.util.数组列表[0]-

com.nishan.lifestyle.entity.User["pictureList"]) note 异常的完整堆栈跟踪及其根本原因可在 GlassFish Server Open Source Edition 4.1.1 日志中找到。

GlassFish Server 开源版 4.1.1

我已使用以下方法获取所有用户的详细信息

public List<T> getAll() {
    session = sessionFactory.openSession();
    Criteria criteria = session.createCriteria(persistClass);
    List<T> list = criteria.list(); 
    session.close();
    return list;
}

//getting JSON file

    @RequestMapping(value = "/api/customer/customer-details", method = RequestMethod.GET)
    public @ResponseBody List<User> getUserId() {
        return customerDaoImp.getAll();
    }

User.java- 实体类

        @Entity
    @Table(name = "tbl_user", catalog = "lifestyle", schema = "")
    @NamedQueries({
        @NamedQuery(name = "User.findAll", query = "SELECT u FROM User u")
        , @NamedQuery(name = "User.findByUserId", query = "SELECT u FROM User u WHERE u.userId = :userId")
        , @NamedQuery(name = "User.findByFullName", query = "SELECT u FROM User u WHERE u.fullName = :fullName")
        , @NamedQuery(name = "User.findByAddress", query = "SELECT u FROM User u WHERE u.address = :address")
        , @NamedQuery(name = "User.findByContact", query = "SELECT u FROM User u WHERE u.contact = :contact")
        , @NamedQuery(name = "User.findByGender", query = "SELECT u FROM User u WHERE u.gender = :gender")
        , @NamedQuery(name = "User.findByDob", query = "SELECT u FROM User u WHERE u.dob = :dob")
        , @NamedQuery(name = "User.findByEmail", query = "SELECT u FROM User u WHERE u.email = :email")
        , @NamedQuery(name = "User.findByPassword", query = "SELECT u FROM User u WHERE u.password = :password")
        , @NamedQuery(name = "User.findByActive", query = "SELECT u FROM User u WHERE u.active = :active")
        , @NamedQuery(name = "User.findByCreatedDate", query = "SELECT u FROM User u WHERE u.createdDate = :createdDate")})
    public class User implements Serializable {

        @OneToMany(cascade = CascadeType.ALL, mappedBy = "userId")
        private List<Picture> pictureList;

        private static final long serialVersionUID = 1L;
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)

        @Column(name = "user_id")
        private Integer userId;

        @Column(name = "full_name")
        private String fullName;

        @Column(name = "address")
        private String address;

        @Column(name = "contact")
        private String contact;

        @Column(name = "gender")
        private String gender;
        @Column(name = "dob")
        @Temporal(TemporalType.DATE)
        private Date dob;
        // @Pattern(regexp="[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?", message="Invalid email")//if the field contains email address consider using this annotation to enforce field validation



        @Column(name = "email")
        private String email;



        @Column(name = "password")
        private String password;


        @Column(name = "active", insertable = false)
        private short active;
        @Column(name = "created_date", insertable = false)
        @Temporal(TemporalType.TIMESTAMP)
        private Date createdDate;

        public User() {
        }

        public User(Integer userId) {
            this.userId = userId;
        }

        public User(Integer userId, String fullName, String email, String password, short active) {
            this.userId = userId;
            this.fullName = fullName;
            this.email = email;
            this.password = password;
            this.active = active;
        }
//getter and setter

Picture.java - 实体类

    @Entity
    @Table(name = "tbl_picture")
    @NamedQueries({
        @NamedQuery(name = "Picture.findAll", query = "SELECT p FROM Picture p")
        , @NamedQuery(name = "Picture.findByPictureId", query = "SELECT p FROM Picture p WHERE p.pictureId = :pictureId")
        , @NamedQuery(name = "Picture.findByPictureName", query = "SELECT p FROM Picture p WHERE p.pictureName = :pictureName")})
    public class Picture implements Serializable {

        private static final long serialVersionUID = 1L;
        @Id
        @GeneratedValue(strategy = GenerationType.IDENTITY)

        @Column(name = "picture_id")
        private Integer pictureId;

        @Column(name = "picture_name")
        private String pictureName;
        @JoinColumn(name = "user_id", referencedColumnName = "user_id")
        @ManyToOne(optional = false)
        private User userId;

        public Picture() {
        }

        public Picture(Integer pictureId) {
            this.pictureId = pictureId;
        }

        public Picture(Integer pictureId, String pictureName) {
            this.pictureId = pictureId;
            this.pictureName = pictureName;
        }
//getter and setter

【问题讨论】:

    标签: json hibernate spring-mvc


    【解决方案1】:

    改变

    @OneToMany(cascade = CascadeType.ALL, mappedBy = "userId")
        private List<Picture> pictureList;
    

    到(解决方法)

    @OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL, mappedBy = "userId")
        private List<Picture> pictureList;
    

    为什么要解决?

    请记住,@OneToMany 默认使用 FetchType.LAZY,这意味着集合默认是延迟加载的,但更改为 EAGER 会带来另一个问题。将加载所有集合。

    Hibernate Docs 建议默认使用 LAZY,解决这个问题的另一种方法是添加 HibernateModule 并配置来处理这种情况。

    https://github.com/FasterXML/jackson-datatype-hibernate

    下面是如何实现模块:

    @Bean
    public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter() {
    
        MappingJackson2HttpMessageConverter messageConverter = new MappingJackson2HttpMessageConverter();
    
        ObjectMapper objectMapper = new ObjectMapper();
        Hibernate5Module hibernate5Module = new Hibernate5Module();
        hibernate5Module.disable(Hibernate5Module.Feature.USE_TRANSIENT_ANNOTATION);
        hibernate5Module.configure(Hibernate5Module.Feature.FORCE_LAZY_LOADING, false);
    
        objectMapper.registerModule(hibernate5Module);
        objectMapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY); //optional
    
        messageConverter.setObjectMapper(objectMapper);
    
        return messageConverter;
    }
    

    然后在扩展 WebMvcConfigurerAdapter 的类中

    @Override
    public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
        converters.add(mappingJackson2HttpMessageConverter());
    
        super.configureMessageConverters(converters);
    }
    

    【讨论】:

    • 多次取表的第一行
    • Hibernate5Module 的问题是它仍然坏掉了,你不能懒加载实体。您必须遍历所有要打印的实体及其子对象,以确保在分离它们和/或将它们传递给 Jackson 之前加载它们。
    猜你喜欢
    • 1970-01-01
    • 2021-02-19
    • 2020-05-13
    • 2019-05-29
    • 2019-05-15
    • 1970-01-01
    • 1970-01-01
    • 2017-12-25
    • 2016-08-15
    相关资源
    最近更新 更多