2

私は Glassfish 3.1 を持っていて、oneToMany 関係を持っています。エラーが発生し続ける:

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
}

そして豆:

@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

        }

                    ...

コードに関する提案はありますか?フォーラムに投稿された同様の質問は、残念ながら私にはうまくいきません。

4

2 に答える 2

4

group.getUsers() の呼び出しにより、この例外がスローされます。これは、JPA セッションでユーザー リストが取り込まれなかったためです。例外を回避するには、JPA セッションのスコープを終了する前に、遅延関係をトラバースする必要があります。

多くの場合、JPA セッション内で遅延ロードされたリストに対して 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;
}

JOIN FETCH を実行する別の方法:

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;
}
于 2012-12-11T19:35:06.693 に答える
0

フェッチ タイプを EAGER にしました。これがエラーを回避する唯一の方法でした。

@OneToMany(..., fetch=EAGER, mappedBy = "...")
于 2015-05-09T20:37:15.220 に答える