1.实体类(持久化类)编写规则
1.什么是持久化类
Hibernate是持久层的ORM映射框架,专注于数据的持久化工作。所谓的持久化,就是将内存
中的数据永久存储到关系型数据库中。那么知道了什么是持久化,什么又是持久化类呢?其实所谓的持久化类指的是一个Java类与数据库表建立了映射关系,那么这个类称为是持久化类。其实你可
以简单的理解为持久化类就是一个Java类有了一个映射文件与数据库的表建立了关系。
2.实体类编写规则
(1)类里面有无参数构造
(2)属性是私有的
(3)私有属性提供的公开的get和set方法
(4)要求实体类里面有一个属性和表里面主键对应
(5)建议:实体类写属性类型时候,建议不写基本数据类型,写对应包装类
- byte short int long float double char boolean
- int:Integer char:Character ,其他首字母大写 比如 double :Double
3.为什么写包装类
(1)使用包装类更准确表示数据值
比如 表示学生分数 int score = 100;
表示学生得了0分:int score = 0;
表示学生没有参数考试:int score = 0;
写包装类Integer score = 0;学生得了0分 Integer score = null;表示学生没有参加考试
2.Hibernate主键生成策略
在讲解Hibernate的主键生成策略之前,先来了解两个概念,即自然主键和代理主键,具体如下:
1.主键
**自然主键:**把具有业务含义的字段作为主键,称之为自然主键。例如在customer表中,如
果把name字段作为主键,其前提条件必须是:每-一个客户的姓名不允许为null,不允许客
户重名,并且不允许修改客户姓名。尽管这也是可行的,但是不能满足不断变化的业务需
求,一旦出现了允许客户重名的业务需求,就必须修改数据模型,重新定义表的主键,这
给数据库的维护增加了难度。
**代理主键:**把不具备业务含义的字段作为主键,称之为代理主键。该字段- -般取名为“ID”,
通常为整数类型,因为整数类型比字符串类型要节省更多的数据库空间。在上面例子中,
显然更合理的方式是使用代理主键。
简单理解:
1 自然主键和代理主键
(1)自然主键:表主键字段和业务相关的
- 身份证号码
(2)代理主键(一般使用):表主键字段和业务不相关的
2 .hibernate要求实体类里面有一个属性作为唯一值,对应表主键,主键有不同的生成策略,hibernate主键生成策略有很多的值
3.在class属性里面有很多值
(1)native: 根据使用数据库自动识别生成策略值,比如使用mysql数据库识别使用inentity
- 如果表主键是自动增长,字段类型必须是int类型
(2)uuid:把生成策略写成uuid之后,添加数据时候,自动生成uuid值,添加主键里面
生成策略是uuid时候,主键类型varchar类型
3.实体类操作
调用 session的方法
(1)添加:save方法
(2)修改操作:update方法
(3)根据id查询:get方法
(4)删除:delete方法
saveOrUpdate方法:可以保存,可以实现修改
4.实体类对象状态(概念)
1 实体类状态有三种
(0)区别状态方式:
- 判断实体类对象里面是否有id值
- 判断实体类对象是否与session对象有关联
(1)瞬时态:对象里面没有id值,和session没有关联
(2)持久态:对象里面有id值,和session有关联
(3)托管态:对象里面有id值,和session没有关联
2 演示操作实体类对象的方法
根据实体类对象不同的状态实现不同的操作
(1)saveOrUpdate方法:
-
如果实体类对象状态是瞬时态,执行添加操作
-
如果实体类对象是持久态,执行修改操作
-
如果实体类对象是托管态,执行修改
如果使用托管态时候,id值不存在,不是做添加操作,修改操作
3 实体类三种状态转换(看懂)
(1)瞬时态和持久态之间转换
- 瞬时态转换持久态:调用session里面save方法或者saveOrUpdate方法实现
** 调用save方法之后,与session有关联了,添加数据里面有id值 - 持久态转换瞬时态:调用session里面delete方法实现
(2)托管态和持久态之间转换
- 持久态转换托管态:把session关闭
- 托管态转换持久态:调用update或者saveOrUpdate方法实现
4 持久态自动更新数据库
5.Hibernate的一级缓存
1.什么是缓存
1 hibernate框架本身提供很多优化机制,一级缓存其中一种优化机制
2 什么是缓存
(1)之前存储数据存到数据库里面,比如mysql数据库里面,数据库本身是文件系统
操作数据库相当于操作文件,使用流方式操作文件,文件里面有很多内容,使用流方式做读写操作,很慢
(2)缓存:数据本身不是存储到文件里面,存到系统内存里面,获取数据效率很高
2.Hibernate缓存
1 hibernate框架中提供很多优化方式,hibernate的缓存就是一个优化方式
2 hibernate缓存有两种
第一种 一级缓存
(1)hibernate中一级缓存默认存在的,可以使用
(2)一级缓存使用范围:session对象范围的缓存,session创建到session关闭范围
(3)一级缓存中缓存 持久态 数据
(4)一级缓存使用集合结构
第二种 二级缓存(替代技术redis)
(1)默认不是打开的,需要配置使用
(2)二级缓存使用依赖于其他组件使用
(3)二级缓存范围不是session范围的,是sessionFactory范围
3.验证一级缓存存在
1 验证方式
使用同样的id值查询两次
(1)首先根据id=8a7e8411593de1d501593de1d7d70000值查询
(2)再根据这个id=8a7e8411593de1d501593de1d7d70000值查询
(1)第一次调用get方法发送sql语句查询数据库
(2)第二个调用get方法没有发送sql语句,数据从hibernate的一级缓存中获取
2.一级缓存执行过程
3.一级缓存特性
1 持久态自动更新数据库
做修改时候,根据id调用get方法查询,向返回对象里面设置值,最后不需要调用update方法实现修改
2 执行过程(了解)
一级缓存快照区(副本)
文字描述:
(1)一级缓存范围是session范围,创建session之后,创建一级缓存,除了一级缓存,一级缓存还会有一个对应一块区域,称为一级缓存对应的快照区
(2)调用get方法,首先到一级缓存找是否有相同数据,如果没有查询数据库,返回user持久态对象,把返回user对象放到一级缓存中,除了放到一级缓存中,还会放到一级缓存对应快照区
(3)修改user对象里面值时候,修改持久态对象里面值,同时会去修改一级缓存中内容,但是不会修改快照区内容
(4)最终提交事务,提交时候,做事情:比较一级缓存和快照区内容是否一样,如果不一样把一级缓存中更新到数据库里面,如果一样不会更新
6.Hibernate事务操作
1.事务相关概念
1 什么是事务
(1)逻辑上一组操作,要么都成功,如果有一个失败都失败
(2)转账例子
2 事务特性
(1)四个特性:原子性、一致性、隔离性、持久性
(2)隔离性:多个事务操作之间不会产生影响
3 不考虑隔离性产生问题
(1)脏读:一个事务读到另一个事务没有提交数据
(2)不可重复读:一个事务读到另一个事务提交update数据
(3)虚(幻)读:一个事务读到另一个事务提交insert数据
4 设置事务隔离级别
(1)mysql默认隔离级别:repeatable read
7.Hibernate绑定session
1 session类似于jdbc的connection,之前web阶段学过 ThreadLocal
(0)与线程绑定,把数据库连接与线程绑定
(1)保证session肯定不能被公用,把session与本地线程绑定
2与本地线程绑定session
3 获取与本地线程session
(1)在hibernate核心配置文件中配置
thread
(2)这个值到hibernate.properties里面没有
(2)调用sessionFactory里面的方法得到
4 获取与本地线程绑定session时候,关闭session报错,不需要手动关闭了
5 hibernate配置事务隔离级别
(1)配置在hibernate核心配置文件中,使用级别对应数字配置
6.事务添加到Service层
8.Hibernate的api使用
1 在hibernate第一天时候,调用session对象里面的方法实现crud操作,做查询操作时候,只是做了根据id查询
2 下面的这几个对象,实现查询操作
(1)查询表所有记录
(2)条件查询
- 包含模糊查询
(3)分页查询
(4)排序查询
(5)投影查询 - 不是查询所有字段值,查询部分字段值
(6)聚集函数使用
(7)多表查询
(8)hibernate操作不能实现复杂查询操作,使用普通sql
1.Query对象
1 作用:
(1)使用query对象实现查询操作,写到语句实现,不是sql语句,是hibernate提供一种查询语句
(2)hql:hibernate query language,hibernate查询语言
(3)sql语句和hql语句区别:
sql语句:操作数据库表和表里面字段
hql语句:操作不是表和字段,是实体类和实体类里面属性
/1 使用query查询所有记录
@Test
public void testQueryFindALL() {
SessionFactory sessionFactory = null;
Session session = null;
Transaction tx = null;
try {
//获取sessionFactory对象
sessionFactory = HibernateUtils.getSessionFactory();
//获取session
session = sessionFactory.openSession();
//开启事务
tx = session.beginTransaction();
//1 创建query对象
// createQuery里面写hql语句
//查询所有
String hql = "from User";
Query query = session.createQuery(hql);
//2 调用query的方法得到结果
List<User> list = query.list();
for (User user : list) {
System.out.println(user);
}
//提交
tx.commit();
}catch(Exception e) {
//回滚
tx.rollback();
}finally {
//关闭
session.close();
sessionFactory.close();
}
}
4 条件查询操作
条件查询hql语句: from 实体类名称 where 属性名称=? and ….
(1)根据username查询
第一个参数是 int类型,?位置,从0开始的
第二个参数是 条件值
2 使用query条件查询
@Test
public void testQueryCondition() {
SessionFactory sessionFactory = null;
Session session = null;
Transaction tx = null;
try {
//获取sessionFactory对象
sessionFactory = HibernateUtils.getSessionFactory();
//获取session
session = sessionFactory.openSession();
//开启事务
tx = session.beginTransaction();
//1 创建query对象
//根据username查询
String hql = "from User where username=?";
Query query = session.createQuery(hql);
//2 设置条件值
//第一个参数是 int类型,?位置,从0开始的
//第二个参数是 条件值
query.setParameter(0, "岳不群");
List<User> list = query.list();
for (User user : list) {
System.out.println(user);
}
//提交
tx.commit();
}catch(Exception e) {
//回滚
tx.rollback();
}finally {
//关闭
session.close();
sessionFactory.close();
}
}
2.Criteria对象
(1)qbc查询,query by criteria,使用qbc时候特点:不需要写hql语句,使用封装的方法实现
/3 使用criteria查询所有
@Test
public void testQBCFindall() {
SessionFactory sessionFactory = null;
Session session = null;
Transaction tx = null;
try {
//获取sessionFactory对象
sessionFactory = HibernateUtils.getSessionFactory();
//获取session
session = sessionFactory.openSession();
//开启事务
tx = session.beginTransaction();
//1 创建criteria对象
//createCriteria参数是实体类class
Criteria criteria = session.createCriteria(User.class);
//2 调用方法得到结果
List<User> list = criteria.list();
for (User user : list) {
System.out.println(user);
}
//提交
tx.commit();
}catch(Exception e) {
//回滚
tx.rollback();
}finally {
//关闭
session.close();
sessionFactory.close();
}
}
3.SQLQuery对象
1 作用
(1) hibernate操作很难实现复杂查询操作,使用普通sql,SQLQuery对象用来在hibernate里面调用普通sql语句实现功能
/4 使用SQLQuery查询所有
@Test
public void testSQLQueryFindAll() {
SessionFactory sessionFactory = null;
Session session = null;
Transaction tx = null;
try {
//获取sessionFactory对象
sessionFactory = HibernateUtils.getSessionFactory();
//获取session
session = sessionFactory.openSession();
//开启事务
tx = session.beginTransaction();
//1 创建sqlquery对象
String sql = "select * from t_user";
SQLQuery sqlQuery = session.createSQLQuery(sql);
//2 调用方法得到结果
List<Object[]> list = sqlQuery.list();
for (Object[] objects : list) {
System.out.println(Arrays.toString(objects));
}
//提交
tx.commit();
}catch(Exception e) {
e.printStackTrace();
//回滚
tx.rollback();
}finally {
//关闭
session.close();
sessionFactory.close();
}
}
(3)让返回list集合中每部分是对象结构
//4 使用SQLQuery查询所有
@Test
public void testSQLQueryFindAllDemo() {
SessionFactory sessionFactory = null;
Session session = null;
Transaction tx = null;
try {
//获取sessionFactory对象
sessionFactory = HibernateUtils.getSessionFactory();
//获取session
session = sessionFactory.openSession();
//开启事务
tx = session.beginTransaction();
//1 创建sqlquery对象
String sql = "select * from t_user";
SQLQuery sqlQuery = session.createSQLQuery(sql);
//2 设置返回list集合中每部分结构
sqlQuery.addEntity(User.class);
//2 调用方法得到结果
List<User> list = sqlQuery.list();
for (User user : list) {
System.out.println(user);
}
//提交
tx.commit();
}catch(Exception e) {
e.printStackTrace();
//回滚
tx.rollback();
}finally {
//关闭
session.close();
sessionFactory.close();
}
}