Мой вопрос является продолжением этого комментарий.
Я смешиваю аннотации JPA и JAXB (MOXy) в одном классе, что в большинстве случаев работает нормально. Как описано в связанном потоке, @XmlInverseReference
предотвращает исключения цикла при упорядочивании двунаправленных отношений. Но чтобы обнаружить цикл, MOXy должен проверить обратную ссылку связанного объекта, что приводит к дополнительным SQL-запросам SELECT, если необходимо заполнить ленивое отношение.
Чтобы подробно проиллюстрировать проблему, рассмотрим этот выдуманный пример:
@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;
[...]
}
Теперь я бы выполнял запросы к Phone
s с помощью такого метода JAX-RS (используя базовый EJB):
@Inject
private PhoneService phoneService;
@GET
@Path( "/phones" )
public List<Phone> getPhonesByNumber( @QueryParam( "number" ) String number ) {
List<Phone> result = phoneService.getPhonesByNumber( number );
return result;
}
Происходит следующее: запрос JPQL в PhoneService
EJB запускает SQL SELECT для таблицы Phone
(отфильтрованной по номеру), и если я использую запрос JOIN FETCH
, я могу получить связанный Employee
с помощью того же единственного оператора SELECT.
Когда метод JAX-RS возвращается, срабатывает сортировка JAXB, которая приводит к дополнительному SQL SELECT: он выбирает все Phone
, employeeID
которых указывает на Employee
, который связан с первоначально запрошенными Phone
. Таким образом, ленивое отношение от Employee
к Phone
теперь разрешено, предположительно потому, что MOXy должен иметь возможность определять, содержится ли исходный Phone
в коллекции.
Я пробовал использовать доступ к свойствам JPA и доступ к полю JAXB для поля phones
, как было предложено в другом потоке, но безрезультатно. Я также пробовал обнулить поле phones
в связанном экземпляре Employee
после получения результата из EJB, то есть когда мои объекты уже отсоединены, но это снова привело к немедленному SQL SELECT (похоже, EclipseLink сделает это всякий раз, когда манипуляции сделаны с IndirectList
?). Единственное обходное решение, которое я смог найти, - это использовать MOXy @XmlNamedObjectGraph
s с подграфом, исключающим поле phones
. Но это непрактично, особенно если задействованные сущности имеют много атрибутов.
Поскольку мне может потребоваться запрос в другом направлении, например сотрудников по именам с соответствующими телефонами, я не могу просто пометить phones
как @XmlTransient
.
Есть ли у кого-нибудь элегантное решение для подавления этих лишних операторов SQL?