简介
学习Java有一段时间了,一直在忙碌着学习,每天大量的新知识和新技术来不及消化,第二天又接着学习。有想法有时会想一下,大部分作为学习者角色完成这段时间的学习。反正最终不忘记自己的初心和学习的意义。好啦~不闲扯了,今天小Hi入门,主要学习持久化对象概述、映射对象标识符、和如何操纵持久化对象
Hibernate简介
1、Hibernate是处于开发中的持久层框架,他是一个ORM映射工具(Object/RelationMapping,对象-关系映射,就是通过将Java对象映射到数据库表,通过操作Java对象,就可以完成对数据表的操作)。是轻量级JavaEE应用的持久层解决方案。 1.开源的持久层框架. 2.ORM(Object/Relational Mapping)映射工具,建立面向对象的域模型和关系数据模型之间的映射. 3.连接java应用和数据库的中间件. 4.对JDBC进行封装,负责java对象的持久化. 5.在分层结构中处于持久化层,封装对数据库的访问细节,使业务逻辑层更专注于实现业务逻辑 2、流行数据库框架 JPA Java Persistence API.JPA通过JDK 5.0注解或XML描述对象-关系表的映射关系(只有接口规范) Hibernate 最流行ORM框架,通过对象-关系映射配置,可以完全脱离底层SQL MyBatis 本是apache的一个开源项目 iBatis,支持普通 SQL查询,存储过程和高级映射的优秀持久层框架 Apache DBUtils 、Spring JDBCTemplate 3. 为什么要用Hibernate 1、Hibernate对JDBC访问数据库的代码做了封装,大大简化了数据访问层繁琐的重复性代码。 2、Hibernate是一个基于jdbc的主流持久化框架,是一个优秀的orm实现,它很大程度的简化了dao层编码工作。 3、Hibernate使用java的反射机制,而不是字节码增强程序类实现透明性 4、Hibernate的性能非常好,因为它是一个轻量级框架。映射的灵活性很出色。它支持很多关系型数据库,从一对一到多对多的各种复杂关系
JDBC和Hibernate区别
JDBC的缺点 代码比较繁琐 没有做到数据缓存 不是面向对象的开发 移植性比较差 事务处理不是特别好 因为jdbc是最底层的操作,所以效率比较高 hibernate的优点 代码比较简单 具有缓存:一级缓存、二级缓存、查询缓存 命中率的概念 面向对象的开发 移植性比较强 hibernate的缺点 支持的分布式事务比较弱 如果一张表的数据有千万级别,不适合用hibernate来做 如果表之间的关系相当复杂,不适合用hibernate来做
Hibernate组成
1、持久化类(POJO)对应与数据库的一张表 2、映射文件:建立持久化类与数据库中的表的对应关系 3、配置文件:用来描述连接数据库的信息
Hibernate环境搭建
1. Hibernate并没有提供日志的实现可以下载slf4j 和 log4j 开发包,整合Hibernate的日志系统到log4j 2. 开始准备jar包 拷贝Hibernate发型包hibernate3.jar(1个) 拷贝Hibernate发型包lib equired下的所有jar(6个) 拷贝Hibernate发型包libjpa下的jar(1个) 拷贝Log4j的核心jar包(1个) 拷贝slf4j发型包slf4j-log4j12-*.jar(1个) 数据库驱动jar(MySQL就1个) 如果用到日志,拷贝Hibenate发型包projectetclog4j.properties到构建路径中 3. 建立配置文件hibernate.cfg.xml(参考Hibernate发型包projectetchibernate.properties) hibernate的配置文件可以分为两个部分: 数据库的连接配置(用户名、密码、url、数据库驱动)2、其他配置(方言、验证数据库结构、映射文件) 4. 创建数据库表和实体 持久化对象的要求: 提供一个无参数 public访问控制符的构造器(默认就是) 提供一个标识属性,映射数据表主键字段 所有属性提供public访问控制符的 set get 方法 属性应尽量使用基本数据类型的包装类型 5. 在实体类所在的包中,创建Java对象与数据库的映射文件。文件名为"实体类名-hbm.xml" 配置class/id/property 6. 配置dtd连不上网情况下约束(hibernate3.jar中rg.hibernate下两个文件hibernate-configuration-3.0.dtd/hibernate-mapping-3.0.dtd) 7. 编码测试 hibernate的SessionFactory在初始化阶段只初始化一次即可,所有使用静态代码块进行封装,其中Configuration是用来加载hibernate的配置文件和映射文件的,加载后可以获取SessionFactory
Hibernate基本API类介绍
Configuration 类负责管理 Hibernate 的配置信息。包括如下内容: •Hibernate运行的底层信息:数据库的URL、用户名、密码、JDBC驱动类,数据库Dialect,数据库连接池等(对应 hibernate.cfg.xml 文件) •持久化类与数据表的映射关系(*.hbm.xml 文件) SessionFactory接口 SessionFactory是生成Session的工厂,构造 SessionFactory 很消耗资源,一般情况下一个应用中只初始化一个 SessionFactory 对象,SessionFactory 对象一旦构造完毕,即被赋予特定的配置信息(SessionFactory 对象中保存了当前的数据库配置信息和所有映射关系以及预定义的SQL语句。同时,SessionFactory还负责维护Hibernate的二级缓存) Session接口 Session 是应用程序与数据库之间交互操作的一个单线程对象,是 Hibernate 运作的中心,所有持久化对象必须在 session 的管理下才可以进行持久化操作。Session 对象有一个一级缓存,显式执行 flush 之前,所有的持久层操作的数据都缓存在 session 对象处,相当于 JDBC 中的 Connection Transaction接口 所有持久层都应该在事务管理下进行,即使是只读操作 常用方法: •commit():提交相关联的session实例 •rollback():撤销事务操作 •wasCommitted():检查事务是否提交
Hibernate运行流程
1、应用程序先调用Configuration类,该类读取Hibernate配置文件及映射文件中的信息 2、并用这些信息生成一个SessionFactory对象 3、然后从SessionFactory对象生成一个Session对象 4、并用Session对象生成Transaction对象 A、可通过Session对象的get(),load(),save(),update(),delete()和saveOrUpdate()等方法对PO进行加载、保存、更新、删除、等操作 B、在查询的情况下,可通过Session对象生成一个Query对象,然后利用Query对象执行查询操作;如果没有异常,Transaction对象将提交这些操作到数据库中
Java 应用的持久化分层
Hibernate中间件:Hibernate不和特定的业务领域相关,能够把任意一个Java应用与数据库系统连接,可以理解为是一种中间件 Hibernate的持久化对象:目的就是与数据库同步,使用对象操作数据库。实体域对象在内存中创建后,不能永久存在。将实体域对象永久保存起来,就是持久化的过程。通常只有实体域对象需要持久化,过程域对象和事件域对象一般不需要持久化。广义持久化指增、删、改、查 ORM:(Object/Relation Mapping): 对象/关系映射 ----------------------------------------------------------------------- 1. ORM:(Object/Relation Mapping): 对象/关系映射 ORM中间件的使用方法 采用元数据来描述对象-关系映射细节,元数据通常采用xml格式,并存放在专门的对象-关系映射文件中。只要配置了持久化类与表的映射关系,orm中间件在运行时就能够参照映射文件的信息,把域对象持久化到数据库中 2:hibernate之所以操作javabean的过程即操作数据库的表,这hibernate底层会调用javabean持久化对象的set和get方法,对数据进行赋值和取值,并获取字段名称,组织sql语句,并执行sql语句,达到效果 3:hibernate要求javabean中要使用包装数据类型(Integer,Long,String等)
对象关系映射
#知识点1:访问Hibernate中持久化类,两种访问角度: 保存(save): 会调用持久化类中的setter方法 查看(get): 会调用持久化类中的getter方法 #知识点2: 基本数据类型和包装类型区别 基本类型可直接运算、无法表达null、数字类型的默认值为0 包装类默认值是null。当对于默认值有业务意义的时候需要使用包装类 *基本数据类型和包装类型对应的hibernate映射类型相同 #知识点3: Hibernate访问持久化类属性的策略 1.propertye 默认值:表明hibernate通过getXXX和 setXXX来访问类属性。推荐使用。提高域模型透明性。 2.field:hibernate通过java反射机制直接访问类属性。对于没有 javabean方法的属性可设置该访问策略。 3. noop(了解):它映射Java持久化类中不存在的属性,即主要用于HQL(用query接口测试,使用hql语句)中,当数据库中有某列,而实体中不存在的情况 #知识点4: 在持久化类的方法中加入程序逻辑 在Customer.hbm.xml文件中无需映射firstname和lastname属性,而是映射name属性。尽管类中并没有name属性,由于hibernate不是直接访问Name属性,而是调用get、set方法,在此方法中加入程序逻辑,因此建立了Firstname、Lastname和表之间的联系 #知识点5: 设置派生属性 利用<property>元素的formula属性,用来设置一个sql表达式,hibernate将根据它来计算出派生属性的值 <property name="totalPrice" formula="(select sum(o.price) from b_customer o)"></property> #知识点6: 控制insert、update语句 映射属性 作用 <property> insert属性 若为false,在insert语句中不包含该字段,该字段永远不能被插入。默认值true。 <property> update属性 若为false,update语句不包含该字段,该字段永远不能被更新。默认值为true。 <class> mutable属性 若为false,等价于所有的<property>元素的update属性为false,整个实例不能被更新。默认为true。 <class> dynamic-insert属性 若为true,等价于所有的<property>元素的insert为true,保存一个对象时,动态生成insert语句,语句中仅包含取值不为null的字段。默认false。 <class> dynamic-update属性 若为true,等价于所有的<property>元素的update为true,更新一个对象时,动态生成update语句,语句中仅包含属性值发生变化的字段。默认false #知识点7: 处理sql引用表示符 在SQL语法中,表示符是指用于为数据库表、视图、字段或索引等名字的字符串,常规表示符不包括空格,也不包含特殊字符,因此无需使用引用符号。如果数据库表名或列名包含特殊字符,可以使用引用表示符(tab上面一个键) #知识点8:设置类的包名 如果在一个映射文件中包含多个类,并且这些类位于同一个包中,可以设置<hibernate-mapping>元素的package属性,避免为每个类提供完整的类名 ***映射关系注意事项 1. 类中的属性不一定与表中的字段一一对应,全部映射 2. 表中的字段不一定与类中的属性一一对应,全部映射 3. 关联关系不一定配置成双向的,可以只配置一边,那是name属性必须要填写 4. 一个类可以映射多个表,一个表可以映射多个类
映射对象标识符
1.Hibernate的唯一性标识 (1)Java按地址区分同一个类的不同对象. (2)关系数据库用主键区分同一条记录. (3)Hibernate使用OID来建立内存中的对象和数据库中记录的对应关系。对象的OID和数据库的表的主键对应。为保证OID的唯一性,应该让Hibernate来为OID赋值 2. hibernate支持自然主键和代理主键 (1)自然主键:具有业务含义的字段,如name (2)代理主键:不具有业务含义的字段,如id 3. Hibernate的一级缓存和快照 (1)一级缓存: hibernate在内存地址中存在一个一级缓存,存在在一级缓存中的对象,就说明该对象具有了持久化的能力,如果对象具有持久化能力就能操作数据库。一级缓存中的数据使用oid用来区分对象,当查询数据库的时候,如果一级缓存中存在oid的数据,则不会产生select语句,Hibernate对查询数据库实现了性能优化,当Session关闭,一级缓存的数据就没有了。如何让缓存中的数据一直存在呢(即使Session关闭也存在),大家可以期待Hibernate的二级缓存。 (2)快照 Hibernate除了在内存中定义一级缓存之外,还存在一个快照区域(即对数据库数据的一份复制),在提交事务(清理缓存)的时候,会用缓存的数据和快照的数据进行比对,如果没有发生变化不执行update语句,如果发生了变化,则执行update语句 4. 掌握increment、identity、assigned (自然主键)、uuid、联合主键等主键策略 increment: 增量为1 Identity支持自动增长类型,不为引发线程安全问题,效率较高 assiged为自然主键,开发人员测试可以指定主键 uuid是生成字符串id 联合主键,通过<composite-id name="customerID" class="cn.itcast.h_oid.e_composite.CustomerID">实现
操纵持久化对象
1. 理解Hibernate中Session对象 当session的save()方法持久化一个对象时,该对象被载入缓存,以后即使程序中不再引用该对象,只要缓存不清空,该对象仍然处于生命周期中。当试图get()、 load()对象时,会判断缓存中是否存在该对象,有则返回,此时不查询数据库。没有再查询数据库 Session中的方法总结: flush: 进行刷新缓存(此时缓存中的数据并不丢失)的操作,让缓存和数据库同步 执行一系列sql语句,但不提交事务,; commit:先调用flush() 方法,然后提交事务. 则意味着提交事务意味着对数据库操作永久保存下来。 refresh:再次刷新,让session和数据库同步,执行查询,把数据库的最新信息显示出来,更新本地缓存的对象状态. clear:清空缓存,等价于list.removeAll(); close:执行先执行commit方法提交事务,再关闭Session的缓存 2. 在hibernate中java对象的状态 Hibernate 把对象分为 4 种状态: 持久化状态, get/load/update/save/saveOrUpdate/Query对象中方法 临时状态, new对象 游离状态, 通过持久化状态转换evict/clear/close也称为脱管 删除状态. delelte Session 的特定方法能使对象从一个状态转换到另一个状态 3. 小知识点: unsaved-value 判断持久化类中的id是否和映射文件中的id相等,如果相等,执行插入操作,否则不执行。unsaved-value=0(默认值)