我有两个实体和一个会话bean,如下所示:
@Entity
public class Manager {
@Id
private int managerId;
private String name;
@OneToMany(mappedBy = "manager")
private Set<Department> departments;
//... constructors, getters and setters
}
@Entity
public class Department {
@Id
private int departmentId;
@ManyToOne
private Manager manager;
//... constructors, getters and setters
}
@Stateless
public class JPADao {
@PersistenceContext
private EntityManager entityManager;
@Override
public void addDepartment(Department department) throws Exception {
entityManager.persist(department);
}
@Override
public List<Property> getAllDepartments() throws Exception {
return entityManager.createNamedQuery("SELECT d FROM Department d").getResultList();
}
@Override
public Set<Department> searchDepartmentByManager(Manager manager) throws Exception {
manager = entityManager.find(Manager.class, manager.getManagerId());
manager.getDepartments().size();
entityManager.refresh(manager); //it won't work if I remove this line
return manager.getDepartments();
}
出于测试目的,我手动加载了一些没有部门的管理员。
调用addDepartment()
后,成功添加部门并建立关系(部门记录与相应的经理相关联的fk)。当我呼叫getAllDepartments(
时,也会显示更改。但是,如果我再次调用addDepartment()
并通过传递分离的管理器对象来调用searchDepartmentByManager()
,则entityManager.find()
返回的管理器对象将不包含刚刚添加的部门。只有在调用entityManager.refresh(manager)
时才会发现变化。
我不明白的是,为什么entityManager.find()
不会向经理发送最新数据?我在数据库中检查了调用addDepartment()
和searchDepartmentByManager()
之间的情况,并且当时成功添加了部门对象。不知怎的,它只是在调用entityManager.find()
之前不会出现在entityManager.refresh(manager)
中。我有一种关于持久化上下文的范围和生命周期的感觉,我想找出有关它的详细信息。
如果有人能回答这个问题我真的很感激。
谢谢, 彼得。
答案 0 :(得分:0)
如果entityManager.find(...)
实体实例包含在持久性上下文中,则使用Manager
,从那里返回它。
使用entityManager.refresh(...)
,Manager
实体实例将被数据库中的值覆盖。
我怀疑发生的事情是,您传递给Manager
的{{1}}实例未被分离。它似乎附加到持久性上下文和它已过时(因为它没有最新的searchDepartmentByManager(...)
(s))。
您可以尝试以正确的顺序持久化/合并实体,以维护映射的父子责任。这是在here上描述的。 (请注意该链接涉及一对一关系,但解决方案应适用于所有类型的双向关系)