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();
}
- 基础篇章:React Native之 ScrollView 的讲解
- 常用 Git 命令清单
- 如何将配置spring文件指定名字,指定位置
- 基础篇章:React Native 之 TextInput 的讲解
- Linux下 标准错误输出重定向
- CentOs6.5 修改主机名
- 基础篇章:React Native 之 View 和 Text 的讲解
- CentOs7.3 修改主机名
- 基础篇章:React Native之Flexbox的讲解(Height and Width)
- PDF.js专题
- CentOs7.3 编译安装 Nginx 1.9.9
- 基础篇章:关于 React Native 之 RefreshControl 组件的讲解
- CentOs7.3 安装 JDK1.8
- 基础篇章:关于 React Native 之 ListView 组件的讲解
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法