java - 如何避免使用 MOXy 加载惰性双向关系?

标签 java jpa jaxb eclipselink moxy

我的问题是 this 的后续问题评论。

我在同一个类上混合使用 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;

    [...]
}

现在,我将使用如下的 JAX-RS 方法在 Phone 上运行查询(使用底层 EJB):

@Inject
private PhoneService phoneService;

@GET
@Path( "/phones" )
public List<Phone> getPhonesByNumber( @QueryParam( "number" ) String number ) {
    List<Phone> result = phoneService.getPhonesByNumber( number );

    return result;
}

发生的情况是这样的:PhoneService EJB 中的 JPQL 查询会触发 Phone 表上的 SQL SELECT(按号码过滤),并且如果我使用 JOIN FETCH 查询,我可以使用相同的单个 SELECT 语句获取关联的 Employee

当 JAX-RS 方法返回时,JAXB 编码启动,这会导致额外的 SQL SELECT:此选择选择其 employeeID 指向的所有 Phone与最初请求的电话关联的Employee。因此,从 EmployeePhone 的惰性关系现在已经解决,大概是因为 MOXy 必须能够确定原始 Phone 是否包含在集合中.

我已尝试按照其他线程中的建议对 phones 字段使用 JPA 属性访问和 JAXB 字段访问,但无济于事。我还尝试在从 EJB 检索结果后(即当我的实体已分离时)将链接的 Employee 实例中的 Phones 字段清空,但这导致了再次立即执行 SQL SELECT(似乎只要对 IndirectList 进行任何操作,EclipseLink 就会执行此操作?)。我能找到的唯一解决方案是将 MOXy @XmlNamedObjectGraph 与排除 phones 字段的子图一起使用。但这是不切实际的,特别是当涉及的实体具有许多属性时。

因为我可能也需要向另一个方向查询,例如员工的姓名及其关联的电话,我不能只将电话标记为@XmlTransient

有人有一个优雅的解决方案来抑制这些额外的 SQL 语句吗?

最佳答案

根据我的经验,完成您尝试的操作的最简单方法是在将所有实体类传递到 JAX-RS Rest api 等表示层之前分离它们。您甚至可以使用@OneToMany(mappedBy = "employee", cascade = CascadeType.DETACH)EntityManager.detach()分离您的电话类别,然后分离您的员工类别,反之亦然。这将确保在编码实体期间,Jax-RS 不会触发您通常不需要的任何 SELECT 语句。

我总是在将模型实体传递到表示层之前分离它们,以便它们可以按照自己的意愿与模型类交互,而不会影响性能或数据库。

关于java - 如何避免使用 MOXy 加载惰性双向关系?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30163294/

相关文章:

Java 编码和解码

java - 永久内存不足 | java |智能

java - 在黑莓上使用 HttpCore

java - 从 hibernate 查询中获取通用对象

java - eclipselink jpa 运算符详细信息

java - Spring boot 无法评估表达式方法抛出 'org.hibernate.LazyInitializationException' 异常。使用 getter,多对多关系

java - Android Studio 前端客户端 [从设备运行] 未连接到 Google AppEngine 后端

java - 文字位于圆圈中心

java - 当 JAXB 编码(marshal)可匹配两种类型的 XML 时,JAXB 如何决定创建哪种类型?

java - 在 java 中解码 xml 时在 CDATA 中保留新行