Hibernate学习总结(二)


目录

一、概述
二、Hibernate表与表之间关系
   1.一对多关系
     1.1 一对多Demo
        1.1.1 entity类及映射配置
        1.1.2 核心配置文件
        1.1.3 创建结果
     1.2 一对多级联操作
        1.2.1 级联保存
        1.2.2 级联删除
        1.2.3 级联修改
   2.多对多关系
     2.1 多对多映射配置
     2.2 多对多级联保存
     2.3 多对多级联删除
     2.4 维护第三张表关系
三、Hibernate查询
   1.根据id查询
   2.HQL查询
     2.1 普通查询
     2.2 多表查询
   3.QBC查询
四、Hibernate查询策略 
   1.立即查询
   2.延迟查询
     2.1 类级别延迟
     2.2 关联级别查询
   3.批量抓取

一、概述

上篇文章主要介绍了项目中使用Hibernate框架的环境搭建及简单使用,本篇文章深入学习Hibernate框架,学习在Hibernate中表与表的关系以及Hibernate中的查询

二、Hibernate表与表之间关系

1.一对多关系

通过外键建立一对多关系:在多的一方建立外键,外键reference另一张表的主键

这里写图片描述

1.1 一对多Demo

1.1.1 entity类及映射配置

Customer.java :

package cn.wh.entity;
import java.util.HashSet;
import java.util.Set;

public class Customer {

    private Integer cid;
    private String custName;
    private String custLevel;
    private String custSource;
    private String custPhone;
    private String custMobile;

    /*一个客户包含多个LinkMan对象*/
    /*Hibernate中使用Set集合表示包含多个对象*/
    private Set<LinkMan> setLinkMan;


    public Set<LinkMan> getSetLinkMan() {
        return setLinkMan;
    }
    public void setSetLinkMan(Set<LinkMan> setLinkMan) {
        this.setLinkMan = setLinkMan;
    }
    public Integer getCid() {
        return cid;
    }
    public void setCid(Integer cid) {
        this.cid = cid;
    }
    public String getCustName() {
        return custName;
    }
    public void setCustName(String custName) {
        this.custName = custName;
    }
    public String getCustLevel() {
        return custLevel;
    }
    public void setCustLevel(String custLevel) {
        this.custLevel = custLevel;
    }
    public String getCustSource() {
        return custSource;
    }
    public void setCustSource(String custSource) {
        this.custSource = custSource;
    }
    public String getCustPhone() {
        return custPhone;
    }
    public void setCustPhone(String custPhone) {
        this.custPhone = custPhone;
    }
    public String getCustMobile() {
        return custMobile;
    }
    public void setCustMobile(String custMobile) {
        this.custMobile = custMobile;
    }
}

Customer.hbm.xml:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC 
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
    <class name="cn.wh.entity.Customer" table="t_customer">
        <id name="cid" column="cid">
            <generator class="native"></generator>
        </id>

        <property name="custName" column="custName"></property>
        <property name="custLevel" column="custLevel"></property>
        <property name="custSource" column="custSource"></property>
        <property name="custPhone" column="custPhone"></property>
        <property name="custMobile" column="custMobile"></property>

        <!-- 关联多个LinkMan对象 
             使用set标签表示多个对象
                name : set变量名
        -->
        <set name="setLinkMan">
            <!-- hibernate中双向维护外键
                 column : 外键名字
             -->
            <key column="cl_id"/>

            <!-- 包含的联系人类的全路径 -->
            <one-to-many class="cn.wh.entity.LinkMan"/>
        </set>

    </class>
</hibernate-mapping>

LinkMan.java :

package cn.wh.entity;

public class LinkMan {

    private Integer lkm_id;
    private String lkm_name;
    private String lkm_gender;
    private String lkm_phone;

    /*关联Customer,一个联系人对象包含一个Customer对象*/
    private Customer customer;

    public Customer getCustomer() {
        return customer;
    }
    public void setCustomer(Customer customer) {
        this.customer = customer;
    }
    public Integer getLkm_id() {
        return lkm_id;
    }
    public void setLkm_id(Integer lkm_id) {
        this.lkm_id = lkm_id;
    }
    public String getLkm_name() {
        return lkm_name;
    }
    public void setLkm_name(String lkm_name) {
        this.lkm_name = lkm_name;
    }
    public String getLkm_gender() {
        return lkm_gender;
    }
    public void setLkm_gender(String lkm_gender) {
        this.lkm_gender = lkm_gender;
    }
    public String getLkm_phone() {
        return lkm_phone;
    }
    public void setLkm_phone(String lkm_phone) {
        this.lkm_phone = lkm_phone;
    }
}

LinkMan.hbm.xml :

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC 
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
    <class name="cn.wh.entity.LinkMan" table="t_LinkMan">
        <id name="lkm_id" column="lkm_id">
            <generator class="native"></generator>
        </id>

        <property name="lkm_name" column="lkm_name"></property>
        <property name="lkm_gender" column="lkm_gender"></property>
        <property name="lkm_phone" column="lkm_phone"></property>

        <!-- 
            name : 变量名字
            class : 关联的联系人类全路径
            column : 外键名字
         -->
        <many-to-one name="customer" class="cn.wh.entity.Customer" column="cl_id"/>

    </class>
</hibernate-mapping>
1.1.2 核心配置文件
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC
    "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">

<hibernate-configuration>
    <session-factory>
    <!-- 1.配置数据库信息(必须配置) -->
        <!-- 数据库驱动类 -->
        <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>

         <!-- 数据库url,hibernate_demo为我们创建的数据库名称 -->
        <property name="hibernate.connection.url">jdbc:mysql:///hibernate_demo</property>

        <!-- 登录数据库的名称及密码 -->
        <property name="hibernate.connection.username">root</property>
        <property name="hibernate.connection.password">123456</property>


    <!-- 2.配置hibernate信息(可选配置) -->
        <!-- 输出sql语句 -->
        <property name="hibernate.show_sql">true</property>

        <!-- 格式化输出的sql语句 -->
        <property name="hibernate.format_sql">true</property>

        <!-- 根据hbm配置文件里的数据库表,对数据库进行ddl操作,创建、删除... 
            update : 如果数据库中不存在hbm中配置的表,则先创建该表;
                      如果数据库中存在hbm中配置的表,则直接更新
        -->
        <property name="hibernate.hbm2ddl.auto">update</property>

        <!-- 配置数据库方言
            例如:如果对数据库进行分页查询,根据该配置,让hibernate识别数据库自身的关键字
                  mysql分页使用limit
                  oracle分页使用rownum
         -->
        <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>

        <!-- 支持thread local session -->
        <property name="hibernate.current_session_context_class">thread</property>


    <!-- 3.添加映射配置文件(必须配置) -->
        <!-- *.hbm.xml文件相对于src目录的路径 -->
        <mapping resource="cn/wh/entity/Customer.hbm.xml"/>
        <mapping resource="cn/wh/entity/LinkMan.hbm.xml"/>
    </session-factory>
</hibernate-configuration>
1.1.3 创建结果

t_customer表:

CREATE TABLE `t_customer` (
  `cid` int(11) NOT NULL AUTO_INCREMENT,
  `custName` varchar(255) DEFAULT NULL,
  `custLevel` varchar(255) DEFAULT NULL,
  `custSource` varchar(255) DEFAULT NULL,
  `custPhone` varchar(255) DEFAULT NULL,
  `custMobile` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`cid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

这里写图片描述

t_linkman表:

CREATE TABLE `t_linkman` (
  `lkm_id` int(11) NOT NULL AUTO_INCREMENT,
  `lkm_name` varchar(255) DEFAULT NULL,
  `lkm_gender` varchar(255) DEFAULT NULL,
  `lkm_phone` varchar(255) DEFAULT NULL,
  `cl_id` int(11) DEFAULT NULL,
  PRIMARY KEY (`lkm_id`),
  KEY `FKkst2io7au7nonc5ncwl9dxpe7` (`cl_id`),
  CONSTRAINT `FKkst2io7au7nonc5ncwl9dxpe7` FOREIGN KEY (`cl_id`) REFERENCES `t_customer` (`cid`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

这里写图片描述

1.2 一对多级联操作

1.2.1 级联保存

写法一:

    //开启事务
    tx = session.beginTransaction();

    //1.创建客户对象
    Customer customer = new Customer();
    customer.setCustLevel("vip");
    customer.setCustName("ali");
    customer.setCustMobile("134567");
    customer.setCustPhone("982");
    customer.setCustSource("net");

    //2.创建联系人对象
    LinkMan linkMan = new LinkMan();
    linkMan.setLkm_name("xiao wang");
    linkMan.setLkm_gender("na");
    linkMan.setLkm_phone("7683");

    LinkMan lm = new LinkMan();
    lm.setLkm_name("xiao zhang");
    lm.setLkm_gender("nv");
    lm.setLkm_phone("739");

    //3.建立关联
    customer.getSetLinkMan().add(linkMan);
    customer.getSetLinkMan().add(lm);

    linkMan.setCustomer(customer);
    lm.setCustomer(customer);

    //4.保存数据库
    session.save(customer);
    session.save(linkMan);
    session.save(lm);


    //提交事务
    tx.commit();

输出结果:
Hibernate: 
    insert 
    into
        t_customer
        (custName, custLevel, custSource, custPhone, custMobile) 
    values
        (?, ?, ?, ?, ?)

Hibernate: 
    insert 
    into
        t_LinkMan
        (lkm_name, lkm_gender, lkm_phone, cl_id) 
    values
        (?, ?, ?, ?)

Hibernate: 
    insert 
    into
        t_LinkMan
        (lkm_name, lkm_gender, lkm_phone, cl_id) 
    values
        (?, ?, ?, ?)

Hibernate: 
    update
        t_LinkMan 
    set
        cl_id=? 
    where
        lkm_id=?

Hibernate: 
    update
        t_LinkMan 
    set
        cl_id=? 
    where
        lkm_id=?

执行顺序:
(1)插入customer
(2)依次插入所有linkMan
(3)根据插入的customer的主键id,更新所有插入的linkMan的外键id

写法二:

1.在客户映射配置文件中配置set的cascade属性为save-update
    <!-- 关联多个LinkMan对象 
        使用set标签表示多个对象
        name : set变量名
    -->
    <set name="setLinkMan" cascade="save-update">
       <!-- hibernate中双向维护外键
           column : 外键名字
       -->
       <key column="cl_id"/>  
       <!-- 包含的联系人类的全路径 -->
       <one-to-many class="cn.wh.entity.LinkMan"/>
   </set>


2.只需要在代码中为客户对象set联系人集合,session.save(客户对象)即可
    //开启事务
    tx = session.beginTransaction();

    //1.创建客户对象
    Customer customer = new Customer();
    customer.setCustLevel("vip");
    customer.setCustName("ali");
    customer.setCustMobile("134567");
    customer.setCustPhone("982");
    customer.setCustSource("net");

    //2.创建联系人对象
    LinkMan linkMan = new LinkMan();
    linkMan.setLkm_name("xiao wang");
    linkMan.setLkm_gender("na");
    linkMan.setLkm_phone("7683");

    LinkMan lm = new LinkMan();
    lm.setLkm_name("xiao zhang");
    lm.setLkm_gender("nv");
    lm.setLkm_phone("739");

    //3.建立关联
    customer.getSetLinkMan().add(linkMan);
    customer.getSetLinkMan().add(lm);

    //4.保存数据库
    session.save(customer);

    //提交事务
    tx.commit();
1.2.2 级联删除
1.客户映射文件配置set的cascade属性为delete
    <!-- 关联多个LinkMan对象 
        使用set标签表示多个对象
        name : set变量名
   -->
   <set name="setLinkMan" cascade="save-update,delete">
      <!-- hibernate中双向维护外键
          column : 外键名字
      -->
      <key column="cl_id"/>

      <!-- 包含的联系人类的全路径 -->
      <one-to-many class="cn.wh.entity.LinkMan"/>
   </set>

2.代码中使用session.delete删除即可
    //开启事务
    tx = session.beginTransaction();

    //1.根据id查询custemor
    Customer customer = session.get(Customer.class, 3);

    //2.delete customer
    session.delete(customer);

    //提交事务
    tx.commit();

执行顺序:
(1)查询customer表,获取外键id
(2)根据外键id查询linkMan表,获取联系人表主键id
(3)根据外键id更新linkMan表,设置满足条件的记录的外键为null
(4)根据主键id删除linkMan记录
(4)根据主键id删除customer记录
1.2.3 级联修改

修改linkman的外键:

    修改id为5的linkman的外键id为1:

    //1.根据id查询
    Customer customer = session.get(Customer.class, 1);
    LinkMan linkMan = session.get(LinkMan.class,5 );

    //2.建立关联
    customer.getSetLinkMan().add(linkMan);
    linkMan.setCustomer(customer);

    //3.save        
    session.update(customer);

以上修改外键,由于hibernate中是双向维护外键,所以在修改customer时修改一次linkman表外键,在修改linkman表时又会修改一次外键,操作性能问题
Hibernate: 
    update
        t_LinkMan 
    set
        lkm_name=?,
        lkm_gender=?,
        lkm_phone=?,
        cl_id=? 
    where
        lkm_id=?

Hibernate: 
    update
        t_LinkMan 
    set
        cl_id=? 
    where
        lkm_id=?

解决:
在一对多的关系中,让一那一方放弃维护外键,即在set标签中添加inverse属性,该属性默认值为false,表示不放弃维护外键,需要改为true即可放弃维护外键
    <!-- 关联多个LinkMan对象 
        使用set标签表示多个对象
        name : set变量名
     -->
    <set name="setLinkMan" cascade="save-update,delete" inverse="true">
        <!-- hibernate中双向维护外键
            column : 外键名字
        -->
        <key column="cl_id"/>

        <!-- 包含的联系人类的全路径 -->
        <one-to-many class="cn.wh.entity.LinkMan"/>
    </set>

2.多对多关系

创建第三张表建立多对多关系:第三张表中至少包含两个字段作为外键,reference两张表的主键

这里写图片描述

2.1 多对多映射配置

User与Role之间对应关系:一个用户有多个角色,一个角色有多个用户,多对多关系

User.java:

package cn.wh.entitys;

import java.util.HashSet;
import java.util.Set;

public class User {

    private Integer user_id;
    private String user_name;
    private String user_password;

    //关联role对象,一个用户有多个角色
    private Set<Role> setRoles = new HashSet<Role>();

    public Set<Role> getSetRoles() {
        return setRoles;
    }
    public void setSetRoles(Set<Role> setRoles) {
        this.setRoles = setRoles;
    }
    public Integer getUser_id() {
        return user_id;
    }
    public void setUser_id(Integer user_id) {
        this.user_id = user_id;
    }
    public String getUser_name() {
        return user_name;
    }
    public void setUser_name(String user_name) {
        this.user_name = user_name;
    }
    public String getUser_password() {
        return user_password;
    }
    public void setUser_password(String user_password) {
        this.user_password = user_password;
    }
}

User.hbm.xml:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC 
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
    <class name="cn.wh.entitys.User" table="t_user1">
        <id name="user_id" column="user_id">
            <generator class="native"></generator>
        </id>

        <property name="user_name" column="user_name"></property>
        <property name="user_password" column="user_password"></property>

        <!-- 
            name属性:set集合名称
            table属性:第三张表名
         -->
        <set name="setRoles" table="role_user">
            <!-- key配置当前表在第三张表role_user中的外键名称-->
            <key column="userid"></key>

            <!-- class表示关联的entity对象全路径,column表示 的是User表在第三张表中的外键名称-->
            <many-to-many class="cn.wh.entitys.Role" column="roleid"></many-to-many>
        </set>

    </class>

</hibernate-mapping>

Role.java:

package cn.wh.entitys;

import java.util.HashSet;
import java.util.Set;

public class Role {

    private Integer role_id;
    private String role_name;
    private String role_password;

    //关联user对象,一个角色有多个用户
    private Set<User> setUsers = new HashSet<User>();

    public Set<User> getSetUsers() {
        return setUsers;
    }
    public void setSetUsers(Set<User> setUsers) {
        this.setUsers = setUsers;
    }
    public Integer getRole_id() {
        return role_id;
    }
    public void setRole_id(Integer role_id) {
        this.role_id = role_id;
    }
    public String getRole_name() {
        return role_name;
    }
    public void setRole_name(String role_name) {
        this.role_name = role_name;
    }
    public String getRole_password() {
        return role_password;
    }
    public void setRole_password(String role_password) {
        this.role_password = role_password;
    }
}

Role.hbm.xml:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC 
    "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
    <class name="cn.wh.entitys.Role" table="t_role">
        <id name="role_id" column="role_id">
            <generator class="native"></generator>
        </id>

        <property name="role_name" column="role_name"></property>
        <property name="role_password" column="role_password"></property>

        <!-- 
            name属性:set集合名称
            table属性:第三张表名
         -->
        <set name="setUsers" table="role_user">
            <!-- key配置当前表在第三张表role_user中的外键名称-->
            <key column="roleid"></key>

            <!-- class表示关联的entity对象全路径,column表示 的是User表在第三张表中的外键名称-->
            <many-to-many class="cn.wh.entitys.User" column="userid"></many-to-many>
        </set>
    </class>  
</hibernate-mapping>

核心配置文件添加mapping:

<mapping resource="cn/wh/entitys/User.hbm.xml"/>
<mapping resource="cn/wh/entitys/Role.hbm.xml"/>

2.2 多对多级联保存

配置set标签,添加cascade属性为save-update:

<set name="setRoles" table="role_user" cascade="save-update">
     <key column="userid"></key>

     <many-to-many class="cn.wh.entitys.Role" column="roleid"></many-to-many>
</set>

代码实现,创建user、role对象,建立关联,保存即可:

        tx = session.beginTransaction();

        //1.创建两个对象
        cn.wh.entitys.User user1 = new cn.wh.entitys.User();
        user1.setUser_name("wang");
        user1.setUser_password("123");

        cn.wh.entitys.User user2 = new cn.wh.entitys.User();
        user2.setUser_name("han");
        user2.setUser_password("456");

        //2.创建三个角色
        Role role1 = new Role();
        role1.setRole_name("teacher");
        role1.setRole_password("tea");

        Role role2 = new Role();
        role2.setRole_name("student");
        role2.setRole_password("stu");

        Role role3 = new Role();
        role3.setRole_name("driver");
        role3.setRole_password("dri");

        //3.为user添加role
        //user1---role1/role2
        user1.getSetRoles().add(role1);
        user1.getSetRoles().add(role2);

        //user2---role2/role3
        user2.getSetRoles().add(role2);
        user2.getSetRoles().add(role3);

        //4.保存user
        session.save(user1);
        session.save(user2);

        tx.commit();

保存结果:

t_user表:
这里写图片描述

t_role表:
这里写图片描述

role_user表:
这里写图片描述

2.3 多对多级联删除

配置set标签,添加cascade属性为delete:

<set name="setRoles" table="role_user" cascade="save-update,delete">
     <key column="userid"></key>

     <many-to-many class="cn.wh.entitys.Role" column="roleid"></many-to-many>
</set>

代码实现删除用户

    //1.根据id查询
    cn.wh.entitys.User user = session.get(cn.wh.entitys.User.class, 1);

    //2.删除user
    session.delete(user);

删除结果:
t_user表:
这里写图片描述

t_role表:
这里写图片描述

user_role表:
这里写图片描述

提醒:

删除user中数据时,会把关联的role及role_user数据全部删除,实际上role中的部分记录(如student)还与user表中其余的记录有关联,也被删除了,造成影响,所以一般不建议删除多对多关系中的表记录

2.4 维护第三张表关系

实际上user表与role表之间无之间联系,只有通过role_user表才能建立关联,所以一般只需要维护第三张表就可以了

测试:
为某个用户添加某个角色

    tx = session.beginTransaction();

    //1.根据id查询user及为user添加的role
    cn.wh.entitys.User user = session.get(cn.wh.entitys.User.class, 1);
    Role role = session.get(Role.class, 3);

    //2.为user添加新的role对象
    user.getSetRoles().add(role);

    //3.更新,这步省略,因为user是持久态对象,在事务提交时会自动更新
    session.update(user);

    tx.commit();

为某个用户删除某个角色

    tx = session.beginTransaction();

    //1.根据id查询user及需要从user删除的role
    cn.wh.entitys.User user = session.get(cn.wh.entitys.User.class, 1);
    Role role = session.get(Role.class, 3);

    //2.从user删除role对象
    user.getSetRoles().remove(role);

    //3.更新,这步省略,因为user是持久态对象,在事务提交时会自动更新
    session.update(user);

    tx.commit();

三、Hibernate查询

1.根据id查询

在一对多场景中,通过根据id查询得到的customer,得到customer关联的linkman对象

    tx = session.beginTransaction();

    //查询id为3的customer,在根据查询的结果查询其管理的联系人对象集合
    Customer customer = session.get(Customer.class, 3);

    Set<LinkMan> linkMans = customer.getSetLinkMan();

    System.out.println(linkMans);

    tx.commit();

2.HQL查询

hql操作的是实体类及其属性
格式:from 实体类 where 属性条件

2.1 普通查询

    //1.查询所有customer
    Query query = session.createQuery("from Customer");
    List<Customer> customers = query.list();

    //2.条件查询
    Query queryBaseCondition = session.createQuery("from Customer as c where c.cid 
                                                   = ? and c.custName = ? ");
    queryBaseCondition.setParameter(0, 2);
    queryBaseCondition.setParameter(1, "ali");
    List<Customer> customersBaseCondition = queryBaseCondition.list();

    //3.模糊查询
    Query queryLike = session.createQuery("from Customer c where c.custName like ?");
    queryLike.setParameter(0, "%li%");
    List<Customer> customersLike = queryLike.list();

    //4.排序查询
    Query queryOrder = session.createQuery("from Customer c order by c.cid desc");
    List<Customer> customersOrder = queryOrder.list();

    //5.分页查询,查询1~6条记录
    Query queryLimit = session.createQuery("from Customer c");
    queryLimit.setFirstResult(1);
    queryLimit.setMaxResults(5);
    List<Customer> customersLimit = queryLimit.list();

    //6.查询部分字段---投影查询
    Query queryField = session.createQuery("select c.custName from Customer c");
    List<Object> custNamesField = queryField.list();

    //7.聚合函数查询
    Query queryCount = session.createQuery("select COUNT(*) from Customer");
    Object count = queryCount.uniqueResult();

2.2 多表查询

    /*HQL多表查询*/
    //1.内连接,返回数组list,不需要想sql语句里写on condition
    Query innerJoinQuery = session.createQuery("from Customer c inner join c.setLinkMan");
    List innerJoinresult = innerJoinQuery.list();

    //2.迫切内连接
    //与普通内连接底层相同,只是返回的是对象的list,关键字fetch
    Query fetchInnerJoinQuery = session.createQuery("from Customer c inner join 
                                                     fetch c.setLinkMan");
    List fetchInnerJoinresult = innerJoinQuery.list();

    //3.左外连接
    Query leftJoinQuery = session.createQuery("from Customer c left outer join c.setLinkMan");
    List leftJoinresult = leftJoinQuery.list();

    //4.迫切左外连接
    Query fetchLeftJoinQuery = session.createQuery("from Customer c left outer join 
                                                    fetch c.setLinkMan");
    List fetchLeftJoinresult = fetchLeftJoinQuery.list();

    //5.右外连接
    Query rightJoinQuery = session.createQuery("from Customer c right outer join c.setLinkMan");
    List rightJoinresult = rightJoinQuery.list();

3.QBC查询

没有查询语句

    //1.查询所有customer
    Criteria criteriaAll = session.createCriteria(Customer.class);
    List<Customer> customersAll = criteriaAll.list();

    //2.条件查询,没有查询语句,使用封装方法实现
    Criteria criterialCondition = session.createCriteria(Customer.class);
    criterialCondition.add(Restrictions.eq("cid", 1));
    criterialCondition.add(Restrictions.eq("custName", "ali"));
    List<Customer> customersCondition = criterialCondition.list();

    //3.模糊查询
    Criteria criteriaLike = session.createCriteria(Customer.class);
    criteriaLike.add(Restrictions.like("custName", "%al%"));
    List<Customer> customersLike = criteriaLike.list();

    //4.排序查询
    Criteria criteriaOrder = session.createCriteria(Customer.class);
    criteriaOrder.addOrder(Order.desc("cid"));
    List<Customer> customersOrder = criteriaOrder.list();

    //5.分页查询,查询1~6条记录
    Criteria criteriaLimit = session.createCriteria(Customer.class);
    criteriaLimit.setFirstResult(1);
    criteriaLimit.setMaxResults(5);
    List<Customer> customersLimit = criteriaLimit.list();

    //6.统计
    Criteria criteriaCount = session.createCriteria(Customer.class);
    criteriaCount.setProjection(Projections.rowCount());
    Object obj = criteriaCount.uniqueResult();
    int rowConut = ((Long)obj).intValue();

    //7.离线查询,不使用session创建criteria对象,应用场景:可以在DAO类之外拼接查询条件等
    DetachedCriteria detachedCriteria = DetachedCriteria.forClass(Customer.class);  
    Criteria deCriteria = detachedCriteria.getExecutableCriteria(session);
    List<Customer> customersDetach = deCriteria.list();

四、Hibernate查询策略

1 立即查询

通过get查询,会立即执行select语句,返回查询的对象

2 延迟查询

通过load查询,不会立即执行select语句,会返回只有id的代理对象,当使用非id属性时,才会执行select语句查询

2.1 类级别延迟

根据id查询对象,调用load方法不会立即执行select语句

2.2 关联级别延迟

    查询entity里关联的其他对象的set

    在配置文件中修改set标签,添加fetch、lazy属性:
    <!-- inverse="true" -->
    <set name="setLinkMan" cascade="save-update,delete" fetch="select" lazy="true">
            <!-- hibernate中双向维护外键
                 column : 外键名字
             -->
            <key column="cl_id"/>

            <!-- 包含的联系人类的全路径 -->
            <one-to-many class="cn.wh.entity.LinkMan"/>
        </set>

    fetch:默认是select
    lazy:true/false/extra
    即:执行select时延迟加载/不延迟加载/及其延迟加载(延迟加载,且只查询需要的信息)

    eg:
    Customer cu = session.get(Customer.class, 1);----------1
    Set<LinkMan> linkMans = cu.getSetLinkMan();------------2
    int size = linkMans.size();----------------------------3

    lazy=false,不延迟加载,则会在步骤1就select linkman
    lazy=true, 延迟加载,则会在3处才执行select linkman操作,但是是select * from linkman
    lazy=extra,及其延迟,则会在3处才执行select,但是执行的是select count(*) from linkman

3 批量抓取

    eg:查询多个customer中所有的limkman
    在set标签里设置bath-size属性
    <!-- 关联多个LinkMan对象 
             使用set标签表示多个对象
                name : set变量名
    -->
    <!-- inverse="true" -->
    <set name="setLinkMan"  batch-size="10">
        <!-- hibernate中双向维护外键
             column : 外键名字
         -->
        <key column="cl_id"/>    

       <!-- 包含的联系人类的全路径 -->
        <one-to-many class="cn.wh.entity.LinkMan"/>
   </set>   

    batch-size指定了查询linkman时,根据缓存中现有customer个数及batch-size(取交集),查询交集数
    的linkman条记录,然后再去linkman时就直接从缓存里取即可,减少了与数据库的通信,提高性能

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值