hibernate和jdbc对比
jdbc缺点
1、编程的时候很繁琐,用的try和catch比较多
2、jdbc没有做数据的缓存
3、没有做到面向对象编程
4、sql语句的跨平台性很差
jdbc的优点
效率比较高
hibernate的优点
1、完全的面向对象编程
2、hibernate的缓存很牛的,一级缓存,二级缓存,查询缓存 重点
3、编程的时候就比较简单了
4、跨平台性很强
5、使用场合就是企业内部的系统
hibernate的缺点
1、效率比较低
2、表中的数据如果在千万级别,则hibernate不适合
3、如果表与表之间的关系特别复杂,则hibernate也不适合
利用hibernate实现crud的操作
步骤
1、创建一个工程
2、导入jar包
说明:
javassist包是用来创建代理对象的
代理对象的三种创建方式:
1、jdkproxy
2、cglib
3、javassist
jta: Java Transaction API,是sun公司给分布式事务处理出来的规范
3、hibernate.cfg.xml
主要的用途:
告诉hibernate连接数据库的信息,用的什么样的数据库(方言)
根据持久化类和映射文件生成表的策略
4、持久化类和映射文件
5、生成表
6、客户端
说明
hibernate.cfg.xml文件的加载
可以指定配置文件的路径,配置文件可以随意放
sessionFactory
1、hibernate中的配置文件、映射文件、持久化类的信息都在sessionFactory中
2、sessionFactory中存放的信息都是共享的信息
3、sessionFactory本身就是线程安全的
4、一个hibernate框架sessionFactory只有一个
5、sessionFactory是一个重量级别的类
session
1、得到了一个session,相当于打开了一次数据库的连接
2、在hibernate中,对数据的crud操作都是由session来完成的
transaction
hibernate中的事务默认不是自动提交的
设置了connection的setAutoCommit为false
只有产生了连接,才能进行事务的操作。所以只有有了session以后,才能有transaction
流程
内部执行原理
根据表生成持久化类和映射文件
把一个工程变成hibernate工程
把数据库引入到myeclipse中
类型
hibernate类型
这个效率比较低
java类型
该种类型的效率比较高
在hibernate内部,为了一张表,这张表中有如下的映射关系:
hibernate类型 java类型 数据库的字段的类型
string java.lang.String varchar/varchar2
对象的状态
save
该方法可以把一个对象从临时装填转换成持久化状态
get
从数据库中根据主键提取出一个对象,该对象就是一个持久化状态的对象
update
把一个对象变成持久化状态
evict
把一个对象从持久化状态转化为脱管状态
clear
把所有的hibernate中的持久化对象都转换成脱管状态的对象
flush
副本
缓存
oscache,ehcache 小型的应用
memorycache,redis,hbase 分布式的应用
一级缓存
概念:为session级别的缓存,一级缓存的生命周期和session的生命周期保持一致
位置:
操作:
get方法:
可以把对象放入到一级缓存中,也可以从一级缓存中把对象提取出来
save方法:
可以把一个对象放入到一级缓存中
evit方法:
可以把一个对象从session的缓存中清空
update方法:
可以把一个对象放入到一级缓存(session)中
clear方法:
清空一级缓存中所有的数据
close方法:
当调用session.close方法的时候,一级缓存的生命周期就结束了
二级缓存
适用的场合
公开的数据
数据基本不发生变化
该数据保密性不是很强
说明:如果一个数据一直在变,不适合用缓存
生命周期
二级缓存的生命周期和sessionFactory是一致的
位置
设置二级缓存
利用的是ehcache实现的二级缓存
1.在hibernate的配置文件中
2.指定哪个类开启二级缓存
操作
get方法,list方法可以把一个或者一些对象放入到二级缓存中
get方法,iterator方法可以提取
策略
<cache usage=""/>
read-only:对象只要加载到二级缓存以后,就只能读取了,不能进行修改。
read-write:对二级缓存中的对象能够进行读和写的操作
查询缓存
一级缓存和二级缓存都是对象缓存:就是把该对象对应的数据库表中的所有的字段
全部查询出来了,这种查询在某些场合下会让效率降低。例如:表中的字段特别多,
但是程序中所需要的字段却很少。
查询缓存也叫数据缓存:内存(页面)中需要多少数据就把多少数据放入到查询缓存中。
生命周期
只要一些数据放入到查询缓存中,该缓存就会一直存在,直到缓存中的数据被修改了,该缓存的生命周期就结束了
操作步骤
在hibernate的配置文件中,开启查询缓存
<property name="cache.use_query_cache">true</property>
总结
hibernate总共有三种缓存
一级缓存解决的问题是在一次请求中,尽量减少和数据库交互的次数,在session.flush之前,改变的是一级缓存的对象的属性。当session.flush的时候才要
跟数据库交互,一级缓存解决不了重复查询的问题。一级缓存是对象缓存
二级缓存可以把经常不改变、常用的公共的数据放入进来,可以重复查询,利用get方法和iterator方法可以把二级缓存中的数据得到。
查询缓存可以缓存数据或者对象,可以利用list方法把数据放入到缓存中。
sessionFactory.getCurrentSession
在hibernate.cfg.xml文件中
<property name="current session context class">thread</property>
如果用该方法产生session,则crud操作必须在事务的环境下运行
当执行transaction.commit 的方法时,session自动关闭
说明:
这么做相当于把session与transaction绑定在一起了。当事务提交的时候,session最好不要关闭,因为如果事务提交以后,再做关于
数据库的操作,就不能做了
关系操作
一对多的单向
inverse与casade的关系
cascade指的是级联操作,操作的是一般属性,指的是对象与对象的操作
inverse指的是关系操作,针对的就是外键
一对多的双向
当多的一方维护关系时,不会发出更新关系的update语句,而一的一方维护关系时,需要发出维护关系的update语句,所以,
一般情况下,多的一方维护关系效率比较高
多对多
多对多建立关系相当与在第三张表中插入一行数据
多对多解除关系相当于在第三张表中删除一行数据
多对多修改关系相当与先删除后增加
多对多谁维护效率都一样,看需求
lazy
需要数据的时候才要加载
类的懒加载
session.load方法产生的是代理对象,该代理类是持久化类的子类
集合的懒加载
set的延迟加载:true、false、extra
说明:
1.因为延迟加载在映射文件设置,而映射文件一旦确定,不能修改
2.延迟加载是通过控制sql语句的发出时间来提高效率的
manytoone的懒加载
对性能来说,没什么影响
抓取策略
fetch=“”
join:左外连接
select:默认的值
subselect:子查询
说明:
1.因为抓取策略的设置在映射文件中,所以一旦映射文件生成就不能改变了
2.通过发出怎么样的sql语句加载集合,从而优化效率
hql语句
单表
from Classes
select cid,name from Classes
select new 类的全限定名(cid,name) from Classes
select count(cid) from Classes
结果为Long类型的数据,该表的总行数
一对多
from Classes c inner join c.students
from Classes c inner join fetch c.students
from Classes c left outer join fetch c.students
Criteria查询
sql查询
错误分析
错误1
该Person在hibernate的映射文件中没有找到:
1、在hibernate的配置文件中没有加载对应的映射文件
2、也有可能是客户端的session的操作对象在映射文件中找不到
错误2
在映射文件中找不到该类,因为类写错了
错误3
当在hibernate内部生成sql语句的时候,要给insert语句赋值,值从属性的getter方法中得到,在拼接getter方法的时候,出错了
错误4
在执行session.get方法的时候,会利用Java的反射机制创建一个对象,利用的是默认的构造函数,所以一个持久化类中必须有一个默认的构造函数
错误5
要求主键必须在程序中进行设置
错误6
主键的生成策略支持表的主键的值的自动增长,但是该表本身没有这样的机制
错误7
错误解析:在flushing之前,保存一个临时状态的对象
前提条件:在Class.hbm.xml文件中,set集合中没有设置级联
错误8
错误原因:当一个对象从数据库中加载数据的时候,session已经关闭了
所有的数据在数据库中加载出来以后,session才能关闭