天天看点

Hibernate学习笔记hibernate框架hibernate实体规则hibernate中的对象状态hibernate多表操作hibernate的多表查询

Hibernate

  • hibernate框架
  • hibernate实体规则
    • 实体内创建的注意事项
    • 主键类型
    • 主键生成策略generator
  • hibernate中的对象状态
    • hibernate进阶
    • hibernate中的事务
    • hibernate中的批量查询
  • hibernate多表操作
  • 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方法将任意对象将对象转换成持久化对象

==持久化状态的对象,会在事务提交是,自动同步到数据库中

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

hibernate进阶

一级缓存

  • 缓存:提高效率,hibernate中的一级缓存是为了提高操作数据库的效率
  • 一级缓存:为了提高效率,session对象中有一个可以存放对象的集合

    查询时:第一次查询时,会将对象放入缓存,再次查询时,会返回缓存中的,不再查询数据库

    修改时:会使用快照对比修改前和修改后对象的属性区别,只执行一次修改

  • 提高效率手段1:提高查询效率
    Hibernate学习笔记hibernate框架hibernate实体规则hibernate中的对象状态hibernate多表操作hibernate的多表查询
  • 提高效率手段2:减少不必要的的修改语句发送(快照)
Hibernate学习笔记hibernate框架hibernate实体规则hibernate中的对象状态hibernate多表操作hibernate的多表查询

持久化状态对象其实就是放入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语句中,不可能出现任何数据库相关的信息的

    • 基本查询
      Hibernate学习笔记hibernate框架hibernate实体规则hibernate中的对象状态hibernate多表操作hibernate的多表查询
    • 条件查询
      Hibernate学习笔记hibernate框架hibernate实体规则hibernate中的对象状态hibernate多表操作hibernate的多表查询
      Hibernate学习笔记hibernate框架hibernate实体规则hibernate中的对象状态hibernate多表操作hibernate的多表查询
    • 分页查询
      Hibernate学习笔记hibernate框架hibernate实体规则hibernate中的对象状态hibernate多表操作hibernate的多表查询
  • Criteria查询(单表查询)

    Hibernate自创的无语句面向对象查询

    • 基本查询
      Hibernate学习笔记hibernate框架hibernate实体规则hibernate中的对象状态hibernate多表操作hibernate的多表查询
    • 条件查询
      Hibernate学习笔记hibernate框架hibernate实体规则hibernate中的对象状态hibernate多表操作hibernate的多表查询
    • 分页查询
      Hibernate学习笔记hibernate框架hibernate实体规则hibernate中的对象状态hibernate多表操作hibernate的多表查询
    • 查询总记录数
      Hibernate学习笔记hibernate框架hibernate实体规则hibernate中的对象状态hibernate多表操作hibernate的多表查询
  • 原生SQL查询(复杂的业务查询)
    • 基本查询
      Hibernate学习笔记hibernate框架hibernate实体规则hibernate中的对象状态hibernate多表操作hibernate的多表查询
    • 条件查询
      Hibernate学习笔记hibernate框架hibernate实体规则hibernate中的对象状态hibernate多表操作hibernate的多表查询
    • 分页查询
      Hibernate学习笔记hibernate框架hibernate实体规则hibernate中的对象状态hibernate多表操作hibernate的多表查询

hibernate多表操作

  • 多对一/一对多
    • 关系表达

      表中的表达:外键指向一的一方主键

      在对象中的表达:使用集合表达,一的一方持有多个多的一方

      使用对象引用一的一方,表达多的一方属于哪个一的一方

      Hibernate学习笔记hibernate框架hibernate实体规则hibernate中的对象状态hibernate多表操作hibernate的多表查询
    • 操作
      Hibernate学习笔记hibernate框架hibernate实体规则hibernate中的对象状态hibernate多表操作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>
                 
    • 级联操作
      Hibernate学习笔记hibernate框架hibernate实体规则hibernate中的对象状态hibernate多表操作hibernate的多表查询
    • 关系维护

      在保存时,两方都会维护外键关系,关系维护两次造成冗余,多余的维护关系语句显然是客户这一端在维护关系(联系人一端通过外键已经维护关系)

      Hibernate学习笔记hibernate框架hibernate实体规则hibernate中的对象状态hibernate多表操作hibernate的多表查询

      多的一方(LinkMan)不能放弃维护关系,因为外键字段就在多的一方

      原则:无论怎么放弃,总有一方必须要维护关系

      一对多关系中:只能一的一方放弃维护,多的一方不能放弃维护

      ( 如果客户放弃维护与联系人的关系. 维护关系的代码可以省略

      如果执行删除主表操作时,主表选择维护关系,可以解除与从表的外键约束,从表外键置空,记录不变,级联操作为delete时,会将两表一同删除)

  • 多对多
    • 关系表达

      使用中间表,至少两列,都是外键列,分别引用两张表的主键

      两方都使用集合来表达拥有多个对方

    • 操作

      orm元数据xxx.hbm.xml

      Hibernate学习笔记hibernate框架hibernate实体规则hibernate中的对象状态hibernate多表操作hibernate的多表查询
      Hibernate学习笔记hibernate框架hibernate实体规则hibernate中的对象状态hibernate多表操作hibernate的多表查询

      将来在开发中,如果遇到多对多关系.一定要选择一方放弃维护关系.

      一般谁来放弃要看业务方向. 例如录入员工时,需要为员工指定所属角色.

      那么业务方向就是由员工维护角色. 角色不需要维护与员工关系.角色放弃维护

    • 级联操作
      Hibernate学习笔记hibernate框架hibernate实体规则hibernate中的对象状态hibernate多表操作hibernate的多表查询

hibernate的多表查询

  • 查询总结
    • oid查询—get方法

      session.get(实体类.class,id)

    • 对象属性导航查询
    • HQL
      • 基础语法
        Hibernate学习笔记hibernate框架hibernate实体规则hibernate中的对象状态hibernate多表操作hibernate的多表查询
      • 排序
        Hibernate学习笔记hibernate框架hibernate实体规则hibernate中的对象状态hibernate多表操作hibernate的多表查询
      • 条件
        Hibernate学习笔记hibernate框架hibernate实体规则hibernate中的对象状态hibernate多表操作hibernate的多表查询
      • 分页
        Hibernate学习笔记hibernate框架hibernate实体规则hibernate中的对象状态hibernate多表操作hibernate的多表查询
      • 聚合
        Hibernate学习笔记hibernate框架hibernate实体规则hibernate中的对象状态hibernate多表操作hibernate的多表查询
      • 投影
        Hibernate学习笔记hibernate框架hibernate实体规则hibernate中的对象状态hibernate多表操作hibernate的多表查询
      • 多表查询

        内连接(迫切fetch封装成一个对象) inner join(fetch)

        外连接

      1. 左外(迫切) left join(fetch)
      2. 右外(迫切)right join(fetch)
    • Criteria
      • 基本语法
        Hibernate学习笔记hibernate框架hibernate实体规则hibernate中的对象状态hibernate多表操作hibernate的多表查询
        Hibernate学习笔记hibernate框架hibernate实体规则hibernate中的对象状态hibernate多表操作hibernate的多表查询
      • 离线查询
      Hibernate学习笔记hibernate框架hibernate实体规则hibernate中的对象状态hibernate多表操作hibernate的多表查询
      Hibernate学习笔记hibernate框架hibernate实体规则hibernate中的对象状态hibernate多表操作hibernate的多表查询
    • 原生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属性失效

          Hibernate学习笔记hibernate框架hibernate实体规则hibernate中的对象状态hibernate多表操作hibernate的多表查询
      • 关联属性策略(多的一方LInkMan,加载Customer)
        Hibernate学习笔记hibernate框架hibernate实体规则hibernate中的对象状态hibernate多表操作hibernate的多表查询
        结论:为了提高效率.fetch的选择上应选择select, lazy的取值应选择 true. 全部使用默认值.
      • no-session问题解决

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

      解决方法:通过Filter扩大session的作用范围
      Hibernate学习笔记hibernate框架hibernate实体规则hibernate中的对象状态hibernate多表操作hibernate的多表查询
    • 批量抓取

      遍历每个客户都要用sql语句查询联系人

      Hibernate学习笔记hibernate框架hibernate实体规则hibernate中的对象状态hibernate多表操作hibernate的多表查询

继续阅读