0
点赞
收藏
分享

微信扫一扫

Hibernate_day02总结

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

/**

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

*/

publicvoid​demo2(){

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.清空一级缓存中的某个对象

*/

publicvoid​demo5(){

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.将数据库中数据覆盖掉一级缓存的数据

*/

publicvoid​demo6(){

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个订单

*/

publicvoid​demo1(){

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"

*/

publicvoid​demo10(){

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

/**

* 插入数据:级联保存:

* * 保存课程级联学生

*/

publicvoid​demo3(){

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();

}


举报

相关推荐

0 条评论