My question is a comment on this .
I mix JPA and JAXB (MOXy) annotations in the same class, which works great in most cases. As described in the linked thread, @XmlInverseReference prevents circular exceptions when bidirectional relationships are sorted. But in order to detect the loop, MOXy must check the backlink of the related object, which leads to additional SQL SELECT if you need to fill in the lazy relation.
To illustrate the problem in detail, consider this example:
@Entity @Access( AccessType.FIELD ) @XmlRootElement @XmlAccessorType( XmlAccessType.FIELD ) public class Phone { @ManyToOne @JoinColumn( name = "employeeID" ) @XmlElement( name = "employee" ) @XmlInverseReference( mappedBy = "phones" ) private Employee employee; private String number; [...] } @Entity @Access( AccessType.FIELD ) @XmlRootElement @XmlAccessorType( XmlAccessType.FIELD ) public class Employee { @OneToMany( mappedBy = "employee" ) @XmlElementWrapper( name = "phones" ) @XmlElement( name = "phone" ) @XmlInverseReference( mappedBy = "employee" ) private List<Phone> phones; private String name; [...] }
Now I will run queries on Phone using this JAX-RS method (using basic EJB):
@Inject private PhoneService phoneService; @GET @Path( "/phones" ) public List<Phone> getPhonesByNumber( @QueryParam( "number" ) String number ) { List<Phone> result = phoneService.getPhonesByNumber( number ); return result; }
What happens: The JPQL query in PhoneService EJB starts SQL SELECT in the Phone table (filtered by number), and if I use the JOIN FETCH query, I can get the associated Employee with the same SELECT statement.
When the JAX-RS method returns, JAXB marshalling is triggered, resulting in an additional SQL SELECT: this selects all the Phone whose employeeID points to Employee , which is associated with the originally requested Phone s. So the lazy relationship from Employee to Phone is now resolved, apparently because MOXy should be able to determine if the original Phone in the collection.
I tried using access to JPA properties and access to JAXB fields for the phones field, as suggested in another thread, to no avail. I also tried to reset the phones field in the associated Employee instance after getting the result from EJB, that is, when my objects were already detached, but this again led to an immediate SQL SELECT (it seems that EclipseLink will do this whenever any manipulations are performed with IndirectList ?). The only workaround I could find was to use MOXy @XmlNamedObjectGraph with a subgraph that excludes the phones field. But this is impractical, especially if the objects involved have many attributes.
How may I need to execute the request in a different direction, for example. employees by name with their phones, I can’t just mark phones as @XmlTransient .
Does anyone have an elegant solution to suppress these extra SQL queries?