Hibernate--初级

2017.2.6-2017.2.9

javaee三层结构

  1. web层:struts2框架
  2. service层:Spring框架
  3. dao层:hibernate框架

    对数据库进行CURD

什么是hibernate框架

  1. hibernate框架应用于Javaee三层结构中的dao层框架
  2. 在dao层里面做对数据库crud操作,使用hibernate实现crud操作,hibernate底层代码就是jdbc,hibernate对jdbc进行封装,使用hibernate好处,不需要写复杂jdbc代码了,不需要写sql语句实现
  3. hibernate是开源的轻量级框架
  4. hibernate版本

    • hibernate3.x
    • hibernate4.x
    • hibernate5.x

什么是orm思想

  1. hibernate使用orm思想对数据库进行crud操作
  2. 在web阶段学习javabean,更正确的叫法–实体类
  3. orm:object relational mapping,对象关系映射
    1. 让实体类和数据库表进行一一对应
    2. 不需要直接操作数据库表,而操作表对应的实体类对象

第一个应用

  1. 引入jar包

    1. 引入require文件下的所有jar包
    2. 引入jpa-metamodel-generator文件夹下的jar包
    3. 引入MySQL驱动jar包
    4. 引入日志jar包

      log4j-version.jar
      log4j-api-version.jar
      slf4j-log4j12-version.jar
      
  2. 创建实体类

    使用hibernate不许自己手动创建表,hibernate会自动创建
    
  3. 配置实体类和数据库表一一对应关系(映射关系)

    1. 创建想xml格式的配置文件

      配置文件的路径和名称没有固定要求
      建议:在实体类所在包里面创建,名称:实体类名称.hbm.xml
      
    2. 配置是xml格式,在配置文件中首先引入xml约束(dtd、schema,hibernate里都为dtd约束)

      <?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>
          <!-- 1。配置类和表对应
              class标签
              name属性:实体类全路径
              table属性:数据表名称
           -->
          <class name="zcw.entity.User" table="user">
              <!-- 2.配置实体类id和表id对应
                  hibernate要求实体类有一个属性唯一值
                  hibernate要求表有字段作为唯一值
               -->
               <!-- 3.id标签 
                  name属性:实体类里面id属性名称
                  column属性:生成的表字段名称
               -->
               <id name="id" column="id">
                  <!-- 4.设置数据表id增长策略
                      native:生成表id值为主键自动增长
                   -->
                   <generator class="native"></generator>
               </id>
              <!-- 5.配置其他属性和表字段对应
                  name属性:实体类属性名称
                  column属性:生成表字段名称
               -->
               <property name="username" column="username"></property>
               <property name="password" column="password"></property>
               <property name="address" column="address"></property>
          </class>
      </hibernate-mapping>
      
  4. 配置hibernate核心配置文件

    <?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>
            <!-- 第一部分:配置数据库信息 -->
            <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
            <property name="hibernate.connection.url">jdbc:mysql:///hibernate</property>
            <property name="hibernate.connection.username">root</property>
            <property name="hibernate.connection.password">951029</property>
    
            <!-- 第二部分:配合hibernate信息 -->
            <!-- 输出底层SQL语句 -->
            <property name="hibernate.show_sql">true</property>
            <!-- 输出低层SQL语句格式 -->
            <property name="hibernate.format_sql">true</property>
            <!-- hibernate自动创建表
                update:如果已经有表,更新,如果没有,创建
             -->
             <property name="hibernate.hbm2ddl.auto">update</property>
             <!-- 配置数据库方言 
                在mysql里面实现分页,关键字limit,只是mysql独有
                在oracle数据库,实现分页rownum
                让hibernate框架识别不同数据库自己特有的语句
             -->
             <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
    
            <!-- 第三部分:在映射文件放到核心配置文件中 -->
            <mapping resource="zcw/entity/User.hbm.xml"/>
        </session-factory>
    </hibernate-configuration>
    

添加操作

  1. 加载hibernate核心配置文件
  2. 创建SessionFactory对象
  3. 使用SessionFactory创建Session
  4. 开启事务
  5. 写具体逻辑crud
  6. 提交事务
  7. 关闭资源

    package test;
    
    import org.hibernate.Session;
    import org.hibernate.SessionFactory;
    import org.hibernate.Transaction;
    import org.hibernate.cfg.Configuration;
    import org.junit.Test;
    
    import zcw.entity.User;
    
    public class addtest {
        @Test
        public void add(){
            //第一步 加载hibernate核心配置文件
            Configuration cfg=new Configuration();
            cfg.configure();
            //第二步 创建SessionFactory对象
            //读取hibernate核心配置文件内容,创建sessionfactory
            SessionFactory sessionFactory=cfg.buildSessionFactory();
            //第三步 使用SessionFactory对象创建session对象
            Session session=sessionFactory.openSession();
            //第四步 开启事务
            Transaction ts=session.beginTransaction();
            //第五步 写具体逻辑crud操作
            User user=new User();
            user.setUsername("张三");
            user.setPassword("666");
            user.setAddress("福建");
            //调用session方法实现添加
            session.save(user);
    
            //第六步 提交事务
            ts.commit();
    
            //第七步 关闭资源
            session.close();
            sessionFactory.close();
        }
    
    }
    

配置文件详解

  1. 映射配置文件
    • 文件名和位置没有固定要求
    • class标签name属性值为类全路径
    • id标签和property标签name属性值为实体类属性名称
    • id标签和property标签,column可以省略
    • property标签type属性,设置生成表字段的类型。hibernate会自动设置类型
  2. 核心配置文件
    • 配置位置要求,在session-factory标签内
    • 配置三部分
      • 数据库部分–必须
      • hibernate部分–可选
      • 映射文件–必须
        -核心配置文件名称(hibernate.cfg.xml)和位置(src下)固定

hibernate核心API

  1. Configuration

    Configuration cfg=new Configuration();
    cfg.configure();
    

    到src目录下面找到名称为hibernate.cfg.xml配置文件,创建对象,把配置文件放到对象里面(加载核心配置文件)

  2. SessionFactory(重点)

    • 使用configuration对象创建SessionFactory对象,创建SessionFactory过程中做的事:

      根据核心配置文件中,有数据库配置,有映射文件部分,到数据库里面根据映射关系把表创建

    • 创建SessionFactory过程非常消耗资源

      在hibernate操作中,建一个项目一般只创建一个SessionFactory对象

    • 实现

      静态代码块只在类加载是后执行,执行一次。

      static Configuration cfg=null;
      static SessionFactory sessionFactory=null;
      //静态代码块实现
      static{
          //加载核心配置文件
          cfg=new Configuration();
          cfg.configure();
          sessionFactory=cfg.buildSessionFactory();
      }
      //提供返回sessionFactory的方法
      public static SessionFactory getSessionFactory(){
          return sessionFactory;
      }
      
  3. Session(重点)

    • session类似与jdbc中connection
    • 调用session里面不同的方法实现crud操作
      • 添加–save()
      • 修改–update()
      • 删除–delete()
      • 根据id查询–get()
    • session对象是单线程对象

      session对象不能共用,只能自己使用

Transaction

  1. 事务对象

    Transaction ts=session.beginTransaction();
    
  2. 事务提交和回滚
    • commit()
    • rollback()
  3. 事务的四个特性
    • 原子性
    • 一致性
    • 隔离性
    • 持久性

实体类编写规则

  1. 属性私有
  2. get、set方法公有
  3. 要求实体类有属性作为唯一值(id)
  4. 实体类属性建议不使用基本数据类型,建议使用基本数据类型对应的包装类

    • int-Integer
    • char-Character
    • 其他的都是首字母大写,比如 double-Double

    因为有时候基本数据类型表达的不够准确,如:int score=0,但是它不能表示学生没来考试,而Integer=null则可以表示

hibernate主键生成策略

  1. native:根据使用的数据库来选择生成策略
  2. uuid:hibernate自动生成UUID值

    id的数据类型一定要为字符串类型

根据id获取数据

核心代码

//  session的get方法有两个参数
//  第一个:实体类的class
//  第二个:id值
User user=session.get(User.class, 1);
System.out.println(user);

修改操作

  1. 首先获取数据
  2. 修改

    Transaction ts=session.beginTransaction();
    //  session的get方法有两个参数
    //  第一个:实体类的class
    //  第二个:id值
    User user=session.get(User.class, 1);
    System.out.println(user);
    user.setUsername("666");
    user.setPassword("111");
    session.update(user);
    
    ts.commit();
    

删除操作

  1. 先查找出来,再删除
  2. 创建实体类对象,再删除

    /*//第一种:先查找,后删除
    User user=session.get(User.class, 1);
    session.delete(user);*/
    
    //第二种:先创建,后删除
    User user=new User();
    user.setId(2);
    session.delete(user);
    

实体类对象状态(概念)

  1. 瞬时态:对象里面没有id,对象与session没有关联

    User user=new User();
    user.setUsername("zcw");
    
  2. 持久态:对象有id值,对象与session关联

    User user=session.get(User.class,1);
    
  3. 托管态:对象有id值,对象与session没有关联

    User user=new User();
    user.setId(1);
    

saveOrUpdate

  1. 执行save操作:当实体类对象为瞬时态时
  2. 执行update操作:当实体类对象为托管态或持久态时

Hibernate的一级缓存

  1. 默认是打开状态
  2. 作用范围:从session创建到session关闭
  3. 缓存存储的数据为持久态数据

是一种优化技术

Hibernate二级缓存

  1. 目前已经不使用了,替代技术redis
  2. 默认不打开
  3. 作用范围:SessionFactory范围

验证一级缓存

  1. 首先根据id=1查询
  2. 再查询id=1
  3. 看是否有两个sql日志输出

一级缓存执行过程

持久态会自动更新数据库

User user=session(User.class,1);
user.setUsername("q");
ts.commit();

就算没有提交,也会完成更新

Hibernate事务规范写法

    SessionFactory sessionFactory = null;
    Session session = null;
    Transaction ts = null;
    try {
        sessionFactory = GetSessionFactory.getSessionFactory();
        session = sessionFactory.openSession();
        ts = session.beginTransaction();
        User user = session.get(User.class, 1);
        System.out.println(user);
        ts.commit();
    } catch (Exception e) {
        e.printStackTrace();
        ts.rollback();
    } finally {
        session.close();
        sessionFactory.close();
    }

Hibernate绑定Session

为了确保session为单线程

  1. 配置hibernate.cfg.xml文件

     <property name="hibernate.current_session_context_class">thread</property>
    
  2. 调用SessionFactory得到

    return sessionFactory.getCurrentSession();
    
  3. 获取与本地线程绑定session的时候,不需要手动关闭

Query对象查询所有记录

使用query对象需要写HQL语句,语法格式:from 实体类名称

  1. 创建Query对象
  2. 调用query对象里面的方法得到结果

        Query query=session.createQuery("from User");
        List<User> list=query.list();
        for(User user:list){
            System.out.println(user);
        }
    

Criteria对象查询数据

这个方法无需写sql语句

  1. 创建Criteria对象
  2. 调用对象里面的方法得到结果

        //createCriteria方法的参数为实体类class
        Criteria criteria=session.createCriteria(User.class);
        List<User>list=criteria.list();
        for(User user:list){
            System.out.println(user);
        }
    

SQLQuery对象查询数据

使用sql语句

  1. 创建SQLQuery对象
  2. 调用方法得到结果集

        SQLQuery sqlQuery=session.createSQLQuery("select * from user");
        List<Object[]> list=sqlQuery.list();
        for(Object[] object:list){
            System.out.println(Arrays.toString(object));
        }
    

    默认的得到的是数组集合,下面的方法将结果集变为封装到User实体中

        SQLQuery sqlQuery=session.createSQLQuery("select * from user");
        sqlQuery.addEntity(User.class);
        List<User>list=sqlQuery.list();
        for(User user:list){
            System.out.println(user);
        }
    

hibernate一对多配置

客户–联系人,客户就是公司(一),联系人就是职工(多)。
外键在多的一方

  1. 创建实体类

    • 用户

      private Integer cid;
      private String cname;
      private String clevel;
      private String csource;
      private String cphone;
      private String cmobile;
      ......get、set方法
      
    • 联系人

      private Integer lkm_id;
      private String lkm_name;
      private String lkm_gender;
      private String lkm_phone;
      
  2. 让两个实体类互相表示

    • 在客户实体类里面表示多个联系人

      private Set<LinkMan> setLinkMan=new HashSet<LinkMan>();
      
      public Set<LinkMan> getSetLinkMan() {
          return setLinkMan;
      }
      public void setSetLinkMan(Set<LinkMan> setLinkMan) {
          this.setLinkMan = setLinkMan;
      }
      
    • 在联系人实体类里面表示所属客户

      private Client client;
      
      public Client getClient() {
          return client;
      }
      public void setClient(Client client) {
          this.client = client;
      }
      
  3. 配置映射关系

    1. 一个实体类对应一个映射配置文件
    2. 配置基本映射文件

      • Client.hbm.xml映射文件

        <class name="zcw.entity.Client" table="client">
             <id name="cid" column="id">
                 <generator class="native"></generator>
             </id>
             <property name="cname" column="cname"></property>
             <property name="clevel" column="clevel"></property>
             <property name="csource" column="csource"></property>
             <property name="cphone" column="cphone"></property>
             <property name="cmobile" column="cmobile"></property>
        </class>
        
      • LinkMan.hbm.xml映射文件

        <class name="zcw.entity.LinkMan" table="linkMan">
             <id name="lkm_id" column="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>
        </class>
        
    3. 在映射文件中,配置一对多关系

      • Client.hbm.xml

         <!-- 在客户映射文件中,表示所有联系人
            使用set标签表示所有联系人
            set标签里面有name属性,属性值为联系人set集合名称
          -->
          <set name="setLinkMan">
            <!-- 一对多建表,有外键
                hibernate机制:双向维护外键,在一和多一方都配置外键
                column属性值:外键名称
              -->
              <key column="clid"></key>
              <!-- 客户所有的联系人,class里面写联系人实体类全路径 -->
              <one-to-many class="zcw.entity.LinkMan"/>
          </set>
        
      • LinkMan.hbm.xml

        <!-- 表示联系人所属客户
            name属性:应为联系人实体类中使用client对象表示,所以写client
            class属性:Client类的全路径
            column属性:外键名称
         -->
         <many-to-one name="client" class="zcw.entity.Client" column="clid"></many-to-one>
        
  4. 创建核心配置文件,把映射文件引入到核心配置文件中

    <mapping resource="zcw/entity/Client.hbm.xml"/>
    <mapping resource="zcw/entity/LinkMan.hbm.xml"/>
    
  5. 测试。成功创建了client和lingkman表

Hibernate一对多级联操作

  1. 创建客户和联系人对象
  2. 建立客户对象和联系人对象的关系
  3. 保存到数据库

复杂写法:

        ts = session.beginTransaction();
        //添加一个客户,为这个客户添加一个联系人
        //1.创建客户和联系人对象
        Client client=new Client();
        client.setCname("baidu");
        client.setClevel("vip");
        client.setCsource("internet");
        client.setCphone("110");
        client.setCmobile("111");

        LinkMan linkMan=new LinkMan();
        linkMan.setLkm_name("zcw");
        linkMan.setLkm_gender("male");
        linkMan.setLkm_phone("177");

        //2.建立客户对象和联系人对象关系
        //2.1将联系人对象放到客户对象的set集合里
        client.getSetLinkMan().add(linkMan);
        //2.2把客户对象放到联系人里
        linkMan.setClient(client);

        //3.保存到数据库
        session.save(client);
        session.save(linkMan);

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

简单写法

  • 在Client.hbm.xml文件的set标签写上cascade属性

    <set name="setLinkMan" cascade="save-update">
    
  • java操作代码中

    • 不需将客户对象放到联系人中
    • 不需保存LinkMan对象

      ts = session.beginTransaction();
      //添加一个客户,为这个客户添加一个联系人
      //1.创建客户和联系人对象
      Client client=new Client();
      client.setCname("baidu");
      client.setClevel("vip");
      client.setCsource("internet");
      client.setCphone("110");
      client.setCmobile("111");
      
      LinkMan linkMan=new LinkMan();
      linkMan.setLkm_name("zcw");
      linkMan.setLkm_gender("male");
      linkMan.setLkm_phone("177");
      
      //2.建立客户对象和联系人对象关系
      //2.1将联系人对象放到客户对象的set集合里
      client.getSetLinkMan().add(linkMan);
      
      //3.保存到数据库
      session.save(client);
      
      //提交事务
      ts.commit();
      

一对多级联删除

将客户和对应的联系人删除

  1. 配置Client.hbm.xml文件的set标签

    <set name="setLinkMan" cascade="save-update,delete">
    
  2. 删除客户

    Client client=session.get(Client.class,2);
    session.delete(client);
    

一对多联级修改

//1.根据id查询联系人,根据id查询用户
Client client=session.get(Client.class, 1);
LinkMan linkman=session.get(LinkMan.class, 3);

//把联系人放到客户
client.getSetLinkMan().add(linkman) ;
//把客户放到联系人里面
linkman.setClient(client);

inverse属性

因为Hibernate双向维护外键,在客户和联系人里面都需要维护外键,修改联系人的时候,首先更新联系人,再更改外键。造成效率问题

解决方法:让client方放弃外键维护。

 <set name="setLinkMan" cascade="save-update,delete" inverse="true">

hibernate多对多配置

用户–角色,小张可以是总经理、农民、司机。
另外建一张表,包含两张表的外键

  1. 创建两个实体类

    • User

      private Integer id;
      private String username;
      private String password;
      
    • Rolle

      private Integer id;
      private String name;
      private String desc;
      
  2. 配置两个实体类的关系

    • User

      private Set<Role> setRole=new HashSet<Role>();
      public Set<Role> getSetRole() {
          return setRole;
      }
      public void setSetRole(Set<Role> setRole) {
          this.setRole = setRole;
      }
      
    • Role

      private Set<User> setUser=new HashSet<User>();
      
      public Set<User> getSetUser() {
          return setUser;
      }
      public void setSetUser(Set<User> setUser) {
          this.setUser = setUser;
      } 
      
  3. 配置文件

    1. 基本配置
    2. 配置多对多关系

      • User.hbm.xml

         <!-- 用户表里表示所有角色,使用set标签
            name属性:角色set集合名称
            table:第三表名称
          -->
         <set name="setRole" table="user_role"> 
            <!-- key标签里面配置当前映射文件在第三张表外键名称 -->
            <key column="userid"></key>
            <!-- class:角色实体类全路径
                column:角色在第三张表外键名称
             -->
            <many-to-many class="zcw.manytomany.Role" column="roleid"></many-to-many>
         </set>
        
      • Role.hbm.xml

         <set name="setUser" table="user_role"> 
            <!-- key标签里面配置当前映射文件在第三张表外键名称 -->
            <key column="roleid"></key>
            <!-- class:角色实体类全路径
                column:角色在第三张表外键名称
             -->
            <many-to-many class="zcw.manytomany.User" column="userid"></many-to-many>
         </set>
        
    3. 在主配置文件中引入映射文件
  4. 测试

    1. 在User.hbm.xml的set标签写上cascade属性

      <set name="setRole" table="user_role" cascade="save-update">
      
    2. 写java代码

      //创建user、role实体对象
      User user1=new User();
      User user2=new User();
      user1.setUsername("张三");
      user1.setPassword("666");
      user2.setUsername("李四");
      user2.setPassword("666");
      
      Role role1=new Role();
      Role role2=new Role();
      Role role3=new Role();
      role1.setName("项目经理");
      role1.setDesc("项目经理");
      role2.setName("餐厅老板");
      role2.setDesc("餐厅老板");
      role2.setName("代码高手");
      role2.setDesc("代码高手");
      
      //建立关系
      user1.getSetRole().add(role1);
      user1.getSetRole().add(role2);
      user1.getSetRole().add(role3);
      user2.getSetRole().add(role1);
      user2.getSetRole().add(role3);
      
      session.save(user1);
      session.save(user2);
      
  5. 测试

多对多删除(一般不用)

  1. 在User.hbm.xml的set标签设置cascade属性

    <set name="setRole" table="user_role" cascade="save-update,delete"> 
    
  2. 删除操作

    User user=session.get(User.class, 5);
    session.delete(user);
    

第三张表的维护

  1. 让用户拥有某个角色

    //让用户2拥有角色3
    //1.获得User和Role
    User user=session.get(User.class, 2);
    Role role=session.get(Role.class,3)
    
    //2.向user中加入role
    user.getSetRole().add(role);
    
  2. 让用户没有某个角色

    //让用户2失去角色2
    //1.获得User和Role
    User user=session.get(User.class, 2);
    Role role=session.get(Role.class,2);
    
    //2.向user中移除role
    user.getSetRole().remove(role);
    

Hibernate查询方式

  1. 对象导航查询

    根据id查询某个客户,再查询这个客户里面所有的联系人

  2. OID查询

    根据id查询某一条记录,返回对象

  3. hql查询

    Query对象,写hql语句实现查询

  4. QBC查询

    Criteria对象

  5. 本地查询

    SQLQuery对象,实现普通sql实现查询

对象导航查询

Client client = session.get(Client.class, 1);
Set<LinkMan> list=client.getSetLinkMan();
System.out.println(list.size());

OID查询

Client client = session.get(Client.class, 1);

HQL查询

  1. HQL:Hibernate Query Language,Hibernate提供一种查询语言,hql语言与普通SQL很相似,区别:普通SQL操作数据库表和字段,hql操作实体类和属性。
  2. 常用hql语句

    1. 查询所有:from 实体类对象
    2. 条件查询:from 实体类名称 where 实体类属性名称=? and 实体类属性名称 like ?

      Query query=session.createQuery("from User where id=?");
      query.setParameter(0, 1);
      List<User> list=query.list();
      for(User user:list){
          System.out.println(user.getPassword());
      }
      
    3. 排序查询:from 实体类名称 order by 实体类属性名称 asc/desc

    4. 分页查询

      //查询记录
      Query query=session.createQuery("from LinkMan");
      //设置开始位置
      query.setFirstResult(0);
      //设置每页的记录数
      query.setMaxResults(3);
      List<LinkMan> list=query.list();
      
    5. 投影查询(查询部分字段值):select 实体类属性名称,实体类属性名称 from 实体类 不支持*号
    6. 聚集函数使用:select count(*) from 实体类名称
      • count,max,min,sum,avg

QBC查询

  1. 查询所有

    1. 创建Criteria对象
    2. 得到结果集

      Criteria criteria=session.createCriteria(User.class);
      List<User>list=criteria.list();
      
  2. 条件查询

    //创建criteria对象
    Criteria criteria=session.createCriteria(LinkMan.class);
    //添加条件
    criteria.add(Restrictions.eqOrIsNull("lkm_gender", "female"));
    criteria.add(Restrictions.like("lkm_name", "%h%"));
    List<LinkMan> list=criteria.list();
    
  3. 排序查询

    Criteria criteria=session.createCriteria(LinkMan.class);
    //设置对那个属性进行排序,设置排序规则
    criteria.addOrder(Order.desc("id"));
    //criteria.addOrder(Order.asc("id"));
    
  4. 分页查询

    //创建对象
    Criteria criteria=session.createCriteria(LinkMan.class);
    //设置开始位置
    criteria.setFirstResult(0);
    //设置每页的记录数
    criteria.setMaxResults(3);
    
  5. 统计查询

    //创建对象
    Criteria criteria=session.createCriteria
    //设置操作
    criteria.setProjection(Projections.rowCount());
    //调用方法得到结果
    Object obj=criteria.uniqueResult();
    Long l=(Long)obj;
    int count=l.intValue();
    

离线查询(不使用session)

DetachedCriteria detachedCriteria=DetachedCriteria.forClass(LinkMan.class);
//最终执行时才需要用到session
Criteria criteria=detachedCriteria.getExecutableCriteria(sesion);
List<LinkMan> list=criteria.list();

HQL多表查询

  1. 内连接

    select * from user u,role r where u.id=r.id;
    或
    select * from user u INNER JOIN role r ON u.id=r.id;
    
  2. 左外连接

    select * from user r LEFT OUTER JOIN role r ON u.id=r.id;
    
  3. 右外连接

    select * from user r RIGHT OUTER JOIN role r ON u.id=r.id;
    

HQL内连接

  1. from Client c inner join c.setLinkMan

    Query query=session.createQuery("from Client c inner join c.setLinkMan");
    //返回的list每部分都是数组形式
    List list=query.list();
    
  2. 迫切内连接(返回的是对象):from Client c inner join fetch c.setLinkMan

HQL左外连接

  1. from Client c left outer join c.setLinkMan
  2. 迫切左外连接:from Client c left outer join fetch c.setLinkMan

HQL右外连接

from Client c right outer join c.setLinkMan

hibernate检索策略(2种)

  1. 立即查询:根据id查询,调用get方法,一调用get方法马上发出语句查询数据库

    User user=session.get(User.class,1);
    
  2. 延迟查询:根据id查询,还有load方法,调用load方法不会马上发送语句查询数据,只有得到对象里面的值的时候才会发送语句查询数据库

    User user=session.load(User.class,1);
    

延迟查询(2种)

  1. 类级别延迟:根据id查询返回实体类对象,调用load方法不会马上发送语句
  2. 关联级别延迟:查询某个客户,再查询这个客户的所有联系人,查询客户的所有联系人的过程是否需要延迟,这个过程称为关联级别延迟。

    在客户映射文件中进行配置,在set标签上使用属性(1)fetch:select(默认)(2)lazy:TRUE延迟(默认)/false不延迟/extra极其延迟

    极其延迟就是你调用什么就发送什么语句

批量抓取

应用场景:查询所有的客户,返回list集合,遍历list集合,得到每个客户,得到每个客户的所有联系人

//创建criteria对象
Criteria criteria=session.createCriteria(User.class);
List<User> list=criteria.list();

for(User u:list){
    Set<Role> roles=u.getSetRole();
    for(Role role:roles){
        System.out.println(role.getName());
    }
}

上面的代码发送的sql语句太多次,可以配置客户的映射文件,在set标签中写上batch-size属性

 <set name="setRole" table="user_role" batch-size="66">

值越大效率越高

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值