• Hibernate 配置详解(3)


    7) hibernate.max_fetch_depth

    该属性用于设置left out join单对象查询关系(one-to-one/many-to-one)中最大的关联深度。默认值为0,即默认情况不使用out-join(而使用延迟加载),建议的取值为0-3之间。

    要理解max_fetch_depth属性,就必须要理解在one-to-one/many-to-one元素上的out-join属性。我们用下面的一个例子来说明:

    public class Department {
    private Long id;
    private String name;
    private Employee manager;
    }
    
    public class Employee {
    private Long id;
    private Department dept;
    }
    Employee对象中有一个dept属性代表员工所属的部门,而在Department对象中有一个manager属性代表部门的管理员,按照正常的映射:

     

    <class name="Department">
    <id name="id">
    <generator class="native" />
    </id>
    <property name="name" />
    <many-to-one name="manager" class="Employee"/>
    </class>
    
     <class name="Employee">
    <id name="id">
    <generator class="native" />
    </id>
    <many-to-one name="dept" column="DEPT_ID"/>
    </class>
    那么,通过get/load方法无论是得到Department对象再得到对应的manager,或者得到Employee对象再得到对应的depthibernate默认都会采用延迟加载得到对应的manager/dept。这个就是我们说的,默认情况下,在many-to-one中,通过many方得到one方,采用延迟加载策略。但是我们也知道,使用延迟加载,会导致额外的SELECT产生,特别是在查询的时候,容易产生N+1问题,所以,我们可以使用适当的fetch策略来修改hibernate加载对象的方式。我们以下只讨论many-to-onefetch属性及策略(以Employee中的dept属性为例):

    1,join:在一条SQL中使用LEFT OUT JOIN直接查询出many方和对应的one

     

    加载策略:直接使用一条left out joinEmployee对应的Department对象查询出来,没有延迟加载:

     

    select employee0_.id as id1_1_1_, employee0_.DEPT_ID as DEPT2_1_1_, department1_.id as id1_0_0_, department1_.name as name2_0_0_, department1_.manager as manager3_0_0_ from Employee employee0_ left outer join Department department1_ on employee0_.DEPT_ID=department1_.id where employee0_.id=?

    2,select:再两条SQL中分别使用SELECT查询出many方和对应的one

     加载策略:使用延迟加载,使用另一条SELECT语句查询出Employee对应的Department对象。

    可以看到,使用fetch=join就可以缓解N+1问题,减少SQL。理解到这个,就可以理解到out-join属性。在many-to-one上还有一个outer-join属性,outer-join的取值可以为auto,false,true,默认值为auto(可以想象为false),即不使用LEFT OUT JOIN,如果设置为true,就相当于fetch=join,在一条SQL中使用LEFT OUT JOIN直接查询出many方和对应的one方。当然,这还需要看fetch属性的取值,比如fetch=select,就算outer-join=true,也会使用延迟加载,因为fetch规定的是获得关联对象的方式,而outer-join只是规定是否用LEFT OUT JOIN获取关联对象,所以我简单理解为fetch的级别高于outer-join(个人理解方式)。


    理解到outer-join的好处之后,问题接着就来了,我们可以看到,假如在Employee方的dept设置为outer-jointrue,那么在得到Employee的时候,就会立刻使用LEFT OUT JOIN取得对应的Department对象,那如果Department对象的manager属性的outer-join也设置为true,那么在得到Department对象时,又会立刻使用LEFT OUT JOIN关联到Employee表,如果大量的关联对象都设置了outer-join属性,那么在得到一个对象的时候,就会引起大量的表的外连接查询,导致查询效率也会非常慢,在这种情况下,就可以通过设置hibernate.max_fetch_depth来限制外链表的数量。比如:

    <class name="Department">
    <id name="id">
    <generator class="native" />
    </id>
    <property name="name" />
    <many-to-one name="manager" class="Employee" outer-join="true"/>
    </class>
    
    <class name="Employee">
    <id name="id">
    <generator class="native" />
    </id>
    <many-to-one name="dept" column="DEPT_ID" outer-join="true"/>
    </class>

    如果没有设置hibernate.max_fetch_depth,就会使用两个LEFT OUT JOINEmployeeEmployee对应的departmentdepartment对应的manager都查询出来:

     

    select employee0_.id as id1_1_2_, employee0_.DEPT_ID as DEPT2_1_2_, department1_.id as id1_0_0_, department1_.name as name2_0_0_, department1_.manager as manager3_0_0_, employee2_.id as id1_1_1_, employee2_.DEPT_ID as DEPT2_1_1_ from Employee employee0_ left outer join Department department1_ on employee0_.DEPT_ID=department1_.id left outer join Employee employee2_ on department1_.manager=employee2_.id where employee0_.id=?

    如果设置:

    hibernate.max_fetch_depth 1

    那么就只会使用一条LEFT OUT JOIN只查询出Employeeemployee对应的department

     

    select employee0_.id as id1_1_1_, employee0_.DEPT_ID as DEPT2_1_1_, department1_.id as id1_0_0_, department1_.name as name2_0_0_, department1_.manager as manager3_0_0_ from Employee employee0_ left outer join Department department1_ on employee0_.DEPT_ID=department1_.id where employee0_.id=?

    同样,这个参数对fetch=join的情况也适用。

    另外,如果是通过查询:

    session.createQuery("FROM Employee").list();
    
    session.createCriteria(Employee.class).list();
    那么,只有当使用Criteria的方式查询,fetch或者outer-join才会起作用,而使用Query对象查询,是只会查询出Employee的。这点需要非常注意。
  • 相关阅读:
    不要胡思乱想
    天天被思想教育
    带金属牙套
    要清楚自己的弱点
    打碎自己,理解自己,重塑自己
    我的侄子
    Proj CMI Paper Reading: Developing Trustworthy Hardware with SecurityDriven Design and Verification
    Proj CMI Paper Reading: Expanding the Reach of Fuzz Testing
    Proj CMI Paper Reading: Defect Prediction Guided SearchBased Software Testing
    Proj CMI Paper Reading: Detect Vulnerabilities Utilizing Fuzzing
  • 原文地址:https://www.cnblogs.com/james1207/p/3275420.html
Copyright © 2020-2023  润新知