我有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
}
...
有关代码的任何建议吗? 遗憾的是,论坛上发布的类似问题对我无效。
答案 0 :(得分:4)
对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;
}
执行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;
}
答案 1 :(得分:0)
我制作了获取类型EAGER,这是我弄清楚如何避免错误的唯一方法:
@OneToMany(..., fetch=EAGER, mappedBy = "...")