Hibernate_day02总结

Hibernate_day02总结

今日内容

l Hibernate持久化对象的状态

l Hibernate的一级缓存

l Hibernate操作持久化对象的方法

l Hibernate 关联关系映射

1.1 上次课内容回顾:

Hibernate框架的概述.

* 什么是Hibernate

* 持久层的ORM框架.

* ORM:对象关系映射.

* 常见的持久层框架

* JPA

* Hibernate

* Mybatis

* JdbcTemplate

* Hibernate流行版本:

* 3.x和4.x

Hibernate的快速入门:

* 下载Hibernate开发环境.

* 了解目录结构.

* 创建项目,引入jar包.

* 创建表和实体

* 创建映射文件.

* 创建核心配置文件.

* 编写测试类.

Hibernate的CRUD的操作:

* save()

* update()

* get/load()

* delete

* createQuery();

* createCriteria()

Hibernate的常见配置:

* 映射文件的配置:

* <class> :类与表的映射.

* name :类的路径

* table :表名

* <id>

* name :类中属性

* column :表中字段

* <property>

* name :类中属性

* column :表中字段

* 核心配置文件的配置:

* hibernate.properties

手动加载映射文件

Configuration cfg = new Configuration();

* hibernate.cfg.xml

Configuration cfg = new Configuration().configure();

Hibernate的核心API:

* Configuration

* addResource();

* addClass();

* SessionFactory:

* 抽取工具类.

* Session:

* get/load的区别?

* get立即发送.load延迟加载.

* get返回的真实对象.load返回代理对象.

* get返回null.load返回ObjectNotFoundException.

* Transaction:

* commit();

* rollback();

* wasCommitted();

* Query:

* Criteria:

Hibernate的持久化类的编写:

* 什么是持久化类:

* 持久化类:Java类与数据库的表建立了映射关系.

* 持久化类编写规则:

* 无参数的构造方法:

* 属性get和set

* 属性尽量使用包装类:

* 提供唯一标识OID.

* 类不要使用final修饰.

* 自然主键和代理主键.

* Hibernate中的主键生成策略:

* increment:

* identity

* sequence

* native

* uuid

* assigned

* foreign

1.2 Hibernate持久化对象的状态

1.2.1 持久化类的三种状态:

持久化类:就是一个Java类与表建立了映射关系.这种Java类就称为是持久化类.

Hibernate为了更好的管理持久化类,将持久化类分成了三种状态.

瞬时态:没有持久化标识OID,对象没有被session管理.

持久态:有持久化标识OID.对象也被session管理.(重点)

脱管态:有持久化标识OID.但对象没有被session管理.

***** 持久化类的持久态的对象可以自动更新数据库.

@Test
/**
* 区分持久化类的三种状态
*/
publicvoid demo1(){
Session session = HibernateUtils.openSession();
Transaction tx = session.beginTransaction();
// 保存一条记录:
User user = new User();// 瞬时态: 没有持久化标识OID,没有被session管理.
user.setUsername("aaa");
user.setPassword("123");
session.save(user); // 持久态: 有持久化标识OID,被session管理.
tx.commit();
session.close();
System.out.println(user.getUsername());// 脱管态: 有持久化标识OID.没有被session管理.
}
@Test
/**
* 证明持久化类的持久态对象可以自动更新数据库
*/
publicvoiddemo2(){
Session session = HibernateUtils.openSession();
Transaction tx = session.beginTransaction();
// 查询一条记录:
User user = (User) session.get(User.class, 1);// 持久态:有标识OID,被session管理.
user.setUsername("ccc");
// session.update(user);
tx.commit();
session.close();
}

1.2.2 Hibernate持久化对象的状态转换:

瞬时态:

* 获得:

* new 对象.

* 转换:

* 瞬时à持久:

* save()/saveOrUpdate();

* 瞬时à脱管:

* User user = new User();

* user.setId(1);

持久态:

* 获得:

* get/load/iterate/find

* 持久à脱管:

* session.close()/session.clear()/session.evict();

* 持久à瞬时:

* delete()

脱管态:

* 获得:

* User user = new User();

* user.setId(1);

* 转换:

* 脱管à持久:

* update/saveOrUpdate/lock

* 脱管à瞬时:

* user.setId(null);

1.3 Hibernate的一级缓存:

1.3.1 什么是缓存:

缓存是计算机领域经常会使用的一个概念.是介于数据源(数据库/文件)与程序之间的.就是内存中的一块空间.查询数据的时候将查询到数据放入到缓存中.当再次获得这个数据的时候,那么直接从缓存中获取.提升性能.

1.3.2 Hibernate中的缓存

Hibernate中提供了两个级别的缓存:

一级缓存:称为session级别缓存.一级缓存的生命周期与session一致.自带的不可卸载的.

二级缓存:称为sessionFactory基本的缓存.可以在多个session中共享数据.默认不开启二级缓存.需要手动配置的.

1.3.3 Hibernate的一级缓存:

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

当session的save()方法持久化一个对象时,该对象被载入缓存,以后即使程序中不再引用该对象,只要缓存不清空,该对象仍然处于生命周期中。当试图get()、 load()对象时,会判断缓存中是否存在该对象,有则返回,此时不查询数据库。没有再查询数据库

@Test
/**
* 证明Hibernate的一级缓存的存在
*/
publicvoid demo1(){
Session session = HibernateUtils.openSession();
Transaction tx = session.beginTransaction();
/**
* 先save再get
*/
/*User user = new User();
user.setUsername("bbb");
user.setPassword("123");
Serializable id = session.save(user); // 持久态
User user2 = (User) session.get(User.class, id); // 不发送SQL语句
System.out.println(user2);*/
/**
* 先后执行两次get方法
*/
User user1 = (User) session.get(User.class, 1); // 发送一条SQL语句
User user2 = (User) session.get(User.class, 1); // 不发送SQL语句
System.out.println(user1 );
System.out.println(user2 );
tx.commit();
session.close();
}

1.3.4 Hibernate的内部结构(持久态对象能自动更新数据库原理)

@Test
/**
* 持久态对象能够自动更新数据库(依赖了一级缓存的快照区)
*/
publicvoid demo2(){
Session session = HibernateUtils.openSession();
Transaction tx = session.beginTransaction();
User user = (User) session.get(User.class, 1); // 持久态
user.setUsername("fff");
tx.commit();
session.close();
}

1.3.5 Hibernate一级缓存的常用操作

flush:刷出缓存(发送更新语句时机)

@Test
/**
* 一级缓存的管理的方法:flush.刷出缓存
*/
publicvoid demo3(){
Session session = HibernateUtils.openSession();
Transaction tx = session.beginTransaction();
User user = (User) session.get(User.class, 1); // 持久态
user.setUsername("eee");
session.flush(); // 刷出缓存
tx.commit();
session.close();
}

clear:清空所有一级缓存中的对象.

@Test
/**
* 一级缓存的管理的方法:clear.清空一级缓存
*/
publicvoid demo4(){
Session session = HibernateUtils.openSession();
Transaction tx = session.beginTransaction();
User user1 = (User) session.get(User.class, 1); // 持久态 发送SQL语句
session.clear();
User user2 = (User) session.get(User.class, 1); // 持久态 发送SQL语句
System.out.println(user1);
System.out.println(user2);
tx.commit();
session.close();
}

evict:清空一级缓存中的某个对象.

@Test
/**
* 一级缓存的管理的方法:evict.清空一级缓存中的某个对象
*/
publicvoiddemo5(){
Session session = HibernateUtils.openSession();
Transaction tx = session.beginTransaction();
User user1 = (User) session.get(User.class, 1); // 持久态 发送SQL语句
session.evict(user1);
User user2 = (User) session.get(User.class, 1); // 持久态 发送SQL语句
System.out.println(user1);
System.out.println(user2);
tx.commit();
session.close();
}

refresh:将快照区数据重新覆盖了缓存区数据.

@Test
/**
* 一级缓存的管理的方法:refresh.将数据库中数据覆盖掉一级缓存的数据
*/
publicvoiddemo6(){
Session session = HibernateUtils.openSession();
Transaction tx = session.beginTransaction();
User user1 = (User) session.get(User.class, 1); // 持久态 发送SQL语句
user1.setUsername("mmm");
session.refresh(user1);
tx.commit();
session.close();
}

1.3.6 Hibernate的一级缓存的刷出时机(了解)

ALWAYS :任何查询操作,事务提交的时候,手动调用flush时候都会刷出.

AUTO :有些查询操作,事务提交的时候,手动调用flush的时候会刷出.(默认)

COMMIT :事务提交或者手动调用flush的时候.

MANUAL :必须手动调用flush刷出

1.4 操作持久化对象的方法

1.4.1 保存的方法:save

save方法:将瞬时态转出持久态对象,而且向一级缓存中存放数据.

1.4.2 查询方法:get/load

get/load方法:可以直接获得持久态对象,而且都可以向一级缓存中存放数据.

1.4.3 修改方法:update

update:可以将脱管态对象转成持久态对象.

在<class>上配置一个select-before-update:在更新之前查询.

1.4.4 保存或更新:saveOrUpdate

saveOrUpate:如果对象是瞬时的采用save方法.如果对象是脱管的执行update.

@Test
/**
* saveOrUpdate方法:
*/
publicvoid demo2(){
Session session = HibernateUtils.openSession();
Transaction tx = session.beginTransaction();
/*User user = new User();// 瞬时
user.setUsername("yyy");
user.setPassword("yyy");
session.saveOrUpdate(user);// 执行save
*/
User user = new User();// 瞬时
user.setId(4); // 脱管
user.setUsername("xxx");
user.setPassword("yyy");
session.saveOrUpdate(user); // 执行update
tx.commit();
session.close();
}

***** merge方法和saveOrUpdate大致类似.如果对象是瞬时执行save.如果是脱管执行update.将内存中出现的OID相同的对象进行合并.

1.4.5 删除方法:

将持久态对象转成瞬时.

1.5 Hibernate的关联关系的映射.(*****)

1.5.1 表之间的关系:

一对多 :

* 建表原则:在多的一方创建一个字段,作为外键指向一的一方的主键.

多对多 :

* 建表原则:创建一个中间表,中间表至少两个字段.两个字段分别作为外键指向多对多双方的主键.

一对一

* 建表原则:

* 唯一外键对应:假设一对一是一个一对多的关系.在多的一方创建外键指向一的一方的主键.将外键设置为unique.

* 主键对应:一个表的主键从另一个表的主键获得.

1.5.2 Hibernate完成一对多的关联关系的配置(客户和订单的案例)

步骤一:创建客户和订单的实体:

步骤二:创建客户和订单的映射文件:

Order.hbm.xml
<hibernate-mapping>
<class name="cn.itcast.hibernate.demo2.Order"table="orders">
<id name="oid"column="oid">
<generator class="native"/>
</id>
<property name="address"column="address"length="100"/>
<!--
在多的一方添加一个标签 many-to-one
name :多的一方存放的一的一方的对象的名称.
class :customer对象的全路径
column :外键名称
-->
<many-to-one name="customer" class="cn.itcast.hibernate.demo2.Customer" column="cno"/>
</class>
</hibernate-mapping>
Customer.hbm.xml
<hibernate-mapping>
<class name="cn.itcast.hibernate.demo2.Customer"table="customer">
<id name="cid"column="cid">
<generator class="native"/>
</id>
<property name="cname"column="cname"length="20"/>
<property name="age"column="age"/>
<!-- 一个客户中有多个订单的.配置的是多个订单的集合 -->
<set name="orders">
<!-- key:外键的名称 -->
<key column="cno"/>
<!-- 配置one-to-many -->
<one-to-many class="cn.itcast.hibernate.demo2.Order"/>
</set>
</class>
</hibernate-mapping>

步骤三:保存数据:

@Test
/**
* 插入两个客户和3个订单
*/
publicvoiddemo1(){
Session session = HibernateUtils.openSession();
Transaction tx = session.beginTransaction();
Customer customer1 = new Customer();
customer1.setCname("老马");
customer1.setAge(38);
Customer customer2 = new Customer();
customer2.setCname("凤姐");
customer2.setAge(38);
Order order1 = new Order();
order1.setAddress("北京市昌平区中腾建华大厦");
Order order2 = new Order();
order2.setAddress("北京市昌平区金燕龙办公楼");
Order order3 = new Order();
order3.setAddress("北京市昌平区四拨子");
// 建立客户和订单的关系:
customer1.getOrders().add(order1);
customer1.getOrders().add(order2);
customer2.getOrders().add(order3);
order1.setCustomer(customer1);
order2.setCustomer(customer1);
order3.setCustomer(customer2);
session.save(customer1);
session.save(customer2);
session.save(order1);
session.save(order2);
session.save(order3);
tx.commit();
session.close();
}

1.5.3 Hibernate中的一对多级联操作:

级联保存:

保存某一个对象的同时,级联关联对象.

级联是有方向性.

* 保存客户的时候,级联订单.

@Test
/**
* 级联保存:
* 保存客户,级联订单
* 在Customer.hbm.xml中完成一个配置:<set>上配置cascade="save-update"
*/
publicvoid demo3(){
Session session = HibernateUtils.openSession();
Transaction tx = session.beginTransaction();
Customer customer1 = new Customer(); // 瞬时
customer1.setCname("老马");
customer1.setAge(38);
Order order1 = new Order(); // 瞬时
order1.setAddress("北京市昌平区中腾建华大厦");
// 建立客户和订单的关系:
customer1.getOrders().add(order1);
order1.setCustomer(customer1);
session.save(customer1); // 持久态.
tx.commit();
session.close();
}
* 保存订单的时候,级联客户.
@Test
/**
* 级联保存:
* 保存订单,级联客户
* 在订单Order.hbm.xml中配置<many-to-one>配置cascade="save-update"
*/
publicvoid demo4(){
Session session = HibernateUtils.openSession();
Transaction tx = session.beginTransaction();
Customer customer1 = new Customer(); // 瞬时
customer1.setCname("老马");
customer1.setAge(38);
Order order1 = new Order(); // 瞬时
order1.setAddress("北京市昌平区中腾建华大厦");
// 建立客户和订单的关系:
customer1.getOrders().add(order1);
order1.setCustomer(customer1);
session.save(order1); // 持久态.
tx.commit();
session.close();
}

测试对象的导航:

@Test
/**
* 测试对象的导航.
* 一对多的双方都配置了cascade="save-update"
*/
publicvoid demo5(){
Session session = HibernateUtils.openSession();
Transaction tx = session.beginTransaction();
Customer customer1 = new Customer(); // 瞬时
customer1.setCname("凤姐");
customer1.setAge(38);
Order order1 = new Order(); // 瞬时
order1.setAddress("北京市昌平区中腾建华大厦");
Order order2 = new Order(); // 瞬时
order2.setAddress("北京市昌平区金燕龙");
Order order3 = new Order(); // 瞬时
order3.setAddress("北京市昌平区四拨子");
// 建立客户和订单的关系:
order1.setCustomer(customer1);
customer1.getOrders().add(order2);
customer1.getOrders().add(order3);
// session.save(order1); // 发送几条insert语句. 4条
// session.save(customer1); // 发送几条insert语句. 3条.
session.save(order2); // 发送几条insert语句. 1条
tx.commit();
session.close();
}

级联删除

删除某个对象的时候,将关联的对象一并删除.

级联删除也是有方向性的.

* 删除客户的时候,级联删除订单.

@Test
/**
* 级联删除:
* * 删除客户,级联订单
* * 在Customer.hbm.xml中配置<set>上cascade="delete"
*/
publicvoid demo7(){
Session session = HibernateUtils.openSession();
Transaction tx = session.beginTransaction();
/**
* 级联删除,一定要先查询再删除
*/
Customer customer = (Customer) session.get(Customer.class, 1);
session.delete(customer);
tx.commit();
session.close();
}
* 删除订单的时候,级联删除客户.
@Test
/**
* 级联删除:
* * 删除订单,级联客户
* * 在Order.hbm.xml中配置<many-to-one>上cascade="delete"
*/
publicvoid demo8(){
Session session = HibernateUtils.openSession();
Transaction tx = session.beginTransaction();
/**
* 级联删除,一定要先查询再删除
*/
Order order = (Order) session.get(Order.class, 3);
session.delete(order);
tx.commit();
session.close();
}

级联的取值:

* none :没有级联

* save-update :级联保存或更新.

* delete :级联删除

* all :所有但是除了delete-orphan

* delete-orphan :孤儿删除.(孤子删除)

* all-delete-orphan :所有的包含的孤儿删除.

孤儿删除:只能在一对多的情况下使用.认为一对多的一的一方是父方.多的一方子方.

* 孤儿删除指的是删除子的一方没有外键值得那些数据.

孤儿删除:

@Test
/**
* 孤儿删除
*/
publicvoid demo9(){
Session session = HibernateUtils.openSession();
Transaction tx = session.beginTransaction();
Customer customer = (Customer) session.get(Customer.class, 3);
Order order = (Order) session.get(Order.class, 4);
customer.getOrders().remove(order);
tx.commit();
session.close();
}

1.5.4 Hibernate一对多的inverse的配置:

如果没有配置inverse出现哪些问题?

* 正常的情况下一对多的双方都有能力去维护外键.造成SQL冗余.(发送多余的SQL去维护外键).配置inverse的一方就放弃外键的维护权.

双向维护产生多余SQL

@Test
/**
* 双向维护产生多余的SQL:
* 在一的一方配置外键维护权:inverse="true"
*/
publicvoiddemo10(){
Session session = HibernateUtils.openSession();
Transaction tx = session.beginTransaction();
Customer customer = (Customer) session.get(Customer.class, 2);
Order order = (Order) session.get(Order.class, 2);
customer.getOrders().add(order);
order.setCustomer(customer);
tx.commit();
session.close();
}

配置cascade和inverse的效果:

@Test
/**
* 测试cascade和inverse.
* 在Customer.hbm.xml中配置cascade="save-update" inverse="true"
*/
publicvoid demo11(){
Session session = HibernateUtils.openSession();
Transaction tx = session.beginTransaction();
Customer customer = new Customer();
customer.setCname("马如花");
customer.setAge(40);
Order order = new Order();
order.setAddress("北京市昌平区朱辛庄");
customer.getOrders().add(order);
session.save(customer);
// 客户 和 订单是否能被保存到数据库,最终效果是如何的?
// cascade:关联对象是否一并保存到数据库.
// inverse:外键是否有值.
tx.commit();
session.close();
}

1.5.5 Hibernate完成多对多的配置:

步骤一:创建实体

步骤二:创建映射文件:

Student.hbm.xml
<hibernate-mapping>
<class name="cn.itcast.hibernate.demo3.Student"table="student">
<id name="sid"column="sid">
<generator class="native"/>
</id>
<property name="sname"column="sname"length="20"/>
<!-- 关联关系的配置 -->
<set name="courses" table="stu_cour">
<!-- key中的column代表的是当前类在中间表的外键的名称 -->
<key column="sno"/>
<many-to-many class="cn.itcast.hibernate.demo3.Course" column="cno"/>
</set>
</class>
</hibernate-mapping>
Course.hbm.xml
<hibernate-mapping>
<class name="cn.itcast.hibernate.demo3.Course"table="course">
<id name="cid"column="cid">
<generator class="native"/>
</id>
<property name="cname"column="cname"length="20"/>
<!-- 关联关系的配置 -->
<set name="students" table="stu_cour">
<key column="cno"/>
<many-to-many class="cn.itcast.hibernate.demo3.Student" column="sno"/>
</set>
</class>
</hibernate-mapping>

1.5.6 基本的保存:

1.5.7 级联操作:

级联保存

@Test
/**
* 插入数据:级联保存:
* * 保存学生级联课程
*/
publicvoid demo2(){
Session session = HibernateUtils.openSession();
Transaction tx = session.beginTransaction();
// 创建两个学生
Student student1 = new Student();
student1.setSname("小马");
// 创建三门课程
Course course1 = new Course();
course1.setCname("C++");
// 设置关系:(双向维护:多对多双向维护,出错. 必须有一方放弃外键维护权.)
student1.getCourses().add(course1);
course1.getStudents().add(student1);
session.save(student1);
tx.commit();
session.close();
}
@Test
/**
* 插入数据:级联保存:
* * 保存课程级联学生
*/
publicvoiddemo3(){
Session session = HibernateUtils.openSession();
Transaction tx = session.beginTransaction();
// 创建两个学生
Student student1 = new Student();
student1.setSname("小马");
// 创建三门课程
Course course1 = new Course();
course1.setCname("C++");
student1.getCourses().add(course1);
course1.getStudents().add(student1);
session.save(course1);
tx.commit();
session.close();
}

级联删除:

@Test
/**
* 级联删除:
* * 删除学生级联课程.
*/
publicvoid demo4(){
Session session = HibernateUtils.openSession();
Transaction tx = session.beginTransaction();
Student student = (Student) session.get(Student.class, 1);
session.delete(student);
tx.commit();
session.close();
}
@Test
/**
* 级联删除:
* * 删除课程级联学生.
*/
publicvoid demo5(){
Session session = HibernateUtils.openSession();
Transaction tx = session.beginTransaction();
Course course = (Course) session.get(Course.class, 2);
session.delete(course);
tx.commit();
session.close();
}

1.5.8 学生选课的操作:

@Test
/**
* 让1号学生选择3号课程
*/
publicvoid demo6(){
Session session = HibernateUtils.openSession();
Transaction tx = session.beginTransaction();
Student student = (Student) session.get(Student.class, 1);
Course course = (Course) session.get(Course.class, 3);
student.getCourses().add(course);
tx.commit();
session.close();
}
@Test
/**
* 让2号学生选择退选2号课改选3号课
*/
publicvoid demo7(){
Session session = HibernateUtils.openSession();
Transaction tx = session.beginTransaction();
Student student = (Student) session.get(Student.class, 2);
Course course2 = (Course) session.get(Course.class, 2);
Course course3 = (Course) session.get(Course.class, 3);
student.getCourses().remove(course2);
student.getCourses().add(course3);
tx.commit();
session.close();
}

本文分享自微信公众号 - Java帮帮(javahelp)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2017-02-23

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 同一Tomcat不同项目如何实现session共享【面试+工作】

    Java帮帮
  • Tomcat Session管理分析【面试+工作】

    上文中在Tomcat的context.xml中配置了Session管理器RedisSessionManager,实现了通过redis来存储session的功能;...

    Java帮帮
  • Spring-Session基于Redis管理Session【面试+工作】

    session同样是使用redis来做集中式存储,为了方便测试使用本地的6379端口redis,LettuceConnectionFactory是redis连接...

    Java帮帮
  • 深入了解session的执行步骤

    第一次访问php,则会随机生成一个session文件发送header头,等待浏览器第二次请求携带cookie,进行判断session_id,我们可以通过上面已经...

    仙士可
  • Django操作session 的方法

    session是存放在服务端的,在django中使用session必须要先在数据库中创建django_session表,session相关信息都要依赖此表

    砸漏
  • 解决session阻塞的问题

    简介 对于数据库运维人员来说创建session或者查询时产生问题是常规情况,下面介绍一种很有效且不借助第三方工具的方式来解决类似问题。 最近开始接触运维...

    逸鹏
  • JSP Session管理

      本篇讲述JSP中session的相关知识和管理方法;   先说说cookie与session   在web中常用的两种用户信息管理方式:cookie 和 s...

    用户1154259
  • XSS利用之延长Session生命周期

    1.0 话题准备 —— session 和 cookie 的原理 —— ▌1.1 session介绍 ---- 简单介绍:PHP session 变量用于存储...

    FB客服
  • Javaweb设置session过期时间

    在Java Web开发中,Session为我们提供了很多方便,Session是由浏览器和服务器之间维护的。Session超时理解为:浏览器和服务器之间创建了一个...

    编程大道
  • Session原理简述

    Session存在的意义,估计每个做web开发的人都是了解的,就为了解决HTTP是无状态协议所带来的问题,不多说了。这里主要想说的是服务端与客户端是如何利用se...

    wangxl

扫码关注云+社区

领取腾讯云代金券