- hibernate是一个持久层框架,是开源O/R映射框架,它在数据库和对象的两种不同的模型之间建立关联,并提供了利用面向对象的思想来操作关系型数据的接口。
- 什么是ORM?
ORM(Object Relationship Mapping)对象关系映射
编程语言 : OOP面向对象思想语言
数据库 : rdbms关系型数据库管理系统(表,字段,主键,外键)
建模工具——power designer
版本控制工具——svn
ORM是一种为了解决面向对象与关系数据库存在的互不匹配的现象的技术。简单的说,ORM是通过使用描述对象和数据库之间映射的元数据,将java程序中的对象自动持久化到关系数据库中。本质上就是将数据从一种形式转换到另外一种形式。
- 编写代码顺序
- 事务(Transaction)(重点)
事务是用户自定义的一个操作序列,是最小的执行单元,不可再分。一个逻辑工作单元必须有四个属性,称为 ACID(原子性、一致性、隔离性和持久性)属性
a.原子性
事务执行不可再分,要么全部执行,要么全部不执行。
c.一致性
事务在执行前与执行后保持一致的状态。
i.隔离性
两个或多个事务进行时互不影响。
d.持久性
事务提交之后,它对于系统的影响是永久性的,无法回滚。
- 数据源配置
- hibernate的属性配置
- 加载hbm.xml映射文件
- 如何创建Session;
- Configuration配置文件
- SessionFactory工厂
- Session核心接口
- Session是什么?
Session是应用程序与hibernate之间的会话,主要作用是用来操作经过映射的实体对象;同时session也是一个容器,可以临时保存po对象的引用。也就是说session可以缓存数据库的数据。
- PO (经过映射的实体对象)对象的生命周期 (状态)(重点)
- 瞬时状态:从未持久化,也没有纳入session的管理时的状态
- 持久状态:纳入到session的管理
- 游离状态:曾经是持久化对象,当前不与session关联
- Session常用的方法
- Flush:刷新,与数据库同步
- save:插入
- persist:插入(不可自设置逐渐值)
- Load
- get:根据oid获得对应的po对象
- evict:从session中移除一个po对象
- clear:从session中移除所有的po对象
- close:关闭session,并从session中移除所有的对象
- update:修改游离态的对象(将游离态对象转为持久态)
- delete:删除
- 方法get与load的区别
作用:均为根据oid获取对应的实体。
区别 : (1)get会立即执行查询语句,得到的是真实对象,如果找不到,则返回null;(立即加载)
(2)load不会立即执行查询语句,返回一个代理对象,当需要访问这个实体时,才会发送sql,如果这是实体不存在,则抛出ObjectNotFoundException异常.(懒汉式加载),可以在hbm.xml文件中设置lazy属性为false。
相同点:查询时先查找缓存,如果找到,无论是真 实对象还是代理对象,都不会再发送sql.
- 主键的设计注意事项
- 每个表里都应该有主键,与之对应的实体也应该有个oid
- 主键的设计应该是无意义的,最好是数字
- hibernate的主键生成方式主要有:
- increment:自增加(最大值+1);(缺点:并发问题,多个session同时操作数据库,因此其仅适合)
- identify:mysql,ms sqlserver,db2支持,不支持Oracle数据库
- sequence:序列
- hilo:采用高低算法生成,保证不重复
- native:先identify.sequence,hilo
- assigned:手动分配
- uuid:生成128位的码,返回字符串
- foreign:外键(一对一)
- 关系映射的学习方法
- 表之间的关系(重点)
- 类之间的关系(重点)
- 映射文件的配置
- PowerDesigner(建模工具)
概念E-R图:不依赖于具体的数据库(优先)
物理E-R图:与数据库相关,可以直接生成sql语句;
步骤
a.新建一个概念E-R图
b.建立关系后转成物理E-R图
c.生成sql语句(oracle时,要转成大写)
- 一对多映射(常用!重点)
- 表关系:主外键
- 类关系:Student,Tclass;
- 映射文件:
<hibernate-mapping>
<class name="com.oracle.po.Tclass" table="TCLASS" schema="SCOTT" dynamic-insert="true" dynamic-update="true">
<!--这两个属性为设置动态sql,使在执行插入,修改操作时,免去空值的问号-->
<id name="classno" type="java.lang.Integer">
<column name="CLASSNO" precision="4" scale="0" />
<generator class="increment"></generator>
</id>
<property name="classname" type="java.lang.String">
<column name="CLASSNAME" length="40" not-null="true" />
</property>
<property name="teacher" type="java.lang.String">
<column name="TEACHER" length="30" />
</property>
<set name="students" inverse="true"order-by="stuno asc/desc"><!--此属性代表查询结果按指定列排序-->
<key>
<column name="CLASSNO" precision="4" scale="0" />
</key>
<!--一对多映射标记 -->
<one-to-many class="com.oracle.po.Student" />
</set>
</class>
</hibernate-mapping>
Student.hbm.xml
Tclass.hbm.xml
<many-to-one>
<set>
<key>
<one-to-many>
</key>
</set>
- <set>标记的使用
- cascade属性="save-update、delete、all":
代表级联操作,默认没有级联操作。指的是对主对象执行一个操作,从属对象也执行相同的操作,常用的取值由delete、save-update、all。
inverse:
反转控制,关联的对象中,哪个对象是主控端(维护他们的关系),不影响结果(主要影响sql语句的数量),但影响性能。
- 多对多映射
- 表关系:中间表,拆分成两个一对多
- 类关系:一个类中包含另一个类的Set集合
- 映射文件:
- set中包含key及many-to-many子标记
- 在多对多的关系修改时,需注意inverse的值是true还是false,inverse代表关系维护方是自己还是中间表,在为true时代表关系由对方来维护,自行的修改操作无效,当为false时代表关系由自己来维护,自行修改有效。
- 通过当前对象的get、set方法来获得集合,并调用clear方法清空,但需要设置set标记的inverse属性位false才可以。
- 一对一映射(用的较少,了解)
- 相同主键:两表主键相同
- 表关系:从表使用主表的外键作为主键,同时也为主键;pd可以通过继承来实现(只继承主键)
- 类关系:一个类中有另一个类的引用
- 映射文件:
- 唯一外键:一对多的特殊形式
- 表关系:
- 类关系:
- 映射文件:需要修改
- 主表--<one-to-one name="driverlicence" property-ref="driver"></one-to-one>
- 从表--<many-to-one name="driver" column="driverno" unique="true" not-null="true"></many-to-one>
- 相同主键:两表主键相同
- 日期类型的映射
- 类中可以为java.Util.Date;
- 映射文件文件中可以使用java.sql.Date、Time、Timestram
- 数据检索
- Critiria条件查询(掌握)(特点:完全面向对象的思想)
- QBC-Query By Critiria
- Critiria条件查询(掌握)(特点:完全面向对象的思想)
Criteria c = session.createCriteria(Emp.class);
//分页查询
c.setFirstResult(10);
c.setMaxResults(3);
//模糊查询
c.add(Restrictions.like("ename","%A%")).add(Restrictions.between("sal",1000.0,5000.0));
//升降序排列
c.addOrder(Order.desc("sal"));
List<Emp> list = c.list();
- QBE-Query By Example
Emp e = new Emp();
e.setJob("MANAGER");
c.add(Example.create(e));
c.list();
- NativeSQL条件查询
本地的sql只能针对当前的数据库编写sql语句,并不兼容;
可以通过SQLQuery.addEntity(Emp.class)方法,将本地sql查询出的数据,封装成一个po对象;
- hibernate优化之加载策略:
所有策略中,执行语句的时间不同,语句不同
- 延迟加载:
- lazy,可以设置 class和set标记的lazy="true",设置 class和set标记的lazy="false"时load和get功能一样,不会再生成代理对象
- 可以设置po关联对象
- 立即加载:两条语句
- 预先加载:一条语句(表连接)
- 批量加载:一次加载多个数据
- HQL
- Hibernate Query Language:hibernate最建议使用的查询方式,功能强大,语法简单,语法与sql相似;支持:条件、排序、分组、子查询、统计、表连接、投影等。
- HQL的查询方法(注意:HQL中表名必须首字母大写!)
from Emp
- Object obj = query.uniqueResult() 只查询单条
- List<Emp> elist = query.list();
- Iterator<Emp> it = query.iterate();用的较少
- 条件查询
- form Emp e where e.job="MANAGER"
- form Emp e where e.job=? query.setString(0,s);
- form Emp e where e.job=:job query.setString("job",s );
- 排序
form Emp e where e.job="MANAGER" order by e.empno
- 投影
查询部分属性,默认每条记录对应是一个Object[],也就是说,返回的List的类型是List<Object[]>,可以通过创建构造方法的凡是来将返回的多个属性封装成多个对象。
Query query = session.createQuery("select new Emp(e.empno,e.ename,e.job,e.sal) from Emp e where e.job=? and e.sal>:sal");
- 聚合函数
List<Object[]> list=session.createQuery("select e.job,count(*),avg(e.sal) from Emp e group by e.job").list();
返回Object[]数组
- 表连接(重点)(常用)
- 共四种:
- Inner join
- Left join
- Right join
- Full join
- fetch运算符
- 作用:可以将查询到的结果组装到一个对象中.即提高了执行效率,由方便了操作;
- 共四种:
一般结合着left join fetch使用,因此称它为迫切左外联。
- 关于一对多查询结果的去重的方法
- Distinct
- 通过LinkedHashSet集合
List<Emp> list = session.createQuery("from Emp e left join fetch e.dept order by e.empno").list();
Set<Emp> set = new LinkedHashSet<Emp>(list);
list = new ArrayList<Emp>(set);
- 表连接在hibernate中的语法分类
- 显式连接:明确的写出join关键字
- 隐式连接:不需要写join关键字
List<Dept> list = session.createQuery("from Dept d where d in(select e.dept from Emp e where e.dept is not null)").list();
- 命名HQL
在hbm.xml文件中,在</class>标签下,增加<query>标记,通过session.getNamedQuery();获得此查询。
例如:
Dept.Hbm.xml: <query name="selectDept">
<![CDATA[from Dept d where d.deptno<:deptno]]>
</query>
Test: Query query = session.getNamedQuery("selectDept");
- 原生的SQL
session.createSQLQuery("select * from emp").addEntity(Emp.class).list();
当进行大数据量操作时最好使用原生的SQL进行操作,执行的语句较少,HQL通过先查询后修改的方式性能很低,并且浪费内存。
- API复习
- SessionFactory
- Session
- Transaction
- Criteria
- Query
- SQLQuery
- 性能优化
- 数据加载方式(延迟加载优先)
- 延迟加载(lazy):可以设置class和set标记的lazy="true"
- 立即加载:与lazy相反,调用get,load时,立即发送查询语句;可以设置class和set标记的lazy="false"
- 预先加载:立即执行sql,只是采用一条表连接的sql语句在set标签设置fetch属性为join
- 批量加载:一次加载多条数据,性能较低。在set标签的batch-size属性设置加载数据条数
- 批量操作
- hql执行update及delete
- sql执行update及delete,insert(优先)
- Session.doWork()方法;(类似于回调方法,作为一个接口,使程序员可以调到原生的JDBC API,除非是在hibernate框架的效率无法满足时才考虑使用)
- hibernate的二级缓存
- 数据加载方式(延迟加载优先)
hibernate中提供了两级缓存;缓存可以节省工作量,提高性能,在缺点是有可能出现数据更新不一致的问题。因此是否使用缓存应视情况而定。
- 一级缓存:session级别(必须使用)
- 二级缓存(Second Cache):sessionFactory级别的(需要配置),二级缓存中放置的东西最好是不轻易变化或不变化的数据。并且是所有session共享的数据。
- 加包:E:\java视频\Video\第三阶段\0909hibernate\hibernate-release-4.2.13.Final\hibernate-release-4.2.13.Final\lib\optional\ehcache
- 增加一个ehcache.xml的配置文件
- 在核心配置文件中开启二级缓存,及使用配置ehcache对应的工厂
- 在映射文件中使用二级缓存<cache usage="read-only"/>
- hibernate和Mybatis的对比
- hibernate的优点
- 逆向工程比较完善
- 具有级联操作,MyBatis并不具备级联(cascade属性="save-update、delete、all")
- 拥有HQL和方言设置,方便数据库移植
- 具有注解方式,编码更加简洁
- 可通过PO类生成数据库表
- 具有二级缓存机制,但需要手动配置
- Hibernate的缺点
- 作为重量级框架,不够灵活
- Mybatis的优点
- MYbatis是轻量级框架,比hibernate更加灵活。
- hibernate的优点
常用框架之Hibernate
最新推荐文章于 2018-08-01 10:44:04 发布