hibernate相关知识的总结

Hibernate是什么
 面向java环境的对象/关系数据库映射工具。
1.开源的持久层框架.
2.ORM(Object/Relational Mapping)映射工具,建立面向对象的域模型和关系数据模型之间的映射.
3.连接java应用和数据库的中间件.
4.对JDBC进行封装,负责java对象的持久化.
5.在分层结构中处于持久化层,封装对数据库的访问细节,
  使业务逻辑层更专注于实现业务逻辑
为什么要用Hibernate 
     1、Hibernate对JDBC访问数据库的代码做了封装,大大简化
          了数据访问层繁琐的重复性代码。  ?2、Hibernate是一个基于jdbc的主流持久化框架,是一个优秀
           的orm实现,它很大程度的简化了dao层编码工作。  ?3、Hibernate使用java的反射机制,而不是字节码增强程序类实现
           透明性  ?4、Hibernate的性能非常好,因为它是一个轻量级框架。映射的灵
           活性很出色。它支持很多关系型数据库,从一对一到多对多的各
           种复杂关系。  

使用jdbc的问题:
1.操作数据相对繁琐
2.数据库字段发生变化时,对应sql语句都要发生变化,不利于后期维护
解决问题:封装(hibernate)
配置文件(将javabean与数据库表进行关联) 放到与Customer类同级的目录下,并且名称一样
Customer.hbm.xml
<hibernate-mapping>
 <!--class:持久化类javabean与表的映射-->
 <class name="cn.itcast.Customer" table="customer">
  <!--id:用来映射主键ID-->
  <id name="id"  type="integer">
   <column name="id"></column>
   <!--gererator:主键生成策略-->
   <gererator class="increment"/>
  </id>
  <!--type:表示hibernate的数据类型,用来关联java的数据类型和数据库的数据类型-->
  <property name="name" column="name" type="string">
  ...
 </class>
</hibernate-mapping>
配置文件(配置连接数据库基本信息)
hibernate.cfg.xml
<hibernate-configration>
 <sessionFactory>
  <!--基本配置-->
  <property name="hibernate.connection.driverClass">com.mysql.jdbc.Driver</property>
  <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/database?useUnicode=true&amp;characterEncoding=utf8</property>
  <property name="hibernate.connection.username">root</property>
  <property name="hibernate.connection.password">root</property>
  <!--方言-->
  <property name="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</property>
  <!--
   自动将配置文件.hbm.xml的配置信息关联数据库表
   create:表不存在时创建,存在时先删再创建,然后添加数据
   none:追加数据,不能创建表
   update:表不存在时创建,存在时追加数据
  -->
  <property name="hibernate.hbm2ddl.auto">update</property>
  <!--是否显示sql语句-->
  <property name="hibernate.show_sql">true</property>
  <!--是否对sql语句格式化-->
  <property name="hibernate.format_sql">true</property>
 </sessionFactory>
</hibernate-configration>

加载配置文件:
Configuration configuration = new Configuration();
1.加载hibernate.cfg.xml
configuration.configure();//默认加载类路径下文件
configuration.configure("cn/itcast/../hibernate.cfg.xml");
2.加载Customer.hbm.xml  要求配置文件和类放置到同一个目录下,并且名称一致
(1)configuration.addClass(Customer.class);
(2)configuration.addResource("cn/itcast/../Customer.hbm.xml");
(3)使用配置文件加载,在hibernate.cfg.xml中配置,项目中使用最多
   <mapping resource="cn/itcast/../Customer.hbm.xml">

hibernate与jdbc对比:
hibernate:SessionFactory工厂(SessionFactory)、创建多个Session(Session)、使用Session来操作数据库(CURD)
jdbc:连接池(DataSource)、多个连接(Connection)、使用Connection来操作数据库(CURD)

hibernate基本配置:
1.使用hibernate更加面向对象(使用对象操作数据库),对DAO层封装,也就是对JDBC的封装
2.建立工程
3.导入相应的jar包
4.建立一个持久化的javabean
5.建立Xxx.hbm.xml,用来映射持久化对象与数据库表的对应关系,规范在hibernate核心包下org.hibernate.hibernate-mapping-3.0.dtd
6.建立连接数据库信息的配置文件hibernate.cfg.xml,该文件放置到src目录下,规范在hibernate核心包下org.hibernate.hibernate-  configuration-3.0.dtd
7.测试操作数据库的CURD
Hibernate的运行过程如下:
1、应用程序先调用Configuration类,该类读取Hibernate配置文件及映射文件中的信息,
2、并用这些信息生成一个SessionFactory对象,
3、然后从SessionFactory对象生成一个Session对象,
4、并用Session对象生成Transaction对象;
    A、可通过Session对象的get(),load(),save(),update(),delete()和saveOrUpdate()等方法对PO进行加载、保存、更新、删除、等操作;
    B、在查询的情况下,可通过Session对象生成一个Query对象,然后利用Query对象执行查询操作;如果没有异常,Transaction对象将提交这些操作到数据库中。

SessionFactory接口:SessionFactory负责维护Hibernate的二级缓存;SessionFactory是生成Session的工厂;是线程安全的

Session接口:Session是应用程序与数据库之间交互操作的一个单线程对象,是 Hibernate 运作的中心,所有持久化对象必须在 session 的管理下才可以进行持久化操作。此对象的生命周期很短。Session 对象有一个一级缓存,显式执行 flush 之前,所有的持久层操作的数据都缓存在 session 对象处。相当于 JDBC 中的 Connection。是线程不安全的。
session的一级缓存:当使用get或者load方法通过OID进行查询数据库的时候,会将查询结果放到session的一级缓存中,如果使用同一个OID再次查询时,会先到session的一级缓存中查找是否有相同的OID对象,如果有则直接读取,不再查询数据库;如果没有则查询数据库,并将查询结果放到session的一级缓存中。当session关闭时,一级缓存数据将不存在。

session快照
commit:先清理session的一级缓存,让缓存中的数据与数据库同步,然后再提交事务。
当使用get或者load方法通过OID进行查询数据库的时候,会将查询结果放到session的一级缓存中,同时将数据产生(复制)一份快照,当修改session一级缓存中的数据时,并且执行commit()或者s.flush(),表示清理session的一级缓存,此时hibernate会使用OID查找快照中对应的OID对象的数据,然后比对,如果2个OID对象一样,不会执行update语句,如果2个OID对象不一样,会执行update语句。

主键生成策略(表示符生成器):
increment:由Hibernate以递增的方式为代理主键赋值
Hibernate会先读取表中的主键的最大值,而接下来向表中插入记录时, 就在 max(id) 的基础上递增,增量为1(带走加1:多线程有并发问题)
不依赖于底层数据库系统,适合所有的数据库系统;适用于只有单个Hibernate应用进程访问同一个数据库的场合;
OID必须为long,int或short

identity:底层数据库把主键定义为自动增长字段类型(加1带走:多线程没有并发问题)
底层数据库系统必须支持自动增长字段类型;OID 必须为 long, int 或 short

native:依据底层数据库对自动生成标识符的支持能力, 来选择使用 identity, sequence 或 hilo 标识符生成器
适合于跨数据库平台开发;
OID 必须为 long, int 或 short

复合主键
1.<composite-id>
   <key-property name="" column="" type=""/>
   <key-property name="" column="" type=""/>
  </composite-id>
2.将复合主键单独创建一个类,在持久化类中用一个属性表示
<composite-id name="" class="">

uuid:Hibernate会产生不重复的32位字符串作为主键

关联关系
<many-to-one name="外键属性名" class="外键属性对应类路径" cascade="save-update">
 <column name="表中外键名"></column>
</many-to-one>
自动持久化所关联对象
cascade="save-update",表示级联保存和更新,当保存或更新对象时,此时会级联保存或更新和此对象相关联的其他对象,也就是将对象持久化

<set name="持久化类中集合的属性名称" table="集合属性映射的多的一端外键表名称" cascade="save-update">
 <key>
  <column name="外键列的名称"></column>
 </key>
 <one-to-many class="一对多集合中对应的类型全路径"/>
</set>
Hibernate要求在持久化类中定义集合属性时,必须把属性声明为接口类型;创建集合0表示初始集合的同时初始化集合的长度,避免空指针异常

对象导航:在两端都配置cascade="save-update",保存一个对象,与之相关联的对象也会保存

inverse:在hibernate中通过对inverse属性的值决定是由双向关联的哪一方来维护表和表之间的关系.inverse=false 的为主动,inverse=true 的为被动方, 由主动方负责维护关联关系。在没有设置 inverse=true 的情况下,父子两边都维护父子关系。
在 1-n 关系中,将 n 方设为主控方将有助于性能改善。

建立两个对象的关联关系:
customer.getOrders().add(order);

order.setCustomer(customer);同时修改关联两端的相应属性会使程序更加健壮,提高业务逻辑层的独立性,使业务逻辑层的程序代码
不受Hibernate实现类的影响。

解除两个对象的关联关系:
Customer.getOrders().remove(order);

Order.setCustomer(null);

级联删除:cascade="delete"  当删除对象的同时,级联删除和对象表相关的外键表中的数据。

自动删除解除了关联关系的对象(删除孤儿):cascade="delete-orphan" 或 cascade="all-delete-orphan"(包含所有行为)

在数据库中对集合排序:<set order-by="id desc/asc">

操纵持久化对象
session.flush();清理session的一级缓存,让缓存中的数据与数据库同步,从而进行CRUD操作,方向:缓存--->数据库,缓存中的数据不丢失
tx.commit():先调用session.flush()清理session的一级缓存,让缓存中的数据与数据库同步,然后再提交事务

session.clear();清空缓存,将一级缓存中的数据清空
session.refresh();重新刷新缓存区域,使缓存中的数据与数据库同步,方向:数据库--->缓存,使用对象的OID再查询一遍数据库

缓存清理模式:
session.setFlushMode(FlushMode.NEVER);//永不清理缓存
s.flush();此时可以清理session缓存
commit();此时不调用flush()

hibernate中java对象的状态:

持久化状态(托管):OID 不为 null
;位于 Session 缓存中
;持久化对象和数据库中的相关记录对应;如果从临时对象转变而来,此时在数据库中不存在对应记录;Session 在清理缓存时, 会根据持久化对象的属性变化, 来同步更新数据库;
在同一个 Session 实例的缓存中, 数据库表中的每条记录只对应唯一的持久化对象

临时状态:OID 通常为 null
;不处于 Session 的缓存中
;在数据库中没有对应的记录

游离状态(脱管):OID 不为 null
;不再处于 Session 的缓存中;
一般情况需下, 游离对象是由持久化对象转变过来的, 因此在数据库中可能还存在与它对应的记录。

删除状态:OID 不为 null
;从一个 Session实例的缓存中删除
;Session 已经计划将其从数据库删除, Session 在清理缓存时, 会执行 SQL delete 语句, 删除数据库中的对应记录。

evict():持久化状态--->游离状态
update():游离状态--->持久化状态

unsave-value:用来判断当前对象是临时对象还是持久对象,默认值是0

get()  load()
1.相同点:都可以根据给定的OID从数据库中加载一个持久化对象
2.不同点:当数据库中不存在与 OID 对应的记录时, load() 方法抛出 ObjectNotFoundException 异常, 而 get() 方法返回 null

2013.7.12
组件:一个类(Address)不能单独映射一个表,它的存在依赖于另一个主体类(Customer)
Customer.hbm.xml
<component name="持久化对象类中的属性" class="该属性的对应数据类型(全路径)">
 <parent name="customer"/>//表示是属于整体类的一部分(可加可不加)
 <property name="组件中的属性名" column="映射数据表的列" type="hibernate的数据类型"/>
</component>

持久化类的属性分为两种:
值(value)类型: 没有 OID, 不能被单独持久化, 生命周期依赖于所属的持久化类的对象的生命周期,组件类型就是一种值类型
实体(entity)类型: 有 OID, 可以被单独持久化, 有独立的生命周期

映射多对多的关联关系:使用set集合
中间表:将多对多的关系分成两个一对多的关系
多对多的关联关系修改中间表的时候,不是执行update,而是先删除再插入

若管理关联关系的一方(主控方)删除该表数据时,先删除中间表与另一表相关联的数据,然后再删除该表数据

hibernate的检索策略:

立即检索:立即加载检索方法指定的对象,lazy="false"。
*会使用OID立即查询数据库,获取该对象所有的的属性。
延迟检索:延迟加载检索方法指定的对象,lazy="true"。
*当使用load方法通过OID进行查询的时候,会生成一个代理对象,代理对象只初始化OID,查其他属性时才查询数据库,显示sql语句,获取相应的其他属性的值。
迫切左外连接检索(fetch属性值设为“join”):通过左外连接加载与检索指定的对象关联的对象。
<class lazy="true">//说明当前类默认是延迟检索
get方法使用OID进行查询时,永远是立即检索
只有使用load方法才能够测试出立即检索和延迟检索

判断当前对象是延迟检索还是立即检索,判断当前对象是否对值进行初始化: Hibernate.isInitialized(c)
对其进行初始化:
方法一:只要调用除OID之外的其他属性,此时可以对代理对象进行初始化.
方法二:将代理对象进行初始化,查询数据库,对数据进行初始化: Hibernate.initialize(c);

类级别的检索:session的方法直接检索Customer对象,对Customer对象到底采用立即检索
还是延迟检索方式
通过class元素的lazy属性设定。
关联级别的检索:通过set元素lazy属性设定。

关联级别set中
* lazy = true(默认值):延迟检索,延迟加载只要调用关联的订单对象时才查询数据库
* lazy = false:立即检索,只要初始化客户对象,和它关联的集合对象也马上被初始化(马上查询数据库)

一对多和多对多关联的检索策略(set): <set> 元素的 lazy 和 fetch 属性:
fetch        lazy
-------------------------------------
join      false 采用迫切左外联接检索。
join      true 采用迫切左外联接检索。
join      extra 采用迫切左外联接检索。
select      false 采用立即检索
select      true 采用延迟检索
select      extra 采用延迟检索(极其懒惰:只查需要的)
subselect    false 采用立即检索(嵌套子查询)
subselect    true 采用延迟检索(嵌套子查询)
subselect    extra 采用延迟检索(极其懒惰)(嵌套子查询)

迫切左外连接检索(fetch 属性值设为 “join”)
Query 的list() 方法会忽略映射文件中配置的迫切左外连接检索策略,而依旧采用立即检索还是延迟加载策略由set集合的lazy属性决定。

组合1 many2one立即检索+set立即检索
<many-to-one name="customer" class="cn.itcast.l_query.Customer" fetch="select" lazy="false">
<set name="orders" table="l_order" inverse="true" fetch="select" lazy="false">

组合2 many2one迫切左外+set立即检索
<many-to-one name="customer" class="cn.itcast.l_query.Customer" fetch="join" lazy="false">
<set name="orders" table="l_order" inverse="true" fetch="select" lazy="false">

组合3 many2one立即检索+set迫切左外
<many-to-one name="customer" class="cn.itcast.l_query.Customer" fetch="select" lazy="false">
<set name="orders" table="l_order" inverse="true" fetch="join" lazy="false">

批量检索  从一的一端查询  查询所有的客户:<set> 元素有一个batch-size 属性,用来为延迟检索策略或立即检索策略设定批量检索的数量. 批量检索能减少 SELECT 语句的数目, 提高延迟检索或立即检索的运行性能.  默认值是1。
注:query.list()属于hql检索,hql检索忽略关联级别的迫切左外连接检索,只与lazy属性有关.
当在<set>元素中定义batch-size=3(使用嵌套子查询合并sql语句)

批量检索  从多的一端查询  查询所有的订单:在Customer.hbm.xml文件中增加batch-size属性
当在Customer.hbm.xml的<class>元素中定义batch-size=3(使用嵌套子查询合并sql语句)

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章