我是JPA 2.0的新手,很少有我不理解的东西。
我有几张桌子:
CUST table (for customers)
--------------------------
CUST_ID (pk, integer)
CUST_NAME (varchar)
和
ORD table (for orders)
----------------------
ORD_ID (pk, integer)
ORD_STATUS (char) can be: 'N' for new, 'S' for shipped, 'D' for delivered
CUST_ID (fk, integer)
这种关系是一个简单的“一对多”(每个客户都可以下多个订单)。
表格内容:
CUST_ID | CUST_NAME
-------------------
1 | elcaro
2 | tfosorcim
3 | elppa
和
ORD_ID | ORD_STATUS | CUST_ID
-----------------------------
2 | N | 1
3 | N | 1
4 | N | 1
5 | S | 1
6 | S | 1
7 | D | 1
8 | D | 1
9 | D | 1
10 | D | 2
11 | N | 2
12 | S | 3
13 | S | 3
以下是我对我的课程进行注释的方法:
@Entity(name = "Customer")
@Table(name = "CUST")
public class Customer implements Serializable
{
private static final long serialVersionUID = 1L;
@Id
@Column(name = "CUST_ID")
private Integer id;
@Column(name = "CUST_NAME")
private String name;
@OneToMany(mappedBy = "customer")
private List<Order> orders;
// Default constructor, getters and setters (no annotations on these)
}
和
@Entity(name = "Order")
@Table(name = "ORD")
public class Order implements Serializable
{
private static final long serialVersionUID = 1L;
@Id
@Column(name = "ORD_ID")
private Integer id;
@Column(name = "ORD_STATUS")
private Character status;
@ManyToOne
@JoinColumns
(
{
@JoinColumn(name = "CUST_ID", referencedColumnName = "CUST_ID")
}
)
private Customer customer;
// Default constructor, getters and setters (no annotations on these)
}
一切正常,以下JPQL查询产生我期望的结果:
`select c from Customer c`
它返回三个Customer类型的对象,每个对象都包含属于该客户的订单。
但是现在,我想要提取状态为“N”的订单的客户列表以及相关订单(当然只有状态“N”订单)。 回到好日子,我会编写一个像这样的SQL查询:
select c.cust_id,
c.cust_name,
o.ord_id,
o.ord_status
from cust c
inner join ord o on (o.cust_id = c.cust_id)
where o.ord_status = 'N'
它将返回以下结果集:
CUST_ID | CUST_NAME | ORD_ID | ORD_STATUS
-----------------------------------------
1 | elcaro | 2 | N
1 | elcaro | 3 | N
1 | elcaro | 4 | N
2 | tfosorcim | 11 | N
但是,以下JPQL查询不会产生预期结果:
`select distinct c from Customer c join c.orders o where o.status = 'N'`
它返回正确的客户组(客户'elppa'没有任何状态'N'订单并被正确排除),但每个客户都包含完整的订单集,无论状态如何。 似乎只评估'where'子句以确定必须提取哪组客户,然后持久性提供程序开始导航关系以提取完整的订单集。 稍微思考一下,我必须承认这是有道理的。
然后我尝试了另一个JPQL查询:
`select c, o from Customer c join c.orders o where o.status = 'N'`
此JPQL查询产生的结果与前一个SQL查询产生的结果类似:每个结果(按预期结果为4个结果)是一个2对象数组,第一个对象是Customer类型,第二个对象是类型订购。但是,同样,Customer类型的对象包含完整的相关订单(如我所料,这次)。更不用说现在订单不包含在Customer对象中,而是单独返回,就像在SQL结果集中一样。
现在的问题是: 是否有可能编写一个JPQL查询,不仅过滤掉状态为“N”的订单的客户,而且过滤掉状态为“N”的相关订单(在关系导航期间获取)? 我希望能得到的是2个客户的结果,其中每个客户仅包含其状态“N”订单。
我阅读了Java EE 6教程,其中一个示例(订单应用程序)有一个类似于我的模式,但我找不到这样的查询(在下载的源代码中)。
虽然我认为以上是标准行为,但我使用Oracle Weblogic 12c服务器(通过其Eclipse适配器),持久性提供程序似乎是EclipseLink。
提前致谢。
致以最诚挚的问候,
斯特凡诺
答案 0 :(得分:4)
JPA处理对象,对象具有标识,无论查询方式如何,都是相同的。无论您的where子句是什么,返回的Customer对象仍然是相同的Customer对象,并且应该具有相同的关系。这对于缓存,对象标识和一致性非常重要。
您的第二个查询可能是您想要的正确方法。可以使用JOIN FETCH上的别名(从EclipseLink 2.4开始)执行您尝试执行的操作,但不建议这样做。
请参阅, http://wiki.eclipse.org/EclipseLink/UserGuide/JPA/Basic_JPA_Development/Querying/JPQL#JOIN_FETCH