1.JPA入门
JPA的认识:
JPA全称Java Persistence API.JPA通过JDK 5.0注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中Java持久层API sun公司出标准,接口(规范,注解)实现框架:Hibernate,oracle toplink(eclipse link),apache open jpa不写映射文件,没有LoginUser.hbm.xml,把映射信息用注解的方式写到持久对象LoginUser
重点:注解方式只是作为一个知识点学习,实际生产中几乎不会使用注解方式.
使用方式步骤:
1.不写映射文件,使用注解代替
2.hibernate主配置文件中配置如下
完成.
2.配置自动生成表配置
如果要生成表,只需要表名,列名对应的类型,全部在映射文件里面有定义
创建表的时间:成功获取到SessionFactory对象
配置创建表:hibernate.hbm2ddl.auto
先删除表,再创建表,再删除表删除表的时机:把SessionFactory关闭
Hibernate.hbm2ddl.auto常用的3个属性
create 只有在测试的时候使用先删除表,再创建表,不会再删除表
update 用在测试和web项目如果没表就根据最新的映射文件来创建表如果表里面已经有这个属性,如修改属性的长度,不会更新到表里面需要更新先删除表或者删除这个属性对应的列名如果表里面没有属性,映射文件存在,增加这个列
validate 用在系统已经上线表不存在就,抛出上面异常映射文件少属性,表比映射定义的列要多,不会报错反之,抛出异常
create-drop这个开发一般不会用,面试会被问到
更多主配置文件参数,请查询官方文档,敲黑板画重点:学习一定要多看官方文档,该文当只是将官方文档中的重点和重要配置做讲解
3.映射文件细节
<!-- 生日:年月日 type="date" -->
<property name="birthday" type="date" />
<!-- 开会时间:时分秒 type="time" -->
<property name="time" type="time" />
<!-- 大文本 type="text" -->
<property name="text" type="text" />
hibernate中对应的数据类型:画红线的是常用的几个
4.hibernate核心API
4.1Configuration
在hibernate中,可以直接使用代码完成所有的配置,不一定非要hibernate.cfg.xml文件
4.2.SessionFactory
作用与概念
主要作用:负责创建Session对象
概念:SessionFactory对象中保存了当前的数据库配置信息和所有映射关系以及预定义的SQL语句。同时,SessionFactory还负责维护Hibernate的二级缓存,查询缓存。
注意
1.SessionFactory对象的创建会有较大的开销,因为SessionFactory内部采取了线程安全的设计方式,因此在实际中SessionFactory对象可以尽量的共享,在大多数情况下,一个应用中针对一个数据库可以共享一个SessionFactory实例。
2.一个请求:一个Session对象(包含一个连接对象,一个事务对象,一个一级缓存)
结论:一级缓存不同请求(不同用户)不能共享,二级缓存可以共享
重要的方法
openSession:这个方法代表,开启一个全新的Session
1)全新的连接
2)全新的事务
3)全新的一级缓存
getCurrentSession:得到当前上下文中的session
1)如果当前上下文中存在session,则使用该session;
2)如果当前上下文中不存在session,则使用opensession创建一个新的session;放到当前线程
3)要使用getCurrentSessoin,必须在hibernate.cfg.xml中配置thread
<property name="current_session_context_class">thread</property>
4)getCurrentSession得到的session是和事务绑定的;
无论是DML(数据操作语言)还是DQL(数据查询语言) ,都必须开启事务
提交事务的时候就是关闭session
注意:getCurrentSession使用场景(如下)
本行转账业务:达到一致性,要不都成功,要不都失败保证在service层,在dao层获取的session都是同一个,对应就是同一个事务对象
4.3. Session
使用最广泛,也被称为持久化管理器,它提供和持久化相关的操作。增、删、改、查等。不是线程安全的,因此,一个Session对象只可以由一个线程使用。避免多个线程共享。轻量级的,创建和销毁不需要消耗太多资源。
Session中有一个缓存,称为一级缓存。存放当前工作单元加载的对象。
一级缓存命中:同一个sessionFactory,同一个session
结论: 先从一级缓存取,取不到,发出sql获取,放入一级缓存
// 一级缓存命中:只会发出一条sql
// 一级缓存命中条件:同一个session的OID是否相同
// 一级缓存内部的结构:
// OID:Object ID(唯一值),hibernate里面定义
// 操作的持久对象全限定类名+"#"+数据库主键的值
// com.hibernate.day01.model.LoginUser#1
//存放在 Map<String,Object> cacheMap
5.Hibernate对象状态
HIbernate的状态对我们来说非常非常重要,特别是当我们使用的时候,还有遇到问题的时候,我们需要通过状态来分析,才知道这到底是为什么?
临时状态(transient):瞬时状态刚刚用new语句创建,没有和session发生关系没有被持久化,不处于session中。该对象成为临时对象
持久化状态(persistent):托管状态和session发生关系已经被持久化,加入到session的一级缓存中。该状态的对象为持久化对象。
游离状态(detached):脱管状态已经被持久化,但不处于session中。该状态的对象为游离对象。
删除状态(removed):从jpa出现,才有的状态只有调用了session.delete(domain对象)方法对象有关联的ID,并且在Session管理下,但是已经被计划删除(真正删除是提交事务的时候)。
6.脏数据更新
脏数据更新:
一个持久状态对象在事务管理内,一但改变原来的数据(非主键)(出现脏数据),事务提交的时候自动发出update去修改
7.org.hibernate.NonUniqueObjectException异常
// 同一个session出现2个OID在不同的内存地址
// 一级缓存里面的OID只能有一个内存地址
// 一级状态的里面的对象是否是持久状态?是
测试完成后报错如下:
报错根本原因:
持久状态的对象是不能修改OID(不能修改主键)
持久层修改id会报下面的错误,大家要注意小心:
org.hibernate.HibernateException: identifier of an instance of com.hibernate.crud.model.LoginUser was altered from 1 to 2
8.延迟加载(懒加载)
延迟加载(懒加载):真正需要非主键属性,才发出sql,获取非主键属性值提高性能,但是如果把session提前关闭,会出现(延迟加载)延迟初始化异常
注意:
1.没有对应主键,报错
2.提前关闭session报错
get,load区别方法
9.Domain对象定义规则
Domain对象定义规则:
1.类不是final类,可以被继承
2.所有属性的类型都必须是包装类型,不能是8个基本类型(int,byte,short,long,char,boolean,float,double)因为hibernate内部很多判断都是判断是否等于null
注意:如果不是包装类型,当为null时报错
10.把持久状态的对象变成游离状态
session.close();把一级缓存清空,关闭
session.clear();把一级缓存清空
session.evict(object持久对象);清空一级缓存里面指定的持久对象