2011-02-02 52 views
2

我在将数据转换为json时遇到问题。使用JSONArray.fromObject将Hibernate实体转换为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... 

    } 

感谢

回答

6

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模式。

+0

谢谢,我不明白一件事,取懒意味着emplyees将是空的,不是? ...因为如果我正在写affiliate.setEmployees(null),它工作正常。这是我理解提取懒惰假设要做的,将emplyees设置为null。 – fatnjazzy 2011-02-02 14:15:04

0

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

你想要的是一个嵌套事务。在执行JSON转换的方法调用的开始处开始您的事务,并在方法结束时结束它。通过简单地向包含此JSON转换的方法调用添加事务注释来实现此目的。

完成此操作后,事务将不会在需要信息时发生并且可能发生延迟加载。可能在代码中还有其他地方完成此操作。寻求他们,并用它们作为示例,从而解决您的解决方案。

当然,如果您将在很多地方使用此功能,您可能需要实际将其推入DAO中,以便重复使用。