2012-12-11 35 views
2

我有Glassfish 3.1,並且我得到了一對多的關係。不斷收到錯誤:Glassfish中的LAZY關係實例化問題

Exception Description: An attempt was made to traverse a relationship using indirection that had a null Session. This often occurs when a n entity with an uninstantiated LAZY relationship is serialized and that lazy relationship is traversed after serialization. To avoid this issue, ins tantiate the LAZY relationship prior to serialization. 

用戶實體。

@Entity 
@Table(name="USERS") 
public class User implements Serializable 
{ 
    private static final long serialVersionUID = -8636046618352460140L; 
    @Id 
    @GeneratedValue(strategy=GenerationType.AUTO) 
    private long userId; 
    private String userName; 
    private int userAge; 
    private double latitude; 
    private double longitude; 

    public User() { 

    } 

// getters & setters 
} 

集團實體

@Entity 
@Table(name="USERS_GROUPS") 
public class Group implements Serializable 
{ 
    private static final long serialVersionUID = -9124043819358665396L; 
    @Id 
    @GeneratedValue(strategy=GenerationType.AUTO) 
    private long groupId; 
    private String groupName; 
    @OneToMany(cascade=CascadeType.PERSIST, fetch=FetchType.EAGER) 
    @JoinTable(name="JOIN_USER_GROUP", 
      joinColumns={@JoinColumn(name="groupId")}, 
      inverseJoinColumns={@JoinColumn(name="userId")}) 
    private List<User> users = null; 

    public Group() { 

    } 
// getters & setters 
} 

和bean:

@PersistenceContext 
private EntityManager em; 
    ... 
public Group searchGroup(String groupName) { 
    Query q = em.createQuery("SELECT g FROM Group g " + 
      "WHERE g.groupName = :name"); 
    q.setParameter("name", groupName); 
    Group result = (Group) q.getResultList().get(0); 
    result.getUsers().size(); // << LAZY instantiation 
    return result; 
} 
// NOT TESTED 
public void updateGroup(Group group) 
{ 
    em.merge(group); 
} 

    ... 

客戶試車手:

public static void main(String[] args) 
{ 
    try 
    { 
     Context jndi = new InitialContext(); 

     GroupManagementService service = (GroupManagementService) 
        jndi.lookup("java:global/GroupsManagement/GroupManagementServiceImp"); 

     User u = new User("John", 20, 54.04, 0.4); 

        // the group home is already in a database 
     Group group = service.searchGroup("home"); 

        group.getUsers().add(u); // << ERROR here 
        service.updateGroup(group); 

        /* IF do this */ 
     List<User> l = group.getUsers(); 
     if(l == null) 
      System.out.println("NULL"); 
     else { 
      System.out.println("SIZE: "+l.size()); // << ERROR here 

     } 

        ... 

有關的代碼有什麼建議? 在論壇上發佈的類似問題,不幸的是不適合我。

回答

3

對group.getUsers()的調用導致拋出此異常,因爲用戶列表從未在JPA會話中填充過。在退出JPA會話的範圍之前,必須遍歷惰性關係以避免異常。

在許多情況下,只需在JPA Session內的懶惰加載列表上調用size()將解決該異常。

public Group searchGroup(String groupName) { 
    Query q = em.createQuery("SELECT g FROM Group g " + 
     "WHERE g.groupName = :name"); 
    q.setParameter("name", groupName); 
    Group result = (Group) q.getResultList().get(0); 
    result.getUsers().size(); // << LAZY instantiation 
    return result; 
} 

但是,在某些情況下.size()本身無法解決問題。當發生這種情況時,與JOIN FETCH結合使用時,我發現它起作用。

public Group searchGroup(String groupName) { 
    Query q = em.createQuery("SELECT g FROM Group g LEFT JOIN FETCH g.users " + 
     "WHERE g.groupName = :name"); 
    q.setParameter("name", groupName); 
    Group result = (Group) q.getResultList().get(0); 
    result.getUsers().size(); // << LAZY instantiation 
    return result; 
} 

進行連接抓取的另一種方法:

public Group searchGroup(String groupName) { 
    Query q = em.createQuery("SELECT g FROM Group g " + 
     "WHERE g.groupName = :name"); 
    q.setParameter("name", groupName); 
    q.setHint("eclipselink.left-join-fetch","g.users"); // << join fetch as hint 
    Group result = (Group) q.getResultList().get(0); 
    result.getUsers().size(); // << LAZY instantiation 
    return result; 
} 
+1

好的,我修好了。我從Glassfish中刪除了我的ejb.jar文件並部署了一個新文件。 我還添加了'service.updateGroup(group);'到'searchGroup'方法。但是,這並沒有什麼區別,因爲當我評論它的應用程序仍然有效。 如何評論這種奇怪的行爲? – alex

+0

您可以使用修補程序進行編輯嗎? – user1598246

+0

發表評論時出錯。我編輯了'result.getUsers()。size()' – alex

0

我做了獲取類型躍躍欲試,這是我能想出如何避免錯誤的唯一方法:

@OneToMany(..., fetch=EAGER, mappedBy = "...")