0
votes

I have two entities and a session bean as below:

@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();
    }

For testing purpose, I have manually loaded some managers with no departments in the database.

After a call to addDepartment(), a department is added successfully and the relationships is set up (the department record has a fk associated with the corresponding manager). The change is also shown when I call getAllDepartments(). However, if I call addDepartment() again, and call searchDepartmentByManager() by passing a detached manager object, the manager object that is returned by the entityManager.find() will not contain the department that has just been added. It will only become aware of the change when the entityManager.refresh(manager) is called.

What I don't understand is that, why doesn't the entityManager.find() returns a manager with the latest data? I checked that in the database between calling addDepartment() and searchDepartmentByManager() and the department object is added successfully at the time. Somehow it just doesn't show up in the entityManager.find() until the entityManager.refresh(manager) is called. I have a feeling it is about the scope and lifetime of the persistence context and I would like to find out the details about it.

I would really appreciate if someone can answer this questions.

With thanks, Peter.

1

1 Answers

0
votes

With entityManager.find(...) if the Manager entity instance is contained in the persistence context, it is returned from there.

With entityManager.refresh(...) the Manager entity instance will be overwritten with the values from the DB.

What I suspect is happening is that the Manager instance you are passing to searchDepartmentByManager(...) is not detached. It seems to be attached to the persistence context and it is outdated (since it does not have the latest Department(s)).

You can try persisting/merging the entities in the right order to maintain parent-child responsibility of the mapping. This is described over here. (note that the link talks about one to one relationship but the solution should apply to all types of bidirectional relationships)