【问题标题】:Convert Hibernate entity to json using JSONArray.fromObject使用 JSONArray.fromObject 将 Hibernate 实体转换为 json
【发布时间】:2011-02-02 13:15:39
【问题描述】:

我在将数据转换为 json 时遇到问题。

Session session = sessionFactory.openSession();       
Affiliate affiliate = (affiliate) session.get( Affiliate , pk );
session.close();
JSONArray.fromObject(affiliate);

调试器显示该行已被提取。
但是在尝试转换为 json 字符串时出现此异常:

Exception in thread "main" net.sf.json.JSONException: org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role: com.affiliates.hibernate.Affiliate.employees, no session or session was closed
at net.sf.json.JSONObject._fromBean(JSONObject.java:959)    ...

这是我的附属实体

    @Entity(name="AFFILIATE")
    @Inheritance(strategy=InheritanceType.SINGLE_TABLE)
    public class Affiliate extends HibernateBean{ 

        @Id
        @GeneratedValue(strategy=GenerationType.IDENTITY) 
        @Column(name="AFFILIATE_ID")
        private long id;

        @ManyToOne(targetEntity = Affiliate.class)
        @JoinColumn(name="PARENT_ID")
        private Affiliate parent;



        @ManyToMany(cascade=CascadeType.ALL,fetch=FetchType.LAZY)
        @JoinTable(name="EMPLOYEES_AFFILIATES"  , joinColumns = {@JoinColumn(name="AFFILIATE_ID")},inverseJoinColumns={@JoinColumn(name="EMPLOYEE_ID")})
        private Set<Employee> employees = new HashSet<Employee>(0);

 getters and setters...

    }

谢谢

【问题讨论】:

    标签: java json hibernate


    【解决方案1】:

    您的employees 集合被标记为FetchType.LAZY,因此它是延迟获取的,并且在会话关闭时无法获取。

    您有多种选择:

    • 如果每次加载 Affiliate 对象时都需要该集合,请将其标记为急切获取:

      @ManyToMany(cascade=CascadeType.ALL,fetch=FetchType.EAGER) 
      
    • 如果您只在这种特殊情况下需要该集合,请指示 Hibernate 在这种情况下急切地加载它:

      • 带有JOIN FETCH 子句:

        Affiliate affiliate = (Affiliate) session.createQuery(
            "from Affiliate a join fetch a.employees where a.id = :id")
            .setParameter("id", pk).uniqueResult()
        
      • Hibernate.initialize():

        Affiliate affiliate = (Affiliate) session.get( Affiliate , pk );  
        Hibernate.initialize(affiliate.getEmployees());
        
      • Fetch Profiles

    • 在响应准备好之前不要关闭会话。使用Open Session in View 模式。

    【讨论】:

    • 谢谢,我不明白一件事,fetch lazy 意味着emplyees 将是空的,不是吗? ...因为如果我正在编写affiliate.setEmployees(null),它工作正常。这就是我理解的 fetch lazy 假设要做的事情,将员工设置为 null。
    • @fatnjazzy:延迟获取意味着employees 是一个代理集合,它会在您访问它时尝试获取实际项目。
    【解决方案2】:

    如果您不更改数据库,请不要更改实体。他们应该匹配。将实体上的 fetch 更改为 Eager 会破坏延迟加载的整个想法,并且您的代码中可能还有其他地方会因此而引入性能问题。这就是说,如果您更改实体,那么任何地方的每个人都必须在每次使用该实体时加载所有数据。

    你想要的是一个嵌套事务。在进行 JSON 转换的方法调用开始时开始您的事务,并在方法结束时结束它。为此,只需向包含此 JSON 转换的方法调用添加事务注释即可。

    完成此操作后,当需要信息时事务不会结束,然后可以进行延迟加载。代码中可能还有其他地方可以做到这一点。寻找它们并将它们用作示例,以作为您的解决方案的基础。

    当然,如果您将在多个地方使用它,您可能希望将其实际推送到您的 DAO 中,以便重复使用。

    【讨论】:

      猜你喜欢
      • 2013-08-08
      • 1970-01-01
      • 1970-01-01
      • 2021-11-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-10-14
      • 2016-06-18
      相关资源
      最近更新 更多