查看“Hibernate笔记 4:核心知识”的源代码
←
Hibernate笔记 4:核心知识
跳到导航
跳到搜索
因为以下原因,您没有权限编辑本页:
您请求的操作仅限属于该用户组的用户执行:
用户
您可以查看和复制此页面的源代码。
[[category:Hibernate]] == 持久化类的编写规则 == 如果一个 Java 类与数据库表建立了映射关系,那么这个类称为是'''持久化类'''。 (该类有对应的映射文件与数据库表相关联) 编写规则: # 持久化类衙要提供无'''参数构造方法'''。 #: 因为在 Hibernate 的底层需要使用反射生成类的实例; # 持久化类必须:'''属性私有''',且提供'''公有的 get 和 set 方法'''。 #: 因为在 Hibernate 底 层会将查询到的数据进行封装; # 持久化类的属性要尽量使用包装类的类型。 #: 因为包装类和基本数据类型的默认值不同,包装类的类型语义描述更消晰而基本数据类型不容易描述; # 持久化类要有一个'''唯一标识 OID''' 与数据库表的'''主键'''相对应。 #: Hibernate 通过 OID 区分在内存中的持久化类; # 持久化类尽量'''不要使用 final''' 进行修饰。 #: 因为 Hibernate 中有延迟加载的机制,这个机制中会产生【代理对象】,Hibernate 产生代理对象使用的是【字节码的增强技术】完成的,其实就是产生了当前类的一个子类对象来实现的。 #: 如果使用了 final 修饰待久化类,那么就不能产生子类,从而不能产生【代理对象】,那么 Hibernate 的'''【延迟加载】策略就会失效'''。 此外,“从代码规范上讲,<span style="color: blue">'''持久化对象是一定要实现序列化接口的'''</span>,保证能在异构化系统或网络中进行数据传输。” === 什么是 OID? === <span style="color: blue; font-size: 150%;">'''OID'''</span>(object identifier,“对象标识符”),是 hibernate 用于区分两个对象(持久化类)是否是同一个对象的标识。 持久化类的 OID 用于'''与数据库表的主键相映射''',所以一般不手动指定。 OID 在对象持久化之前是 '''null''',持久化的时候 hibernate 或者我们手动指定一个 id('''被插入到数据库当做主键,在 session中 当做索引'''),所以,需要保证 OID 与主键的一致性,比如:类型、长度等。 == 主键生成策略 == Hibernate 的主键依据:不同的主键类型、不同的数据库,可以有不同生成策略。 主键类型: # '''自然主键''':带有业务含义的主键(比如:学号,工作编号)。 #* 如果不手动指定主键就提交缓存进行更新,则会报错! #* 主键生成策略: #*# <span style="color: blue">'''assinged'''</span>:Hibernate不维护主键,开发人员需要手动设置主键; #*#* 如果不指定过元素的 <code><generator></code> 属性,则默认使用该主键生成策略。 # '''代理主键''':通过编码自动生成的,无业务含义的主键。 #* 主键生成策略: #*# <span style="color: blue">'''increment'''</span>:(由 Hibernate 提供)'''自动增长'''。 #*#* 适用主键:short、int、long 类型的主键; #*#* 不适用与并发访问数据库; #*# <span style="color: blue">'''identity'''</span>:(由数据库提供)'''自动增长'''。 #*#* 适用主键:short、int、long 类型的主键; #*#* 适用数据库:支持自动增长的数据库(如:DB2、 MySQL、 MS SQL Server、 Sybase 和 HypersomcSQL);(不适用于 Oracle) #*# <span style="color: blue">'''sequence'''</span>:(由数据库提供)'''序列'''。 #*#* 适用主键:short、int、long 类型的主键; #*#* 适用数据库:支持序列的方式的数据库(如:Oracle、db2、sap、db、postgresql); #*# <span style="color: blue">'''native'''</span>:本地策略,根据底层的数据库不同,'''自动选择'''使用 identity 还是 sequence。 #*#* 适用主键:short、int、long 类型的主键; #*# <span style="color: blue">'''uuid'''</span>:Hibernate 采用 128 位的 UUID 算法来生成标识符。 #*#: 该算法能够在网络环境中生成唯一的字符串标识符,其 UUID 被编码为一个长度为 '''32 位的十六进制字符串'''。 #*#* 适用于:字符串类型的主键。 #*#* 这种策略并不流行,因为字符串类型的主键比整数类型的主键占用更多的数据库空间。 == 生命周期(实体状态) == Session 的生命周期是以一个逻辑事物的开始和结束为边界,Session 的主要功能是提供创建、读取和删除映射的实体类的操作。 实体可能存在于三种状态: # '''瞬时态'''(transient):实体对象在内存是自由存在的(即为普通的 Java 对象),即:“该实体从未与任何持久化上下文关联过,它没有持久化标识”。 #* 特点: #*# 不存在待久化标识 '''OID''' (相当于主键值); #*# 尚未与 Session 关联; #*# 数据库无对应记录; #* 对象失去引用后将被 JVM 回收。 # '''持久态'''(persistent):实体对象处于 Hibernate 框架所管理的状态,即:“该实体在数据库中有对应的记录,并拥有一个持久化标识”。 #* 特点: #*# 存在待久化标识 '''OID''' ; #*# 已与 Session 关联(加入到了 Session 缓存,且 Session 未关闭); #*# 数据库有对应记录; #* 持久态对象发生改变时,Hibernate 将会依据其改变自动更新。【无需 update 等操作】 #** 在一个 Session 中,对持久对象的改变不会马上对数据库进行变更,而是发生在 Transaction 终止,执行 commit 之后。 # '''游离态'''(detached,脱管态):由持久态实体对象转变(关联的 Session 被关闭)而来。 #* 特点: #*# 存在持久化标识 '''OID'''; #*# 失去了与 Session 的关联; #*# 数据库有对应记录; #* 游离态对象发生改变时,Hibernate 不能检测到。 #*: 对象的引用依然有效,也可以继续被修改,但修改将不会影响到到数据库中的数据。 “瞬时态”与“游离态”的区别是“是否存在 OID”。(数据库对应记录不是重点)??? 如: Customer customer = new Customer(); // 瞬时态 customer.setCust_id(1); // 脱管态 customer.setCust_id(null); // 瞬时态 === 状态转换 === 三种状态可以互相转换: : [[File:Hibernate 生命周期图.png|600px]] === 持久态的自动更新 === 见:<big>'''[[Hibernate笔记 4:核心知识:Session缓存#持久态自动更新]]'''</big> == Hibernate 缓存 == Hibernate 的缓存分为:“'''一级缓存'''”(<span style="color: blue; font-size: 120%">Session 缓存</span>)和“'''二级缓存'''”(<span style="color: blue; font-size: 120%">SessionFactory 缓存</span>),二者都位于持久化层,存储的都是数据库数据的备份。 作用:减少对数据库的访问次数。 其中: # “'''一级缓存'''”:Session 级别的缓存,事务范围。 ——见:<big>'''[[Hibernate笔记 4:核心知识:Session缓存]]'''</big> #* Hibernate 的内置缓存(默认的缓存机制),不能被卸载; # “'''二级缓存'''”:SessionFactory 级别的缓存,应用范围(应用中的所有 Session 共享)。 #* 默认关闭,需要手动配置; == 事务管理 == 在 Hibernate 中,可以通过代码来操作管理事务(如:开启、提交、回滚),此外,还可以在 Hibernate 的配置文件中对事务进行配置。 事务管理方式: 1、代码。 ——如【'''[[Hibernate笔记 3:核心API#Transaction]]'''】中所示; 2、配置文件。 通过配置文件设置事务管理,步骤: # 配置:事务隔离级别; # 配置:Session 管理方式;(绑定到本地线程) # HibernateUtil 工具类修改 Session 获取方式: #: <syntaxhighlight lang="Java" highlight=""> /** * 获取当前线程绑定的会话: */ public static Session getCurrentSession(){ return sessionFactory.getCurrentSession(); } </syntaxhighlight> * 所有相关配置内容,见:<big>'''[[Hibernate笔记 2:配置文件详解#配置:事务管理]]'''</big> === 关于“Session 管理方式:绑定到本地线程” === 在真正进行事务管理的时候,<span style="color: blue">'''事务控制应该在 Service 层(而非 DAO 层)实现'''</span>, 并且在 Service 中调用多个 DAO 实现一个业务逻辑的操作。 所以,最主要的是:如何保证“在 Service 中开启的事务时所使用的”和“DAO 中多个操作所使用的”是'''同一个 Session 对象'''。 对于保证“同一 Session 对象”,有两种方式: # 在业务层获取到 Session, 并将 Session 作为参数传递给 DAO; # 使用 '''ThreadLocal''' 将业务层获取的 Session 绑定到当前线程中, 然后在 DAO 中获取 Session 的时候, 都从当前线程中获取。【⭐绑定 Session 到当前线程⭐】 显然,“绑定 Session 到当前线程”是更优解。 —— 对此,Hibernate 中,对此已经提供了支持,只需配置即可。 而后,常用的 HibernateUtil 工具类中,获取 Session 的方式也应由 '''<syntaxhighlight lang="Java" inline>sessionFactory.openSession()</syntaxhighlight>''' 替换为使用 '''<syntaxhighlight lang="Java" inline>sessionFactory.getCurrentSession()</syntaxhighlight>'''。 === 关于“事务” === 事务的“<span style="color: blue">'''ACID'''</span>”:Atomicity(原子性)、Consistency(一致性)、Isolation(隔离性)、Durability(持久性) ——见:'''[[InnoDB:InnoDB 和 ACID 模型]]''' 事务的“<span style="color: blue">'''并发问题'''</span>”:脏读、不可重复读、幻读 ——见:'''[[InnoDB 锁机制解析#锁问题]]''' 事务的“<span style="color: blue">'''隔离级别'''</span>”:“READ UNCOMMITTED”、“READ COMMITTED”、“REPEATABLE READ”、“SERIALIZABLE” ——见:'''[[InnoDB:InnoDB 事务模型#事务隔离级别]]''' 相关内容,见:'''[[InnoDB:InnoDB 锁和事务模型]]'''
返回至“
Hibernate笔记 4:核心知识
”。
导航菜单
个人工具
登录
命名空间
页面
讨论
大陆简体
已展开
已折叠
查看
阅读
查看源代码
查看历史
更多
已展开
已折叠
搜索
导航
首页
最近更改
随机页面
MediaWiki帮助
笔记
服务器
数据库
后端
前端
工具
《To do list》
日常
阅读
电影
摄影
其他
Software
Windows
WIKIOE
所有分类
所有页面
侧边栏
站点日志
工具
链入页面
相关更改
特殊页面
页面信息