Hibernate学习笔记

hibernate框架

1.什么是框架
提高我们的开发效率.可以理解成是一个半成品项目.

2.hibernate框架
dao层框架
操作数据库.
以面向对象的方式操作数据库.
orm 思想. 对象关系映射. 通过映射文件配置对象与数据库中表的关系
O 对象
R 关系型数据库
M 映射文件

3.hibernate框架搭建

  1. 导包
    required+驱动包

  2. 准备实体类 以及 orm元数据

  3. 创建主配置文件

  4. 书写代码测试

4.配置文件详解

  • orm元数据(xxx.hbm.xml)
		<hibernate-mapping package="">
			<class name table>
				<id name >
					<generator class="">
				</id>
				<property name="" />
  • hibernate.cfg.xml
    • 必选配置
      4+1 方言
		<!-- 数据库驱动 -->
		<property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
		 <!-- 数据库url -->
		<property name="hibernate.connection.url">jdbc:mysql:///hibernate_32</property>
		 <!-- 数据库连接用户名 -->
		<property name="hibernate.connection.username">root</property>
		 <!-- 数据库连接密码 -->
		<property name="hibernate.connection.password">1234</property>
		<!-- 数据库方言
		不同的数据库中,sql语法略有区别. 指定方言可以让hibernate框架在生成sql语句时.
		针对数据库的方言生成.
			sql99标准: DDL 定义语言  库表的增删改查
					  DCL 控制语言  事务 权限
					  DML 操纵语言  增删改查
			注意: MYSQL在选择方言时,请选择最短的方言.
		 -->
		<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
  • 可选配置
    显示sql
    格式化sql
    自动生成表
		<!-- 将hibernate生成的sql语句打印到控制台 -->
			<property name="hibernate.show_sql">true</property>
		<!-- 将hibernate生成的sql语句格式化(语法缩进) -->
			<property name="hibernate.format_sql">true</property>
		<!-- 
		## auto schema export  自动导出表结构. 自动建表
		#hibernate.hbm2ddl.auto create		
		自动建表.每次框架运行都会创建新的表.以前表将会被覆盖,表数据会丢失.(开发环境中测试使用)
		#hibernate.hbm2ddl.auto create-drop 
		自动建表.每次框架运行结束都会将所有表删除.(开发环境中测试使用)
		#hibernate.hbm2ddl.auto update(推荐使用) 
		自动生成表.如果已经存在不会再生成.如果表有变动.自动更新表(不会删除任何数据).
		#hibernate.hbm2ddl.auto validate	
		校验.不自动生成表.每次启动会校验数据库中表是否正确.校验失败.
		 -->
			<property name="hibernate.hbm2ddl.auto">update</property>
  • 指定隔离级别和orm元数据引入
		 <!-- 指定hibernate操作数据库时的隔离级别 
			#hibernate.connection.isolation 1|2|4|8		
			0001	1	读未提交
			0010	2	读已提交
			0100	4	可重复读
			1000	8	串行化
		 -->
		 <property name="hibernate.connection.isolation">4</property>
		 <!-- 指定session与当前线程绑定 -->
		 <property name="hibernate.current_session_context_class">thread</property>
		 
		 <!-- 引入orm元数据
			路径书写: 填写src下的路径
		 -->
		<mapping resource="com/dustdawn/entity/Customer.hbm.xml" />

5.api详解
Configuration 读取配置
sessionFactory 创建session
Session 获得事务操作对象,以及数据增删改查
Transaction 控制事务

hibernate实体规则

实体内创建的注意事项

  1. 持久化类提供无参数构造
  2. 成员变量私有,提供共有get/set方法访问,需提供属性
  3. 持久化类中的属性,因尽量使用包装类型(不会错,且值能为null)
  4. 持久化类需要提供oid,与数据库中的主键列对应
  5. 不要用final修饰class(非接口代理,hibernate使用cglib代理生成代理对象,代理对象是继承被代理对象,如果被final修饰将无法生成代理)

主键类型

  • 自然主键
    表的业务列中,有某业务列符合,必须有,并且不重复的特征时,该列可以作为主键使用
  • 代理主键
    表的业务列中,没有某业务列符合,必须有,并且不重复的特征时,创建一个没有业务意义的列作为主键

主键生成策略generator

就是每条记录录入时,主键的生成规则(7个)
xxx.hbm.xml

< id name=“cust_id” >
< generator class=“native”>< /generator>
< /id>

  • 代理主键

    • identity : 主键自增.由数据库来维护主键值.录入时不需要指定主键.
      • sequence: Oracle中的主键生成策略.
      • increment(了解): 主键自增.由hibernate来维护.每次插入前会先查询表中id最大值.+1作为新主键值.
      • hilo(了解): 高低位算法.主键自增.由hibernate来维护.开发时不使用.
      • native:hilo+sequence+identity 自动三选一策略.
      • uuid: 产生随机字符串作为主键. 主键类型必须为string 类型.
  • 自然主键

    • assigned:自然主键生成策略. hibernate不会管理主键值.由开发人员自己录入.

hibernate中的对象状态

Session接口是hibernate应用程序提供的操作数据库的接口,提供了基本的保存,更新,删除,和加载java对象的方法。Session具有一个缓冲,位于缓存中的对象称为持久化对象。

  • 瞬时状态
    • 没有id,没有与session关联(没有在session缓存中):customer.setCust_name("");
  • 持久化状态
    • 有id,与session关联(在session缓存中):session.save(customer);
    • 特点:持久化状态对象的任何变化自动同步到数据库中
  • 游离/托管状态
    • 有id,没有与session关联(没有在session缓存中):session.close();
      Customer c1 = new Customer();
      c1.setCust_id(1l);
      设置id不存在对应瞬时,存在则游离

session的save()方法不能理解成保存,应该理解成将瞬时状态转换成持久状态的方法。
主键自增,执行save方法,为了将对象转换成持久化状态,必须生成id值,所以需要执行insert语句生成

saveOrUpdate方法将任意对象将对象转换成持久化对象
==持久化状态的对象,会在事务提交是,自动同步到数据库中

new
get
save
delete
close
updata
起点
瞬时状态
持久化
游离/托管

hibernate使用原则:将我们希望同步到数据库的数据,对应的对象转换成持久化状态

hibernate进阶

一级缓存

  • 缓存:提高效率,hibernate中的一级缓存是为了提高操作数据库的效率

  • 一级缓存:为了提高效率,session对象中有一个可以存放对象的集合
    查询时:第一次查询时,会将对象放入缓存,再次查询时,会返回缓存中的,不再查询数据库
    修改时:会使用快照对比修改前和修改后对象的属性区别,只执行一次修改

  • 提高效率手段1:提高查询效率
    在这里插入图片描述

  • 提高效率手段2:减少不必要的的修改语句发送(快照)

在这里插入图片描述
持久化状态对象其实就是放入session缓存中的对象

hibernate中的事务

Service层
HibernateUtils.getCurrentSession().beginTransaction();
操作事务
HibernateUtils.getCurrentSession().getTransaction().commit();
HibernateUtils.getCurrentSession().getTransaction().rollback();

Dao层
Session session = HibernateUtils.getCurrentSession();
session.get();

  • 事务特性

    • A — 原子性
      事务可以看做数据库操作的容器,对事务所包裹的操作被认为像物理上的原子,是最小、不可分割的单位,要么全成功,要么全失败
    • C — 一致性
      事务在提交前后数据总量不应该发生变化(赖以保证的基础是原子性)
    • I — 隔离性
      多个事务在并发产生的时候,可能会产生一些负面问题(脏读、不可重复读、幻读)
      提供隔离级别解决
    • D — 持久性
      保证事务提交之后,涉及到操作的数据必须被写入持久化介质(如硬盘)中
  • 事务并发问题

    • 脏读
      某事务读到了另一个事务正在操作但未提交的数据
    • 不可重复读
      一次事务中两次连续的读取到的数据内容不一致(过程中其他事务修改数据并提交了)
    • 幻/虚读
      一次事务中两次连续的读取到的数据数量不一致(过程中其他事务增加数据并提交了)

解决方法:

  • 事务的隔离级别
    1)read uncommitted : 读取尚未提交的数据 :哪个问题都不能解决
    2)read committed:读取已经提交的数据 :可以解决脏读 ---- oracle默认的
    3)repeatable read:重读读取:可以解决脏读 和 不可重复读 —mysql默认的
    4)serializable:串行化:可以解决 脏读 不可重复读 和 虚读—相当于锁表操作数据只允许串行,不允许并发

知识点1. 在Hibernate中配置操作数据库中的隔离级别

 <!-- 指定hibernate操作数据库时的隔离级别 
			#hibernate.connection.isolation 1|2|4|8		
			0001	1	读未提交
			0010	2	读已提交
			0100	4	可重复读
			1000	8	串行化
		 -->
		 <property name="hibernate.connection.isolation">4</property>
		

知识点2. 在项目中如何管理事务

  • 在业务开始之前打开事务

  • 业务执行之后提交事务

  • 执行过程中出现异常回滚事务

  • 在dao层操作数据库需要用到session对象,在service层控制事务也是使用session对象完成,要保证dao层和service层使用同一个session
    解决方法
    原理:将session对象绑定到ThreadLocal线程
    调用sessionfactory.getCurrentSession()方法即可获得与当前线程绑定的session对象

    方法:hibernate.cfg.xml中配置

		 <!-- 指定session与当前线程绑定 -->
		 <property name="hibernate.current_session_context_class">thread</property>

注意1:调用getCurrentSession方法必须配合主配置中的上配置
注意2:通过getCurrentSession方法获得的session对象,当事务提交时,session会自动关闭,不要手动调用close关闭

hibernate中的批量查询

  • HQL查询(多表查询,但不复杂时使用)
    Hibernate Query Language(Hibernate独家查询语言,属于面向对象的查询语言)
    HQL语句中,不可能出现任何数据库相关的信息的

    • 基本查询
      在这里插入图片描述

    • 条件查询
      在这里插入图片描述在这里插入图片描述

    • 分页查询
      在这里插入图片描述

  • Criteria查询(单表查询)
    Hibernate自创的无语句面向对象查询

    • 基本查询
      在这里插入图片描述

    • 条件查询
      在这里插入图片描述

    • 分页查询
      在这里插入图片描述

    • 查询总记录数
      在这里插入图片描述

  • 原生SQL查询(复杂的业务查询)

    • 基本查询
      在这里插入图片描述
    • 条件查询
      在这里插入图片描述
    • 分页查询
      在这里插入图片描述

hibernate多表操作

  • 多对一/一对多

    • 关系表达
      表中的表达:外键指向一的一方主键
      在对象中的表达:使用集合表达,一的一方持有多个多的一方
      使用对象引用一的一方,表达多的一方属于哪个一的一方
      在这里插入图片描述
    • 操作
      在这里插入图片描述
      	<set name="linkMens" cascade="save-update" inverse="true">
      	<!--外键列名  -->
      	<key column="lkm_cust_id"></key>
      	<one-to-many class="LinkMan" />
      	</set>
      
      <many-to-one name="customer" column="lkm_cust_id" class="Customer"  >
      </many-to-one>
      
    • 级联操作
      在这里插入图片描述
      <set name="linkMens" cascade="save-update">
      
    • 关系维护
      在保存时,两方都会维护外键关系,关系维护两次造成冗余,多余的维护关系语句显然是客户这一端在维护关系(联系人一端通过外键已经维护关系)
      在这里插入图片描述
      多的一方(LinkMan)不能放弃维护关系,因为外键字段就在多的一方
      原则:无论怎么放弃,总有一方必须要维护关系
      一对多关系中:只能一的一方放弃维护,多的一方不能放弃维护
      ( 如果客户放弃维护与联系人的关系. 维护关系的代码可以省略
      /* c.getLinkMens().add(lm1);
      c.getLinkMens().add(lm2); */
      如果执行删除主表操作时,主表选择维护关系,可以解除与从表的外键约束,从表外键置空,记录不变,级联操作为delete时,会将两表一同删除)
  • 多对多

    • 关系表达
      使用中间表,至少两列,都是外键列,分别引用两张表的主键
      两方都使用集合来表达拥有多个对方
    • 操作
      orm元数据xxx.hbm.xml在这里插入图片描述
      在这里插入图片描述
      将来在开发中,如果遇到多对多关系.一定要选择一方放弃维护关系.
      一般谁来放弃要看业务方向. 例如录入员工时,需要为员工指定所属角色.
      那么业务方向就是由员工维护角色. 角色不需要维护与员工关系.角色放弃维护
    • 级联操作
      在这里插入图片描述

hibernate的多表查询

  • 查询总结

    • oid查询—get方法
      session.get(实体类.class,id)

    • 对象属性导航查询

    • HQL

      • 基础语法
        在这里插入图片描述
      • 排序
        在这里插入图片描述
      • 条件
        在这里插入图片描述
      • 分页
        在这里插入图片描述
      • 聚合
        在这里插入图片描述
      • 投影
        在这里插入图片描述
      • 多表查询
        内连接(迫切fetch封装成一个对象) inner join(fetch)
        外连接
      1. 左外(迫切) left join(fetch)
      2. 右外(迫切)right join(fetch)
    • Criteria

      • 基本语法在这里插入图片描述 在这里插入图片描述
      • 离线查询

      在这里插入图片描述 在这里插入图片描述

    • 原生SQL

  • 查询优化

    • 类级别查询
      session.get()方法:没有任何策略,调用即立即查询数据库加载数据

    session.load()方法(true:默认延迟加载):是在执行时,不发送任何sql语句,返回一个对象,使用该对象时,才执行查询(orm元数据文件中class元素上配置lazy属性来控制:
    < class name=“Customer” table=“cst_customer” lazy=“true”>)

      延迟加载:仅仅获得没有使用,不会查询,在使用时才进行查询
      
      lazy(默认值):true,查询类时,会返回代理对象(带$符号)不去查询,而在使用属性时,调用代理对象增强的方法,根据关联的session查询数据库加载数据
    

    结论:为了提高效率.建议使用延迟加载(懒加载),优化查询

    • 关联级别查询
      set元素中配置
      对象属性导航:Customer的属性getLinkMen导航另一个对象

      • 集合策略(一的一方Customer,取LinkMan)

        • 延迟加载&抓取策略
          extra:如果只获得集合的size,只查询集合的size(count语句),不会打印数据
          fetch为join时,类级别加载lazy属性失效
          在这里插入图片描述
      • 关联属性策略(多的一方LInkMan,加载Customer)
        在这里插入图片描述
        结论:为了提高效率.fetch的选择上应选择select, lazy的取值应选择 true. 全部使用默认值.

      • no-session问题解决
        采用上结论懒加载时,返回页面是为代理对象,到达页面时service层执行完毕,session关闭,会出现懒加载初始化缺少session对象的情况

      解决方法:通过Filter扩大session的作用范围
      在这里插入图片描述

    • 批量抓取
      遍历每个客户都要用sql语句查询联系人
      在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值