Hibernate
程序员文章站
2022-05-07 19:03:36
持久化类的编写规则什么是持久化类持久化:将内存中的一个对象持久化到数据库中的过程.Hibernate就是用来进行持久化的框架持久化类:一个Java对象与数据库的表建立了映射关系,那么这个类在Hibernate中称之为持久化类.(持久化类 = Java类 + 映射文件)编写规则1.对持久化类提供一个无参数的构造方法 — Hibernate需要使用凡是生成实例2.属性需要私有,对私有属性提供get和set方法 — Hibernate中获取,设置对象的值3. 对持久化类提供一个唯一标识OID与数...
持久化类的编写规则
什么是持久化类
- 持久化:将内存中的一个对象持久化到数据库中的过程.Hibernate就是用来进行持久化的框架
- 持久化类:一个Java对象与数据库的表建立了映射关系,那么这个类在Hibernate中称之为持久化类.(持久化类 = Java类 + 映射文件)
编写规则
1.对持久化类提供一个无参数的构造方法 — Hibernate需要使用凡是生成实例
2.属性需要私有,对私有属性提供get和set方法 — Hibernate中获取,设置对象的值
3. 对持久化类提供一个唯一标识OID与数据库主键对应 — Java中通过对象的地址区分是否同一个对象,数据库中通过主键确定是否是同一个记录,而在Hibernate中通过持久化类的OID的属性区分是否是同一个对象
4. 持久化类中属性尽量使用包装类 — 因为基本数据类型默认是0,包装类默认值是null (int => Integer,long=>Long,double=>Double)
5. 持久化类不能使用final进行修饰 — 延迟加载本身是Hibernate一个优化的手段,返回的是一个代理对象(Javassist),如果不能继承,不能产生代理对象,延迟加载也就会失败,load方法和get方法将会一样.
主键生成策略
主键的分类
- 自然主键:主键的本身就是表中的一个字段(实体中的一个具体的属性)
- 代理主键:主键的本身不是表中必须的一个字段(不是实体中的某个具体属性)
在实际开发中,尽量使用代理主键
1.一旦自然主键参与业务逻辑中,后期有可能需要修改源码
2.好的程序设计满足OPC原则,对程序的扩展是open的,对修改源码是close的
主键生成策略
在映射文件中配置
<id name="cust_id" column="cust_id">
<generator class="native"/>
</id>
- increment : Hibernate中提供的自动增长机制,适用short、int、long类型的主键,在单线程中使用 .(首先发送一条语句select max(id) from stu,然后将查到的id + 1作为下一条记录的主键)
- identity : 适用short、int、long类型的主键.使用的是数据库的自动增长机制.适用于有自动增长机制数据库(MySQL、MSSQL),但是Oracle没有自动增长
- sequence : 适用short、int、long类型的主键.采用序列的方式.(Oracle支持序列).但MySQL不能使用sequence
- uuid : 适用于字符串类型主键.使用Hibernate中的随即方式生成字符串主键
- native : 本地策略,可以在identity和sequence之间进行自动切换
- assigned : Hibernate放弃外键的管理,需要通过手动编写程序或者用户自己设置.
- foreign : 外部的,一对一的一种关联映射的情况下使用(了解)
持久化类的三种状态
三种状态
- 瞬时态 : 没有唯一的标识OID,没有被session管理
- 持久态 : 有唯一的标识OID,被session管理
- 托管态 : 有唯一的标识OID,不被session管理
public void demo1() {
Session session = HibernateUtils.openSession();
Transaction transaction = session.beginTransaction();
Customer customer = new Customer(); //瞬时态 : 没有唯一的标识OID,没有被session管理
customer.setCust_name("张三");
Serializable id = session.save(customer);//持久态 : 有唯一的标识OID,被session管理
transaction.commit();
session.close();
System.out.println(customer.getCust_name());//托管态 : 有唯一的标识OID,不被session管理
}
站在三种状态角度看saveOrUpdate()方法
public void demo2() {
Session session = HibernateUtils.openSession();
Transaction transaction = session.beginTransaction();
/*当为瞬时态对象时执行save方法*/
/*Customer customer = new Customer();
customer.setCust_name("张三");
session.saveOrUpdate(customer);*/
/*当为托管态对象时执行update方法*/
Customer customer = new Customer();
customer.setCust_id(3l);
customer.setCust_name("李四");
session.saveOrUpdate(customer);
transaction.commit();
session.close();
}
持久态对象特性 : 持久态对象自动更新数据库
public void demo3() {
Session session = HibernateUtils.openSession();
Transaction transaction = session.beginTransaction();
Customer customer = session.get(Customer.class, 3l);
customer.setCust_name("王五");
//不用执行update方法,持久态对象自动更新数据库
//session.update(customer);
transaction.commit();
session.close();
}
一级缓存
什么是缓存
- 缓存 : 是一种优化的方式,将数据存入到内存中,使用的时候直接从缓存中获取,不用通过向存储源获取
Hibernate的一级缓存
- Hibernate框架中提供了优化手段 : 缓存、抓取策略.
- Hibernate中提供了两种缓存机制:一级缓存、二级缓存
- Hibernate的一级缓存:称为是session级别的缓存,一级缓存生命周期与session一致(一级缓存是由Session中的一系列Java集合构成的).一级缓存是自带的不可卸载的.
- Hibernate的二级缓存:时SessionFactory级别的缓存,需要配置,一般不用Hibernate中的二级缓存,一般用redis等
证明一级缓存的存在
public void demo4() {
Session session = HibernateUtils.openSession();
Transaction transaction = session.beginTransaction();
Customer customer1 = session.get(Customer.class, 1l);//发送SQL语句
System.out.println(customer1);
Customer customer2 = session.get(Customer.class, 1l);//不发送SQL语句
System.out.println(customer2);
transaction.commit();
session.close();
}
一级缓存的特殊区域 : 快照区
事务管理
什么是事务
- 事务:是逻辑上的一组操作.组成这组操作的各个逻辑单元要么全部成功,要么全部失败.
事务特性
- 原子性:代表事务不可分割
- 一致性:代表事务执行的前后,数据的完整性保持一致
- 隔离性:代表一个事务执行过程中,不应该受到其他事务的干扰
- 持久性:代表事务执行完成后,数据就持久到数据库中
不考虑隔离性,引发的安全问题
- 读问题:
1.脏读 : 一个事务读到另一个事务未提交的数据(因为另一个事务可能会回滚)
2.不可重复读 : 一个事务读到另一个事务已经提交的,但是update数据,导致在前一个事务多次查询结果不一致
3.虚读 : 一个事务读到另一个事务已经提交的,但是insert数据,导致在前一个事务多次查询结果不一致 - 写问题:
引发两类丢失更新(了解)
读问题的解决
- 设置事务的隔离级别
1.Read uncommitted : 以上读问题都会发生
2.Read committed : 解决脏读,但是不可重复读和虚读有可能发生(Oracle一般用)
3.Repeatable read : 解决脏读和不可重复读,但是虚读有可能发生(MySQL一般用)
4.Serializable : 解决所有问题(不允许事务并发)
在Hibernate核心文件hibernate.cfg.xml中配置
<!--
事务隔离级别
1 -> Read uncommitted
2 -> Read committed
4 -> Repeatable read
8 -> Serializable
-->
<property name="hibernate.connection.isolation">4</property>
Hibernate的事务管理:线程绑定的session
- 必须保证连接对象是同一个
1.向下传递
2.使用ThreadLocal对象(将这个连接绑定到当前线程中,在DAO的方法中通过当前的线程获得连接) - Hibernate框架内部已经绑定好了ThreadLoacl
在SessionFactory中提供了一个方法getCurrentSession();
这个方法默认不能用,需要配置才能用
public static Session getCurrentSession() {
return sf.getCurrentSession();
}
在核心文件hibernate.cfg.xml中配置
<!-- 配置当前线程绑定的Session -->
<property name="hibernate.current_session_context_class">thread</property>
- thread : 与当前线程绑定
- jta : 跨服务器绑定,例:实现向Oracle与MySQL的操作在同一个事务中
- managed : - - -
其他常用API
Query***
- query接口用于接收HQL,查询多个对象
HQL:Hibernate Query Language,Hibernate查询语言(面向对象的查询语言)
@Test
/*
* Query
*/
public void demo4() {
Session session = HibernateUtils.getCurrentSession();
Transaction tx = session.beginTransaction();
//简单查询
// String hql = "from Customer";
// Query query = session.createQuery(hql);
//条件查询
// String hql = "from Customer where cust_name like ?";
// Query query = session.createQuery(hql);
// query.setParameter(0, "王%");
//分页查询
String hql = "from Customer";
Query query = session.createQuery(hql);
query.setFirstResult(0);
query.setMaxResults(3);
List<Customer> list = query.list();
for (Customer customer : list) {
System.out.println(customer);
}
tx.commit();
}
Criteria***
- Criteria : QBC ==> Query By Criteria
更加面向对象的一个查询方式
@Test
/*
* Criteria
*/
public void demo5() {
Session session = HibernateUtils.getCurrentSession();
Transaction tx = session.beginTransaction();
//简单查询
// Criteria criteria = session.createCriteria(Customer.class);
//条件查询
// Criteria criteria = session.createCriteria(Customer.class);
// criteria.add(Restrictions.like("cust_name", "张%"));
// criteria.add(Restrictions.like("cust_name", "张",MatchMode.ANYWHERE));
//分页查询
Criteria criteria = session.createCriteria(Customer.class);
criteria.setFirstResult(0);
criteria.setMaxResults(3);
List<Customer> list = criteria.list();
for (Customer customer : list) {
System.out.println(customer);
}
tx.commit();
}
SQLQuery
- SQLQuery用于接收SQL,特别复杂情况下使用SQL(例如关联八九个表)
本文地址:https://blog.csdn.net/a1669820631/article/details/107296075
上一篇: Java编程之字符串的大小写转换
推荐阅读
-
Spring 整合 Hibernate 时启用二级缓存实例详解
-
JSP开发中hibernate框架的常用检索方式总结
-
SSH整合中 hibernate托管给Spring得到SessionFactory
-
浅谈hibernate之映射文件VS映射注解
-
详解Hibernate cascade级联属性的CascadeType的用法
-
解决hibernate+mysql写入数据库乱码
-
在spring中使用Hibernate5
-
解决Hibernate JPA中insert插入数据后自动执行select last_insert_id()
-
详解 hibernate mapping配置
-
SSH框架之Hibernate第一篇