关于Hibernate,老师讲了很多,可让自己写总结才发现写不出来什么。就随便写了鞋关于自己学习笔记的一些整理。
hibernate完全是建立在JDBC的基础上的。
那为什么还要用hibernate呢?
JDBC无法直接面向对象
开发效率低
代码冗余
重复性工作多
hibernate的优势 :
Hibernate是一个开发源代码的对象关系映射框架
对JDBC进行了非常轻量级的对象封装, 简化了JDBC 繁琐的编码
将JavaBean对象和数据库的表建立对应关系
下面就说一下编程时用Hibernate实现项目的步骤:
1.创建项目并导入jar包
2.创建Hibernate主配置文件
用于配置数据库连接
运行时所需的各种属性
默认文件名为“hibernate.cfg.xml”
主配置文件内容包括:
(1) 数据库连接信息:驱动程序类名、URL、用户名、密码。
(2) Hibernate相关特性:dialect(方言)、show_SQL(输出SQL语句到控制台)、format_SQL(格式化SQL语句)。
(3) 连接池相关信息。
(4) 实体类映射文件:实体类与数据库表之间的逻辑映射。
3.学会使用Hibernate完成数据增删改操作
3.1 创建实体类
这个我们在学习钱就是先编好了,不过还是有几点要注意:
把类属性的访问级别设成私有的;
所有的实体类都要求有无参的构造器, 因为Hibernate需要使用Java反射机制来为你创建对象;
要为实体类实现Java.io.Serializable 接口,以便Hibernate能更好的缓存实体对象;
3.2创建和配置映射文件
告诉hibernate应该访问数据库里面的哪个表及应该使用表里面的哪些字段
注意映射关系的对应:类与表,
属性与主键(映射文件的<id>元素定义了该属性到数据库表主键字段的映射。),
主键生成策略:主键生成器generator是可选的,它用于指定实体对象的标识符(在表中称之为主键)生成策略。
属性与普通字段
<hibernate-mapping>
<!-- 类和表 -->
<class name="entity.Student" table="students">
<!-- 属性和主键 -->
<id name="id" column="stu_id">
<!-- 主键生成策略 -->
<generator class="sequence">
<param name="sequence">lib_seq</param><!--sequence对象的名字 -->
</generator>
</id>
<!-- 属性和字段 -->
<property name="name" column="name"></property>
</class>
</hibernate-mapping>
注意:填写类名时应为全限定名3.3 在主配置文件中添加实体映射文件路径
3.3将映射文件的路径信息添加到hibernate.cfg.xml中。
<mapping resource=“***/***/***.hbm.xml" />
3.4 以上步骤完成后,测试一下
3.5 数据库操作
包含七个步骤:
(1)获取配置,默认读取classpath根目录下名为hibernate.cfg.xml的文件
(2)创建Sessionfactory
(3)获取Session——Hibeinate持久化管理器,通过它可以做增删改查
(4)开始事务
(5)持久化操作(即增删改查)
(6)提交事务
(7)关闭Session
可在编写映射文件时会遇到有些实体与实体之间存在相互关联该怎样编写入映射文件呢?这就需要了解到关联映射的相关知识了。
关联映射
关联关系:通过一个对象持有另一个对象的实例。
除了将实体与表进行映射之外,还要将实体的关联关系与表的关联关系进行映射。我们要关注的是以下三个方面:
关联关系在实体中如何体现;
关联关系在映射文件(hbm.xml)中如果体现;
如何完成级联操作
单向多对一关联(many-to-one)
实体文件中,many的一端应持有one的一端的对象(引用)
映射文件体现多对一
例:每本书都拥有一个类型,而一个类型拥有多本不同的书
public class Book {
private int id;
private String name;
private String author;
private Type type;
public class Type {
private int id;
private String name;
book的映射文件
<class name="entity.Book" table="book">
<!—主键映射及属性映射(省略) -->
<!-- 多对一关联 -->
<many-to-one name="type" class="entity.Type">
<column name="type_id"></column>
</many-to-one>
</class>
注:多对一关联中,name为many一端实体类中设置的one类型的属性,class为one类名,column为外键列列名
单向一对多关联(one-to-many)
实体文件中,one的一端应持有many端的对象集合
映射文件体现一对多
关联操作
public class Type {
private int id;
private String name;
private String desc;
private Set<Book> books;
映射文件例:
<class name="entity.Type" table="types">
<!—主键映射及属性映射(省略) -->
<!—一对多关联 -->
<set name="books"> <key column="type_id"></key> <one-to-many class="entity.Book" /> </set> </class>
双向一对多/一对一关联
双向一对多就是同时配置了单向的一对多和单向的多对一。
一对一关联是特殊的一对多关联,many的一端是唯一的而不是多个。
Many-to-many多对多关联
将多对多转换成两个一对多
为中间表建立实体类及映射文件,两个端点和中间端分别建立双向一对多关联
例:每条借书记录包含一个学生信息,一条书籍信息;而每个学生或每本书籍都可拥有多条借阅记录;即一个学生可借多本书,一本书也可被多个不同的学生借走。
public class Record {
private Book book;
private Student stu;
如果中间表是联合主键:
<!-- 类和表 -->
<class name="entity.Record" table="record">
<!-- 属性和主键 -->
<!-- 联合主键 -->
<composite-id>
<!--同时表达这是外键 -->
<key-many-to-one name="book" column="book_id" class="entity.Book"></key-many-to-one>
<key-many-to-one name="stu" column="stu_id" class="entity.Student"></key-many-to-one>
</composite-id>
<!-- 属性和字段(省略) -->
</class>
下面说一下 编程过程中涉及到的一些Hibernate核心的接口
Hibernate核心接口
Configuration接口
Configuration对象用来配置和引导Hibernate,一个Hibernate应用使用一个Configuration实例来指定主配置文件的位置,然后创建会话工厂。
Configuration cfg = new Configuration().configure("/cfg/auction.cfg.xml")
Sessionfactory接口
一个Hibernate应用从SessionFactory(会话工厂)里获得会话实例。
一般情况下,整个应用只有唯一的一个SessionFactory,它应该在应用初始化时被创建。
Session接口
Session(会话)接口是Hibernate应用使用的主要接口,它拥有操作持久化对象的一系列API,可用于管理(例如加载和保存)对象,因此我们也称之为“持久化管理器”。
Transaction接口
Transaction(事务接口)
Query接口
执行查询,并控制查询如何具体执行。查询使用HQL或SQL。Query实例可用来绑定查询参数,限定查询返回的结果数,并且最终执行查询。
Hibernate学习中有两点值得注意:
1.对象的状态
2缓存及加载方式
实体对象的三种状态
实体对象的生命周期是Hibernate 应用中的一个关键概念
实体对象的三种状态
瞬时状态(Transient)
刚用new语句创建,还没有被持久化,且不处于Session的缓存中
持久状态(Persistent)
已经被持久化,且加入到Session的缓存中
游离状态(Detached)
已经被持久化,但不再处于Session的缓存中
app操作对象状态,在某一时刻,Hibernate会将对象状态同步到数据库
new产生的对象—瞬时态,瞬时对象的状态的改变不会被同步,直到它变成一个持久状态。通过save saveOrUpdate方法转换为持久态,通过delete方法可以将对象变回瞬时态
session关闭之后,原有的持久态就变成了游离态,游离对象的状态的改变不会被同步,直到它变成一个持久状态。游离态通过系列方法可重新回到持久态,并在事务提交的时候和数据库同步
session的get load方法可直接获得一个持久态对象。
持久态和游离态的共同点在于,都有数据表的一行与之对应,不同的是,持久态在session范围内,而游离态不在session范围内。
默认Hibernate使用延迟加载策略
含义:主对象的关联对象或集合不立即抓取;
加载主对象时其仍为一个代理;
只有当需要使用到关联对象或集合,才会对其进行加载;
又称为代理对象的初始化。
但是,延迟加载仅在session范围内有效——持久对象上才能有延迟加载。
缓存与加载方式
缓存就是为了提高效率和节约资源,有一级缓存和二级缓存。
一级缓存就是Session级别的缓存,一个Session做了一个查询操作,它会把这个操作的结果放在一级缓存中,如果短时间内这个session(一定要同一个session)又做了同一个操作,那么hibernate直接从一级缓存中拿,而不会再去连数据库,取数据。
二级缓存就是SessionFactory级别的缓存,顾名思义,就是查询的时候会把查询结果缓存到二级缓存中,如果同一个sessionFactory创建的某个session执行了相同的操作,hibernate就会从二级缓存中拿结果,而不会再去连接数据库。
加载方式
加载方式有四个关注点:
1主对象的关联对象,2主对象的关联集合,3主对象本身,4主对象的属性。
第一层对象称为主对象,主对象的关联对象和关联集合不是立即加载的,而且延迟加载,需要用到它的时候才会被加载到缓存中。而对象本身,load()方法是延迟加载,get()方法则是立即加载到缓存中。对象属性是默认立即加载的。如果我们要改变他的加载方式,则可以通过修改相关的配置文件来完成。