1.查询关联实体:
(1)在一对一关连查询中,可以直接通过引用其关联属性来查询:
select c.address from Customer c
JPA实现者会根据实体映射的关系自动关联所对应的实体。
(2)在一对多中,可以通过IN
select c.name,o from Customer c, in (c.orders) o
其中o为集合的别名。
2.内连接:
查询所有客户和他所属的订单(若客户无订单是查询不到的):
select c,order from Customer c (inner) join c.orders order
inner可以不写,默认inner。
等价于:
select c,order from Customer c,in (c.orders) order
3.左连接:
即左外连接,客户无订单是可以查到的,但其订单为null值:
select c,order from Customer c left (outer) join c.orders order
4.抓取连接(在join后面加上fetch),针对延迟加载:
select c,order from Customer c join fetch c.orders order
select c,order from Customer c left join fetch c.orders order
例如:customer的order为延迟加载
@OneToMany(mappedBy="customer",fetch=FetchType.LAZY) public Set<Order> getOrders(){ return orders; }
在关联查询中,若使用
select c from customer c join c.orders o
返回的customer对象并没有加载所关联的orders属性,此时在客户端调用getOrders方法时会抛出异常。因此改为:
select c from customer c join fetch c.orders o
此时返回的customer对象加载了所关联的orders属性。
-------------------------------------------------------------------------------------------------------------------------------------
这里的join fetch 跟下面的代码是什么关系?---上面的是通过Query,下面这个则是通过find。
两者什么区别和联系?
及时加载和延迟加载 @PersistenceContext protected EntityManager em; public Customer findCustomerById(Integer customerId){ Customer customer=em.find(Customer.class,customerId); return customer; }
由于customer和address为一对一关系,默认为及时加载,所以在find customer的时候,
其实select语句是左连接address,同时取出关联address的。
如果改为延迟加载:
@OneToOne(cascade=CascadeType.PERSIST,fetch=FetchType.LAZY) @JoinColumn(name="address_id") public Address getAddress(){ return this.address; } 则在session bean中的find方法:@PersistenceContext protected EntityManager em; public Customer findCustomerById(Integer customerId){ Customer customer=em.find(Customer.class,customerId); //通过调用延迟加载关联的address customer.getAddress(); return customer; } 其实分两个select语句来实行,一个是先select customer,第二个是通过where address_id来select关联的address 如果客户端要使用customer的getAddress()方法,则必须在session bean中延迟加载customer.getAddress(),否则 客户端调用时会报错。延迟加载只能在持久化上下文(session bean)中执行。