Community
Participate
Working Groups
Hi, I am facing an issue related to Eclipselink and the maintenance of bi-directional relations. I have an EJB 3.0 application using JPA 1.0 which is deployed in Glassfish 2.1.1. The application has 2 entities, User and UserGroup, which have a one-to-many relation between them, that is: User refers to an UserGroup and it is the owner of the relation while UserGroup has a collection of multiple Users. The following code is executed inside EJB container in order to create both User and UserGroup. UserGroup group = new UserGroup(); group.setName("grup"); User user = new User(); user.setName("user"); user.setUserGroup(group); // group.setUsers(new ArrayList<User>()); // group.getUsers().add(user); return local.create(user); After execution, the transaction is finished and the entries are created in the database. When I try to get the previously created UserGroup to see if it contains the associated User it doesn't work, both System.out shows a size of 0. idUser = the id of the previously create User local.getUserGroup call search the UserGroup by ID using EntityManager.find() User u = local.getUser(idUser); System.out.println(u.getUserGroup().getUsers().size()); UserGroup ug = local.getUserGroup(u.getUserGroup().getIdUserGroup()); System.out.println(ug.getUsers().size()); However, if I uncomment the lines // group.setUsers(new ArrayList<User>()); // group.getUsers().add(user); the size is 1, as expected. But this works only because I manually maintain the bi-directional relationship. The size should always be 1 if Eclipselink maintains the bi-directional relationships. This could of course be fixed if a refresh() is done after getting the UserGroup from cache. But according to EJB 3.0 Specification, section 8.4.2., inside an EJB container, the JPA provider is responsible for maintaining both ends of a bidirectional relation: The container maintains the relationships among entity beans. • It is the responsibility of the container to maintain the referential integrity of the container-managed relationships, as described in Section 8.3.6, in accordance with the semantics of the relationship type as specified in the deployment descriptor. For example, if an entity bean is added to a collection corresponding to the container-managed relationship field of another entity bean, the container-managed relationship field of the first entity bean must also be updated by the container in the same transaction context. persistence.xml is configured to use a shared cache and to weave lazy relationships. Also the property eclipselink.target-server is set to SunAS9 I attached the User, UserBean and persistence.xml files.
Created attachment 179623 [details] User, UserGroup and persistence.xml files It seems that the files were not attached on first attempt.
Setting as a duplicate of an existing enhancemetn request. Please vote for that issue if it is important to you. Note: The JPA specification says the following in section 2.1.7: "Note that it is the application that bears responsibility for maintaining the consistency of runtime relationships—for example, for insuring that the “one” and the “many” sides of a bidirectional relationship are consistent with one another when the application updates the relationship at runtime." If you only want to set the owning side of a relationship, you will have to do a refresh after the object is flushed to the DB. The other option is to set both sides as you have observed. *** This bug has been marked as a duplicate of bug 297399 ***
Thank you for your quick feedback. It is true that JPA specification mentions the fact that it is application's responsibility to maintain both ends of a bi-directional relation. But isn't this applying only in the case where JPA is used inside a Java SE application? The sample application I have runs inside Glassfish thus it uses EJB and in the EJB 3.0 Specification, section 8.4.2 it states that: "The container maintains the relationships among entity beans. • It is the responsibility of the container to maintain the referential integrity of the container-managed relationships, as described in Section 8.3.6, in accordance with the semantics of the relationship type as specified in the deployment descriptor. For example, if an entity bean is added to a collection corresponding to the container-managed relationship field of another entity bean, the container-managed relationship field of the first entity bean must also be updated by the container in the same transaction context." Also, in the same specifications, in section 8.3.6.1, it states that: "• If the argument to the add method is already an element of a collection-valued relationship field of the same relationship type as the target collection (as defined by the ejb-relation and ejb-relationship-role deployment descriptor elements), it is removed from this first relationship and added, in the same transaction context, to the target relationship (i.e., it is effectively moved from one collection of the relationship type to the other). For example, if there is a one-to-many relationship between field offices and sales representatives, adding a sales representative to a new field office will have the effect of removing him or her from his or her current field office. If the argument to the add method is not an element of a collection-valued relationship of the same relationship type, it is simply added to the target collection and not removed from its current collection, if any." Isn't Eclipselink following these specifications? The duplicate bug doesn't mention in which cases Eclipselink is responsible or not for maintaining the bi-directional relationships. I think there is a difference between Java SE and Java EE applications that is why I am reopening this bug.
Marking as a duplicate again. The EJB 3.0 specification deals with multiple types of persistence. 1. Java Persistence i.e. JPA. This is the new persistence spec. 2. Container Managed Persistence. CMP. This is the legacy Enterprise specification, but, I believe, containers are required to continue to support this spec as part of the backward compatibility commitment in Java. The paragraphs you are quoting relate to CMP. There is an available CMP implementation based on the same code as EclipseLink - TopLink, but it is not available in Open source. *** This bug has been marked as a duplicate of bug 297399 ***
Switching to Toplink is not an option, we just dropped it because it has a lot of other issues. But at least this clarifies it, thank you.
The Eclipselink project has moved to Github: https://github.com/eclipse-ee4j/eclipselink