使用内连接

时间:2017-06-09 19:53:18

标签: java eclipselink jpa-2.0

我有以下情况:

@Entity
@XmlRootElement
@Table(name = "TB_A")
public class A implements Serializable {

    @OneToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "CD_B")
    private B b;

}

@Entity
@XmlRootElement
@Table(name = "TB_B")
public class B implements Serializable {

    @OneToMany(fetch = FetchType.EAGER, cascade = CascadeType.ALL)
    @JoinColumn(name = "CD_B")
    @JsonIgnore
    private Set<C> c = new HashSet<>();

}

@Entity
@XmlRootElement
@Table(name = "TB_C")
public class C implements Serializable {

    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "CD_B")
    private B b;

}

我需要运行以下代码:

String sql = "SELECT * FROM TB_A a "
            + "INNER JOIN TB_B b ON ... "
            + "LEFT JOIN TB_C c ON ... ";

Query query = em.createNativeQuery(sql, A.class);

List<A> AList = query.getResultList();

for(A a : AList) {
    List<c> CList = a.getB().getC();
}

对已执行的查询进行分析,我注意到每次访问元素B和C时JPS都在运行SELECT。

如何正确映射此nativeQuery以使用lazyLoad?

  • Obs:我必须使用NativeQuery,因为在我的WHERE子句中,我需要使用Oracle的特定功能。所以JPQL对我来说不是一个选择(如果我可以使用它,我的生活会更容易!)。

1 个答案:

答案 0 :(得分:1)

简短的回答:你做不到。

这一行将做什么:

Query query = em.createNativeQuery(sql, A.class);

执行你的SQL,然后扔掉任何与A.class无关的东西。

然后你的for循环:

for(A a : AList) {
    List<c> CList = a.getB().getC();
}

再次获取一切。
在这里,您再次使用JPA,它对您之前执行的查询一无所知。

在某些情况下,您可以尝试映射到C.class 然后你就可以完全避免循环。
如果在您的情况下您需要A.class和C.class,则可以查看ResultSetMapping:http://www.java2s.com/Tutorial/Java/0355__JPA/SqlResultSetMappingForHierarchicalEntity.htm