Hibernate框架(初级)

Hibernate框架

    • 什么是Hibernate
    • 下载Hibernate的开发环境
    • 创建JAVAEE项目,搭建Hibernate环境
        • 导入jar包
        • 创建项目
    • 总结映射的配置
    • 总结核心配置
    • 总结测试时需要的几个对象
    • 持久化类
        • 什么是持久化类
        • 持久化类的编写规则
    • 主键生成策略
        • 主键的分类
            • 自然主键
            • 代理主键
        • 实际开发
        • Hibernate的主键生成策略
    • 持久化类的三种状态
        • 瞬时态
        • 持久态
        • 脱管态
        • 区分三种状态对象
        • 持久态的重要特点
    • Hibernate的缓存
        • 什么是缓存
        • Hibernate的一级缓存
    • Query的简单使用
    • Criteria
    • SQLQuery

什么是Hibernate

Hibernate是一个持久层的ORM(对象关系映射)框架。

下载Hibernate的开发环境

Hibernate5.0.7开发环境下载链接
Hibernate框架(初级)_第1张图片

  • documentation:Hibernate开发文档
  • lib:Hibernate开发包
    • required:Hibernate开发的必须依赖包
    • optional:Hibernate开发的可选jar包
  • project:Hibernate测试项目

创建JAVAEE项目,搭建Hibernate环境

导入jar包

  • 数据库驱动包
    mysql-connector-java-6.0.6.jar
  • Hibernate开发必须的jar包
    Hibernate框架(初级)_第2张图片
  • 引入日志记录包
    在这里插入图片描述

创建项目

  • 创建表

  • 创建实体类(对应表格)

  • 创建类与表的映射配置(实体类名.hbm.xml)
    建立类与表之间的映射,主键对应和普通属性的对应

    
    
    <hibernate-mapping>
        
        <class name="com.hibernate.pojo.Customer" table="cst_customer">
            
            <id name="cust_id" column="cust_id">
                <generator class="native" />
            id>
            
            <property name="cust_source" column="cust_source">property>
            <property name="cust_industry" column="cust_industry">property>
            <property name="cust_level" column="cust_level">property>
            <property name="cust_mobile" column="cust_mobile">property>
            <property name="cust_name" column="cust_name">property>
            <property name="cust_phone" column="cust_phone">property>
        class>
    hibernate-mapping>
    

    映射约束从导入的jar包hibernate-core-5.0.7.Final.jar!\org\hibernate\hibernate-mapping-3.0.dtd中复制
    Hibernate框架(初级)_第3张图片

  • 创建Hibernate的核心配置文件hibernate.cfg.xml
    配置数据库连接参数
    配置打印sql语句
    配置hibernate的方言
    配置映射文件

    
    
    <hibernate-configuration>
        <session-factory>
            
            <property name="hibernate.connection.driver_class">com.mysql.cj.jdbc.Driverproperty>
            <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/hibernate_day01?serverTimezone=Asia/Shanghai&characterEncoding=UTF-8property>
            <property name="hibernate.connection.username">rootproperty>
            <property name="hibernate.connection.password">cqrjxk39property>
            
        	<property name="hibernate.show_sql">trueproperty>
        	
        	<property name="hibernate.format_sql">trueproperty>
            
            <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialectproperty>
            <mapping resource="com/hibernate/pojo/Customer.hbm.xml">mapping>
        session-factory>
    hibernate-configuration>
    
  • 测试

    1. 加载Hibernate核心配置文件
    2. 创建SessionFactory对象:类似JDBC连接池
    3. 通过SessionFactory获取session对象:类似JDBC中的Connection
    4. 开启事务
    5. 编写代码
    6. 事务提交
    7. 资源释放
    public void test1(){
            //1. 加载Hibernate核心配置文件
            Configuration configure = new Configuration().configure();
            //2. 创建SessionFactory对象:类似于JDBC连接池
            SessionFactory sessionFactory = configure.buildSessionFactory();
            //3. 通过SessionFactory获取Session对象:类似JDBC中的Connection
            Session session = sessionFactory.openSession();
            //4. 开启事务
            Transaction transaction = session.beginTransaction();
            //5. 编写代码
            Customer customer = new Customer();
            customer.setCust_name("张三");
            session.save(customer);
            //6. 事务提交
            transaction.commit();
            //7. 资源释放
            session.close();
        }
    

总结映射的配置

  • class标签的配置:
    • 标签用来建立类与表的映射关系
    • 属性:
      • name: 类的全路径
      • table: 表名(类名与表名一致,table可以省略)
      • catalog: 数据库名
  • id标签的配置:
    • 标签用来建立类中的属性与表中主键的对应关系
    • 属性:
      • name:类中的属性名
      • column:表中的字段名(类中的属性名与表名一致,colume可以省略)
      • length:长度
  • property标签的配置:
    • 标签用来建立类中的属性与表中普通字段的对应关系
    • 属性:
      • name:类中的属性名
      • column:表中的字段名
      • length:长度
      • not-null:设置非空
      • unique:设置唯一

注意: Hibernate是可以根据映射关系自动创建表的,只需要在Hibernate的核心配置文件hibernate.cfg.xml中配置如下语句即可:

<property name="hibernate.hbm2ddl.auto">updateproperty>

总结核心配置

  • 必须配置:
    • 连接数据库的基本参数:
      • 驱动类
      • ul路径
      • 用户名
      • 密码
    • 方言
  • 可选配置:
    • 显示SQL:hibernate.show_sql
    • 格式化SQL:hibernate.format_sql
    • 自动建表:hibernate.hbm2ddl.auto
      • none:不使用hibernate的自动建表
      • create:如果数据库中已经有表,删除原有表,重新建表(测试使用)
      • create-drop:如果数据库中已经有表,删除原有表,重新建表,表格使用完后删除该表(测试使用)
      • update:如果数据库中有表使用原有表,如果数据库中没有表则创建表,可以更新表结构
      • validate:如果没有表,不会创建表,只会使用数据库中原有的表(会自动校验映射与表结构,不匹配会报错)
  • 映射文件的引入:
    • 通过mapping标签引入映射文件的位置

总结测试时需要的几个对象

Hibernate的核心配置文件既可以使用属性文件进行配置,也可以使用xml文件进行配置,但是属性文件配置时不能引入映射文件,需要手动加载映射文件。

  • Configuration:
    • 作用:
      • 加载核心配置文件
    • hibernate.properties
      • Configuration cfg = new Configuration();
      • 加载映射配置文件:cfg.addResource("com/hibernate/pojo/Customer.hbm.xml");
    • hibernate.cfg.xml
      • Configuration cfg = new Configuration().configure();
  • SessionFactory:
    • 作用:
        维护了Hibernate的连接池,线程安全的,一个项目只需要创建一个即可,所以一般将其抽取为Hibernate的工具类

Hibernate的工具类:

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class HibernateUtil {

    private static final Configuration cfg;

    private static final SessionFactory sf;

    static {
        cfg = new Configuration().configure();
        sf = cfg.buildSessionFactory();
    }

    public static Session getSession(){
        return sf.openSession();
    }
}
  • Session:Hibernate与数据库的连接对象,是Hibernate与数据库交互的桥梁,线程不安全,所以不能定义为全局变量,只能定义为局部变量
  • Session中常用的方法:
    • 保存方法,返回Serializable类型的主键:
      • Serializable save(Object obj)
    • 查询方法:
      • T get(Class clazz,Serializable id)
      • T load(Class clazz,Serializable id)
      • get和load的区别:
        1. get采用的是立即加载,当执行get方法时,立即发送SQL语句,load采用的是懒加载,当执行load方法时不会发送SQL语句,而是在使用其查询对象的时候才会发送SQL
        2. get方法返回的是真实对象本身,load返回的是代理对象,利用javassit.jar产生的代理
        3. get方法查询时数据库中找不到时,会返回空,load会抛出异常ObjectNotFoundException
    • 修改方法:(推荐使用先查询再修改)
      • void update(Object obj)
    • 删除方法:(推荐使用先查询再删除)--级联删除
      • void delete(Object obj)
    • 保存或更新:(不常用)
      • void saveOrUpdate(Object obj)
    • 查询所有:
      • Query query = session.createQuery("from 类名");
        List<类名> list = query.list();
      • SQLQuery query = session.createSQLQuery("select * from 表名");
        List<数组类型> list = query.list();

例如:

		//根据id查询
        Customer customer = session.get(Customer.class, 1L);
        System.out.println(customer);
        Customer customer1 = session.load(Customer.class, 1L);
        System.out.println(customer1);
        //修改
        Customer customer = session.get(Customer.class, 1L);
        session.update(customer);
        //删除
        Customer customer = session.get(Customer.class, 1L);
        session.delete(customer);
        //查询所有
        Query query = session.createQuery("from Customer");
        List<Customer> list = query.list();
        SQLQuery sqlQuery = session.createSQLQuery("select * from cst_customer");
        List<Object[]> list1 = sqlQuery.list();

持久化类

什么是持久化类

持久化:将内存中的一个对象持久化到数据库中的过程
持久化类:一个Java对象与数据库的表建立了映射关系,那么这个类就称为持久化类

持久化类的编写规则

  1. 必须提供一个无参构造方法,因为Hibernate底层需要使用反射生成实例
  2. 属性需要私有,并提供公有的get和set方法
  3. 对持久化类提供一个唯一的标识OID与数据库的主键相对应
  4. 持久类的属性尽量使用引用类型,因为引用类型默认值是null
  5. 持久化类尽量不要使用final修饰,因为Hibernate有一个懒加载的优化手段,返回的时代里对象,代理对象是继承这个类进行代理的

主键生成策略

主键的分类

自然主键

自然主键指的是主键本身是表中的一个字段
例如:创建一个人员表,人员都会有一个身份证号(唯一不重复),使用身份证号作为主键,这种主键称为自然主键

代理主键

代理主键指的是主键本身不是表中必须要有的字段
例如:创建一个人员表,给每一个人编一个号pno(唯一不重复),使用编号作为主键,这种主键称为代理主键

实际开发

实际开发中,尽量使用代理主键,一旦主键参与到业务逻辑中去,后期有可能要修改源代码,好的程序应该满足ocp原则,对程序扩展是open的,对修改源代码是close的

Hibernate的主键生成策略

在实际开发中一般允许用户手动设置主键,一般将主键交给数据库,手动编写程序进行设置。在Hibernate中为了减少编程,提供了多种主键生成策略。

  • increment : Hibernate中提供的增长机制,适用于short,int,long类型的主键,在单线程中使用
  • identity:适用于Int,short,long类型的主键,使用的是数据库底层的自动增长机制,适用于有自动增长机制的数据库(MySQL,oracle不支持)
  • sequence:适用于short,int,long类型的主键,采用的是序列的方式(Oracle支持序列,MySQL不支持)
  • uuid:使用于字符串类型的主键,使用Hibernate中的随机方式自动生成字符串主键
  • native:本地策略,可以在identity和sequence之间自动切换
  • assigned:Hibernate放弃主键管理,需要自己手动编写程序

例如

	<id name="cust_id" column="cust_id">
	    <generator class="native" />
	id>

持久化类的三种状态

瞬时态

这种对象没有唯一的标识OID,没有被session管理

持久态

这种对象有唯一标识OID,被session管理

脱管态

这种对象有唯一标识OID,没有被session管理

区分三种状态对象

例如:

 	public void test1(){
        Session session = HibernateUtil.getSession();
        Transaction transaction = session.beginTransaction();
        Customer customer = new Customer();//瞬时态对象
        customer.setCust_name("李四");
        Serializable id = session.save(customer);
        Customer customer1 = session.get(Customer.class, id);//持久态
        transaction.commit();
        session.close();
        System.out.println("客户名称:"+customer.getCust_name());//脱管态对象
    }
  • 瞬时态对象:
    • 获得:
      • Customer cutomer = new Customer();
    • 状态转换:
      • 瞬时 → 持久:
        • save(Object obj);
        • saveOrUpdate(Object obj);
      • 瞬时 → 脱管:
        • customer.setCust_id(1L);
  • 持久态对象:
    • 获得:
      • get();
      • load();
      • find();
      • iterate();
    • 状态转换:
      • 持久 → 瞬时:
        • delete();
      • 持久 → 脱管:
        • close();
        • clear();
        • evict(Object obj);
  • 脱管态对象:
    • 获得:
      • Customer customer() = new Customer(); customer.setCust_id(1L);
    • 状态转换:
      • 脱管 → 持久:
        • update();
        • saveIrUpdate();
      • 脱管 → 瞬时:
        • customer.setCust_id(null);

持久态的重要特点

持久态可以自动更新数据库(由Hibernate的一级缓存实现)
例如:

	public void test1(){
        Session session = HibernateUtil.getSession();
        Transaction transaction = session.beginTransaction();
        Customer customer = session.get(Customer.class, 6L);
        customer.setCust_name("王五");
        transaction.commit();
        session.close();
    }

上面的程序并有使用update方法,但是因为customer是持久态对象,所以也会更新数据库的内容为王五

Hibernate的缓存

什么是缓存

缓存是一种优化机制,可以将数据存入内存中,使用时直接从缓存中获取,不用通过存储源

Hibernate的一级缓存

Hibernate的一级缓存,又称session级别的缓存,一级缓存的生命周期与session一致,一级缓存是Hibernate自带的,不可卸载的。
特点:

  • 当应用程序调用session接口的save(),update(),saveOrUpdate()时,如果session缓存中没有相应的对象,Hibernate会自动从数据库中查询相应的对象信息到一级缓存中
  • 当应用程序调用session接口的load(),get()方法,以及query接口的list(),iterator()方法时,会判断缓存中是否存在该对象,有则返回,没有就会查询数据库,并将其添加到一级缓存中
  • 当应用程序调用session的close()方法时,session缓存会被清空

例如:

	public void test1(){
        Session session = HibernateUtil.getSession();
        Transaction transaction = session.beginTransaction();
        Customer customer = session.get(Customer.class, 6L);
        Customer customer1 = session.get(Customer.class, 6L);
        System.out.println(customer == customer1);
        transaction.commit();
        session.close();
    }

运行结果:
Hibernate框架(初级)_第4张图片
通过控制台打印的数据我们可以发现,程序的两次查询只发送了一次sql语句,并且查询得到的对象是一个对象,证明Hibernate是有一级缓存的

Query的简单使用

query接口用于接收HQL,查询多个对象

  1. 查询所有:

    	   String hql = "from Customer";
           Query query = session.createQuery(hql);
           List<Customer> list = query.list();
           for (Customer customer:list){
               System.out.println(customer);
           }
    
  2. 查询某些(带条件查询)

    		String hql = "from Customer where cust_name like ?";
            Query query = session.createQuery(hql);
            //从0开始
            query.setParameter(0,"王%");
            List<Customer> list = query.list();
            for (Customer customer:list){
                System.out.println(customer);
            }
    
  3. 分页查询

    	   String hql = "from Customer";
           Query query = session.createQuery(hql);
           //设置起始页
           query.setFirstResult(0);
           //设置每页的记录数
           query.setMaxResults(3);
           List<Customer> list = query.list();
           for (Customer customer:list){
               System.out.println(customer);
           }
    

Criteria

更加面向对象的查询,完全看不到查询语句

  1. 查询所有:

    		Criteria criteria = session.createCriteria(Customer.class);
            List<Customer> list = criteria.list();
            for (Customer customer:list){
                System.out.println(customer);
            }
    
  2. 查询某些

    		Criteria criteria = session.createCriteria(Customer.class);
            criteria.add(Restrictions.like("cust_name","王%"));
            List<Customer> list = criteria.list();
            for (Customer customer:list){
                System.out.println(customer);
            }
    
  3. 分页查询

     Criteria criteria = session.createCriteria(Customer.class);
            criteria.setFirstResult(0);
            criteria.setMaxResults(3);
            List<Customer> list = criteria.list();
            for (Customer customer:list){
                System.out.println(customer);
            }
    

SQLQuery

SQLQuery用于接收sql语句,特别复杂的请况下使用。

你可能感兴趣的:(框架)