2016/4/22 23:19:44

Hibernate学习笔记(二)

1.1 Hibernate的持久化类状态

1.1.1 Hibernate的持久化类状态

持久化:就是一个实体类与数据库表建立了映射。

  • 瞬时态 transisent:(临时态)
  • 持久态 persistent
  • 脱管态 detached:(离线态)

1.1.2 三种持久化对象的状态

Transient瞬时态:持久化对象没有唯一标识OID.没有纳入Session的管理。

Persistent持久态:持久化对象有唯一标识OID.已经纳入到Session的管理。(结论:持久化持久态对象有自动更新数据库的能力。)

Detached脱管态:持久化对象有唯一标识OID,没有纳入到Session管理。

1.1.3 区分三种持久化对象的状态

	@Test
// 区分持久化对象的三种状态:
public void demo1(){
// 1.创建Session
Session session = HibernateUtils.openSession();
// 2.开启事务
Transaction tx = session.beginTransaction(); // 向数据库中保存一本图书:
Book book = new Book(); // 瞬时态:没有唯一标识OID,没有与session关联.
book.setName("Hiernate开发");
book.setAuthor("孙XX");
book.setPrice(65d); session.save(book); // 持久态:有唯一标识OID,与session关联. // 3.事务提交
tx.commit();
// 4.释放资源
session.close(); book.setName("Struts2开发"); // 脱管态:有唯一的标识,没有与session关联.
}

1.1.4 三种状态对象转换

瞬时态:

Book book = new Book();	//获得
瞬时--->持久:
* save(book);
* save()/saveOrUpdate();
瞬时--->脱管:
* book.setId(1);

持久态:

Book book = (Book)session.get(Book.class, 1); //获得
* get()/load()/find()/iterate(); 持久--->瞬时:
delete(book);
* 特殊状态:删除态.(被删除的对象,不建议去使用.) 持久--->脱管:
session.close();
* close()/clear()/evict();

脱管态:

Book book = new Book();
book.setId(1); //获得 脱管--->持久:
* session.update();
* update()/saveOrUpdate()/lock() 脱管--->瞬时:
* book.setId(null);

1.1.4 持久态对象有自动更新数据库的能力

自动更新数据库的能力依赖了Hibernate的一级缓存.

	@Test
// 测试持久态的对象自动更新数据库
public void demo2(){
// 1.创建Session
Session session = HibernateUtils.openSession();
// 2.开启事务
Transaction tx = session.beginTransaction(); // 获得一个持久态的对象.
Book book = (Book) session.get(Book.class, 1);
book.setName("Struts2开发"); // session.update(book); // 3.提交事务
tx.commit();
// 4.关闭资源
session.close();
}

1.2 Hibernate的一级缓存

1.2.1 Hibernate的一级缓存

缓存:缓存将数据库/硬盘上文件中数据,放入到缓存中(就是内存中一块空间).当再次使用的使用,可以直接从内存中获取。

缓存的好处:提升程序运行的效率.缓存技术是Hibernate的一个优化的手段。

Hibernate分成两个基本的缓存:

  • 一级缓存:Session级别的缓存.一级缓存与session的生命周期一致.自带的.不可卸载。
  • 二级缓存:SessionFactory级别的缓存.不是自带的。

在 Session 接口的实现中包含一系列的 Java 集合, 这些 Java 集合构成了 Session 缓存. 只要 Session 实例没有结束生命周期, 存放在它缓存中的对象也不会结束生命周期。

1.2.2 证明Hibernate一级缓存的存在

	@Test
// 证明一级缓存的存在
public void demo3(){
// 1.创建Session
Session session = HibernateUtils.openSession();
// 2.开启事务
Transaction tx = session.beginTransaction(); // save方法可以向一级缓存中存放数据的.
/*Book book = new Book();
book.setName("JQuery开发");
book.setAuthor("张XX");
book.setPrice(45d); Integer id = (Integer) session.save(book); Book book2 = (Book) session.get(Book.class, id); System.out.println(book2);*/ // 分别用get执行两次查询.
Book book1 = (Book) session.get(Book.class, 1);// 马上发生SQL去查询
System.out.println(book1); Book book2 = (Book) session.get(Book.class, 1);// 不发生SQL,因为使用一级缓存的数据
System.out.println(book2); // 3.提交事务
tx.commit();
// 4.关闭资源
session.close();
}

1.2.3 理解一级缓存中快照区

向一级缓存存入数据的时候,放入一级缓存区和一级缓存快照区,当更新了一级缓存区的数据的时候,事务一旦提交,比对一级缓存区和一级缓存快照区,如果数据一致,不更新,如果数据不一致,则更新。

@Test
// 深入理解一级缓存结构:快照区:
public void demo4(){
// 1.创建Session
Session session = HibernateUtils.openSession();
// 2.开启事务
Transaction tx = session.beginTransaction(); // 获得一个持久态的对象.
Book book = (Book) session.get(Book.class, 1);
book.setName("Spring3开发"); // 3.提交事务
tx.commit();
// 4.关闭资源
session.close();
}

1.2.4 Hibernate管理一级缓存

一级缓存是与session的生命周期相关的,session生命周期结束,一级缓存就销毁了。

  • clear()/evict()/flush()/refresh()管理一级缓存.

    • clear() :清空一级缓存中所有的对象.
    • evict(Object obj) :清空一级缓存中某个对象.
    • flush() :刷出缓存,发出SQL语句
    • refresh(Object obj):将快照区的数据重新覆盖了一级缓存的数据.

1.2.5 Hibernate一级缓存的刷出时机

FlushMode:

* 常量:
* ALWAYS :每次查询的时候都会刷出.手动调用flush.事务提交的时候.
* AUTO :默认值.有些查询会刷出.手动调用flush.事务提交的时候.
* COMMIT :在事务提交的时候,手动调用flush的时候.
* MANUAL :只有在手动调用flush才会刷出.

严格程度:MANUAL > COMMIT > AUTO > ALWAYS

1.3 操作持久化对象的方法

save():保存一条记录:将瞬时态对象转换成持久态对象。

update():更新一条记录:将脱管态对象转换成持久态对象。在<class>标签上设置select-before-update="true",在更新之前先去查询。

savvOrUpdate():根据对象状态的不同执行不同的save()或update()方法。

  • 如果一个对象是瞬时态对象,执行save()操作。
  • 如果一个对象是脱管态对象,执行update()操作。
  • 如果设置的id在数据库中不存在,就会报错,可以在<id>上设置一个unsaved-value="不存在的Id",执行save()操作,在数据库里就会保存到最后一个id。

delete():将持久态对象转成瞬时态。

get()/load():获得一个持久态对象。

1.4 Hibernate关联关系的映射

1.4.1 实体之间的关系

实体之间有三种关系:

  • 一对多(用得最多):

    • 实例:一个用户,生成多个订单,每个订单只属于一个用户。
    • 建表原则:在多的一方创建一个字段,作为外键,指向一的一方的主键。
  • 多对多

    • 实例:一个学生可以选择多门课程,一门课程可以被多个学生选择。
    • 建表原则:创建第三张表,中间表至少有两个字段,分别作为外键指向多对多双方的主键。
  • 一对一(特殊,用得最少):

    • 实例:一个公司只能有一个注册地址,一个注册地址只能被一个公司使用(否则将两个表建到一个表)
    • 建表原则:
      1. 唯一外键:假设一方是多的关系,需要在多的一方创建一个字段,作为外键,指向一的一方的主键,并且在外键添加unique。
      2. 主键对应:一对一的双方,通过主键进行关联。

1.4.2 Hibernate中的一对多配置

第一步:
* 创建两个实体:
* 客户实体:
public class Customer {
private Integer cid;
private String cname;
// 一个客户有多个订单.
private Set<Order> orders = new HashSet<Order>();
public Integer getCid() {
return cid;
}
public void setCid(Integer cid) {
this.cid = cid;
}
public String getCname() {
return cname;
}
public void setCname(String cname) {
this.cname = cname;
}
public Set<Order> getOrders() {
return orders;
}
public void setOrders(Set<Order> orders) {
this.orders = orders;
} } 订单实体:
public class Order {
private Integer oid;
private String addr;
// 订单属于某一个客户.放置一个客户的对象.
private Customer customer;
public Integer getOid() {
return oid;
}
public void setOid(Integer oid) {
this.oid = oid;
}
public String getAddr() {
return addr;
}
public void setAddr(String addr) {
this.addr = addr;
}
public Customer getCustomer() {
return customer;
}
public void setCustomer(Customer customer) {
this.customer = customer;
} } 第二步:建立映射: Customer.hbm.xml
<hibernate-mapping>
<class name="cn.itcast.hibernate3.demo2.Customer" table="customer">
<!-- 配置唯一标识 -->
<id name="cid" column="cid">
<generator class="native"/>
</id>
<!-- 配置普通属性 -->
<property name="cname" column="cname" length="20"/> <!-- 建立映射 -->
<!-- 配置一个集合 <set>的name Customer对象中的关联对象的属性名称. -->
<set name="orders">
<!-- <key>标签中column:用来描述一对多多的一方的外键的名称. -->
<key column="cno"></key>
<!-- 配置一个<one-to-many>标签中class属性:订单的类的全路径 -->
<one-to-many class="cn.itcast.hibernate3.demo2.Order"/>
</set>
</class>
</hibernate-mapping> Order.hbm.xml
<hibernate-mapping>
<class name="cn.itcast.hibernate3.demo2.Order" table="orders">
<!-- 配置唯一标识 -->
<id name="oid" column="oid">
<generator class="native"/>
</id>
<!-- 配置普通属性 -->
<property name="addr" column="addr" length="50"/>
<!-- 配置映射 -->
<!--
<many-to-one>标签
name :关联对象的属性的名称.
column :表中的外键名称.
class :关联对象类的全路径
-->
<many-to-one name="customer" column="cno" class="cn.itcast.hibernate3.demo2.Customer"/>
</class>
</hibernate-mapping> 第三步:将映射放到核心配置文件中.

1.4.3 Hibernate中级联保存的效果

级联:操作当前对象的时候,关联的对象如何处理.

cascade=”save-update”

级联方向性:

  • 保存客户的时候,选择级联订单.
  • 保存订单的时候,选择级联客户.

1.4.4 Hibernate中级联删除的效果

	cascade=”delete”

1.4.5 Hibernate中的级联取值

none				:不使用级联
dave-update :保存或更新的时候级联
delete :删除的时候级联
all :除了孤儿删除以外的所有级联.
delete-orphan :孤儿删除(孤子删除).
* 仅限于一对多.只有一对多时候,才有父子存在.认为一的一方是父亲,多的一方是子方.
* 当一个客户与某个订单解除了关系.将外键置为null.订单没有了所属客户,相当于一个孩子没有了父亲.将这种记录就删除了.
all-delete-orphan :包含了孤儿删除的所有的级联.

1.4.6 双向维护产生多余的SQL

配置inverse=”true”:在那一端配置.那么那一端放弃了外键的维护权.

  • 一般情况下,一的一方去放弃.
  • cascade:操作关联对象.

  • inverse:控制外键的维护.

1.4.7 Hibernate的多对多的配置

第一步:创建实体类:
学生的实体:
public class Student {
private Integer sid;
private String sname;
// 一个学生选择多门课程:
private Set<Course> courses = new HashSet<Course>();
public Integer getSid() {
return sid;
}
public void setSid(Integer sid) {
this.sid = sid;
}
public String getSname() {
return sname;
}
public void setSname(String sname) {
this.sname = sname;
}
public Set<Course> getCourses() {
return courses;
}
public void setCourses(Set<Course> courses) {
this.courses = courses;
} }
课程的实体:
public class Course {
private Integer cid;
private String cname;
// 一个课程被多个学生选择:
private Set<Student> students = new HashSet<Student>();
public Integer getCid() {
return cid;
}
public void setCid(Integer cid) {
this.cid = cid;
}
public String getCname() {
return cname;
}
public void setCname(String cname) {
this.cname = cname;
}
public Set<Student> getStudents() {
return students;
}
public void setStudents(Set<Student> students) {
this.students = students;
} } 第二步建立映射:
Student.hbm.xml
<hibernate-mapping>
<class name="cn.itcast.hibernate3.demo3.Student" table="student">
<!-- 配置唯一标识 -->
<id name="sid" column="sid">
<generator class="native"/>
</id>
<!-- 配置普通属性 -->
<property name="sname" column="sname" length="20"/> <!-- 配置关联映射 -->
<!-- <set>标签 name:对应学生中的课程集合的名称 table:中间表名称. -->
<set name="courses" table="stu_cour">
<!-- <key>中column写 当前类在中间表的外键.-->
<key column="sno"></key>
<!-- <many-to-many>中class:另一方类的全路径. column:另一方在中间表中外键名称-->
<many-to-many class="cn.itcast.hibernate3.demo3.Course" column="cno"/>
</set>
</class>
</hibernate-mapping> Course.hbm.xml
<hibernate-mapping>
<class name="cn.itcast.hibernate3.demo3.Course" table="course">
<!-- 配置唯一标识 -->
<id name="cid" column="cid">
<generator class="native"/>
</id>
<!-- 配置普通属性 -->
<property name="cname" column="cname" length="20"/>
<!-- 配置与学生关联映射 -->
<!-- <set>中name:对应当前类中的学生的集合的名称 table:中间表的名称-->
<set name="students" table="stu_cour">
<!-- <key>中column:当前类在中间表中外键 -->
<key column="cno"></key>
<!-- <many-to-many>中class:另一方的类全路径. column:另一方在中间表中外键名称 -->
<many-to-many class="cn.itcast.hibernate3.demo3.Student" column="sno"/>
</set>
</class>
</hibernate-mapping> 第三步:将映射文件加入到核心配置文件中:

Hibernate学习笔记(二)的更多相关文章

  1. Hibernate学习笔记二:Hibernate缓存策略详解

    一:为什么使用Hibernate缓存: Hibernate是一个持久层框架,经常访问物理数据库. 为了降低应用程序访问物理数据库的频次,从而提高应用程序的性能. 缓存内的数据是对物理数据源的复制,应用 ...

  2. Hibernate学习笔记二

    Hibernate持久化类的编写规则 Hibernate是持久层的ORM映射框架,专注于数据的持久化工作.所谓持久化,就是将内存中的数据永久存储到关系型数据库中. 持久化类 一个java类与数据库表建 ...

  3. Hibernate学习笔记二:常用映射配置

    转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/6760895.html 一:单向一对一 常用唯一外键的方法来配置单向一对一关系. 1:实体关系 类A中有类B对象 ...

  4. JDBC学习笔记二

    JDBC学习笔记二 4.execute()方法执行SQL语句 execute几乎可以执行任何SQL语句,当execute执行过SQL语句之后会返回一个布尔类型的值,代表是否返回了ResultSet对象 ...

  5. Hibernate学习笔记(一)

    2016/4/18 19:58:58 Hibernate学习笔记(一) 1.Hibernate框架的概述: 就是一个持久层的ORM框架. ORM:对象关系映射.将Java中实体对象与关系型数据库中表建 ...

  6. Hibernate 学习笔记一

    Hibernate 学习笔记一 今天学习了hibernate的一点入门知识,主要是配置domain对象和表的关系映射,hibernate的一些常用的配置,以及对应的一个向数据库插入数据的小例子.期间碰 ...

  7. WPF的Binding学习笔记(二)

    原文: http://www.cnblogs.com/pasoraku/archive/2012/10/25/2738428.htmlWPF的Binding学习笔记(二) 上次学了点点Binding的 ...

  8. AJax 学习笔记二(onreadystatechange的作用)

    AJax 学习笔记二(onreadystatechange的作用) 当发送一个请求后,客户端无法确定什么时候会完成这个请求,所以需要用事件机制来捕获请求的状态XMLHttpRequest对象提供了on ...

  9. [Firefly引擎][学习笔记二][已完结]卡牌游戏开发模型的设计

    源地址:http://bbs.9miao.com/thread-44603-1-1.html 在此补充一下Socket的验证机制:socket登陆验证.会采用session会话超时的机制做心跳接口验证 ...

随机推荐

  1. Git tag push 到远端仓库

    很早之前,我们就提到过用Git tag来给工程打上标签,但是这个命令只是在本地仓库打标签而已, 为了能把标签同步到远程服务器,我们可以这样做: 默认情况下,git push并不会把tag标签传送到远端 ...

  2. ubuntu安装node.js+express+mongodb

    输入以下命令安装: sudo apt-get install nodejs 安装完成后,终端输入nodejs,就能进入node命令啦: 但是正常下应该是输入node进入命令而不是nodejs: 在Ub ...

  3. Discovering-论文

    Discovering Spatio-Temporal Causal Interactions in Traffic Data Streams data:real taxi trajectories ...

  4. html特殊字符

    平时写代码很少用到HTML的特殊字符,最常用的可能是 了,但有时在移动端为了节省时间,可能会用这些字符实现某种特殊效果,现整理如下: 使用方法: 这些字符属于unicode字符集,所以,你的文档需要声 ...

  5. cygwin 安装apt-cyg命令

    googlecode关闭了.没法用wget安装apt-cyg 找了半天只有github里有个方法可行: apt-cyg is a simple script. To install: lynx -so ...

  6. sed tr 去除PATH中的重复项

    最近发现由于自己不良的安装软件的习惯,shell的PATH路径包含了很多冗余的项.这里使用shell命令去除PATH的冗余项. export PATH=$(echo $PATH | sed 's/:/ ...

  7. 初学软件测试之——如何使用Junit4

    前几天刚刚接触软件测试,这篇文章主要是介绍使用eclipse的插件——Junit4进行单元测试.下面先介绍一下单元测试的定义:单元测试(unit testing),是指对软件中的最小可测试单元进行检查 ...

  8. Android: 实例解析Activity生命周期

    Activity生命周期图: 下面以一个实例来解析,实例APP运行,进入MainActivity, 点击Send Button以后进入MessgaeActivity 当第一次运行App,进入MainA ...

  9. linux 下的信号量参数

    linux 下的信号量参数 转载自:http://blog.itpub.net/26110315/viewspace-718306/ 信号量是一种锁机制用于协调进程之间互斥的访问临界资源.以确保某种共 ...

  10. YbSoftwareFactory 代码生成插件【十三】:Web API 的安全性

    ASP.NET Web API 可非常方便地创建基于 HTTP 的 Services,这些服务可以非常方便地被几乎任何形式的平台和客户端(如浏览器.Windows客户端.Android设备.IOS等) ...