hibernate的抓取策略和JPA的抓取策略

所谓“抓取策略”,总要涉及两个问: 何时抓取(是否延迟加载)以及如果抓取 。这两点在Hibernate提供的注解上体现的非常明显。

Hibernate提供两套注解分别用来描述“何时抓取”和“如何抓取”。这样看起来非常条理和清晰。
但是JPA没有这么做。它只提供了fetch=FeatchType.LAZY or FetchType.EAGER.但是我们必须明白这两种选项对应的实际抓取策略是什么。

测试用例:
@Test
public void testFetch(){

    Session session = HibernateUtil.openSession();

    Customer customer = session.get(Customer.class, 1);
    System.out.println(customer.getOrders());//是否延迟加载

    session.close();
}

一、JPA抓取策略

它对于lazy和eager只各提供一种抓取方法,不需要再指定“如何抓取”
1、fetch=FetchType.LAZY:何时抓取:lazy,如何抓取:select(默认)
@OneToMany(mappedBy = "customer", cascade = {CascadeType.ALL}, fetch=FetchType.LAZY)
private Set<Order> orders = new HashSet<Order>();
2、fetch=FetchType.EAGER:何时抓取:eager,如何抓取:join
@OneToMany(mappedBy = "customer", cascade = {CascadeType.ALL}, fetch=FetchType.EAGER)
private Set<Order> orders = new HashSet<Order>();

二、Hibernate抓取策略

1、延迟加载和非延迟加载
延迟
@OneToMany(mappedBy = "customer", cascade = {CascadeType.ALL})
@LazyCollection(LazyCollectionOption.TRUE)
private Set<Order> orders = new HashSet<Order>();
非延迟
@OneToMany(mappedBy = "customer", cascade = {CascadeType.ALL})
@LazyCollection(LazyCollectionOption.FALSE)
private Set<Order> orders = new HashSet<Order>();

3、抓取策略(*对多)
默认
@OneToMany(mappedBy = "customer", cascade = {CascadeType.ALL})
@LazyCollection(LazyCollectionOption.FALSE)
@Fetch(FetchMode.SELECT)
private Set<Order> orders = new HashSet<Order>();
关联查询
@Fetch(FetchMode.JOIN)
子查询
@OneToMany(mappedBy = "customer", cascade = {CascadeType.ALL})
@LazyCollection(LazyCollectionOption.FALSE)//不是必须
@Fetch(FetchMode.SUBSELECT)
private Set<Order> orders = new HashSet<Order>();
测试子查询需要查询列表
@Test
public void testFetchList(){

    Session session = HibernateUtil.openSession();

    Query<Customer> query = session.createQuery("from Customer", Customer.class);
    List<Customer> list = query.list();
    for (Customer customer : list) {
        Set<Order> orders = customer.getOrders();
        for (Order order : orders) {
            System.out.println(order.getOrderNo());
        }
        System.out.println();
    }
    session.close();
}

4、抓取策略(*对一)
测试用例
@Test
public void testFetchOrder(){

    Session session = HibernateUtil.openSession();

    Order order = session.get(Order.class, 1L);
    System.out.println(order.getCustomer());//是否延迟加载

    session.close();
}

JPA策略:
1、何时抓取:eager,如何抓取:join(默认)
@ManyToOne(fetch=FetchType.EAGER)
@JoinColumn(name="customer_id")
private Customer customer;
2、何时抓取:lazy,如何抓取:select
@ManyToOne(fetch=FetchType.LAZY)
@JoinColumn(name="customer_id")
private Customer customer;

Hibernate策略:
1、代理延迟加载
@ManyToOne
@JoinColumn(name="customer_id")
@LazyToOne(LazyToOneOption.PROXY)
@Fetch(FetchMode.SELECT)
private Customer customer;

2、很少使用,需要使用编译时字节码增强
@LazyToOne(LazyToOneOption.NO_PROXY)


三、抓取策略的总结

1、JPA
属性:
1.1 *对一(默认非延迟、join):
fetch = FetchType.EAGER:非延迟、join
fetch = FetchType.LAZY:延迟、select、代理
1.2 *对多(默认延迟、select):
fetch = FetchType.EAGER:非延迟、join
fetch = FetchType.LAZY:延迟、select

2、Hibernate
2.1 延迟策略:
*对一 (默认非延迟):@LazyToOne(LazyToOneOption.XXX)
@LazyToOne(LazyToOneOption.PROXY)
@LazyToOne(LazyToOneOption.FALSE) 

*对多 (默认延迟):@LazyCollection(LazyCollectionOption.XXX)
@LazyCollection(LazyCollectionOption.TRUE)
@LazyCollection(LazyCollectionOption.FALSE)


2.2 抓取策略: 
*对一(默认join)
@Fetch(FetchMode.SELECT)
@Fetch(FetchMode.JOIN)

*对多(默认select)
@Fetch(FetchMode.SELECT)
@Fetch(FetchMode.JOIN)
@Fetch(FetchMode.SUBSELECT)


猜你喜欢

转载自blog.csdn.net/saint_lmy/article/details/80762933