Hibernate知识点小结

来源:互联网 发布:php微信开发实例 编辑:程序博客网 时间:2024/05/20 10:12
什么是一级缓存?

Hibernate创建每个Session对象时,都会给该Session分配一块独立的缓存区,用于存放该Session查询
出来的对象,这个分配给Session的缓存区称之为一级缓存,也叫Sess级缓存.

为什么使用一级缓存?

Session取数据时,会优先向缓存区取数据,降低数据库访问次数,提高代码运行效率.

如何使用一级缓存?

一级缓存默认是开启的,使用Hibernate的API进行操作时自动使用.

一级缓存规则:

一级缓存是Session独享的,每个Session不能访问其他Session的缓存区.
Session的save, update, delete操作会触发缓存的更新.

一级缓存管理:

session.evict(obj) 将obj从缓存中移除.
session.clear() 清除一级缓存中所有的obj.
session.close() 关闭Session,释放缓存空间.

对象的3中状态:

在hibernate中,可以把实体对象看成有3种状态,分别是:临时态,持久态,游离态.
3种状态的转换
临时态 转换:通过new创建的对象为临时态,通过delete方法操作的对象转变为临时态,
特征:临时态的对象可以被垃圾回收,临时态的对象未进行持久化,未与session关联.
持久态 转换:通过get,load, list, iterate()方法查询到的对象为持久态;通过save, update方法操作的对象转换为持久态
特征:持久态对象垃圾回收器不能回收;持久态对象进行了持久化,与session关联,实际上持久化对象
存在于session缓存中,由session负责管理;持久态对象的数据可以自动更新到数据库中,时机是在调用.
session.flush()执行,而提交事务时会调用session.flush().ts.commit()==>session.flush()+commit.
游离态 转换:通过session的evict,clear,close方法操作的对象会转换为游离态
特征:游离态的对象可以被垃圾回收;游离态的对象进行过持久化,但是与session解除了关联.

Hibernate中批量插入数据该如何处理?

public void batchAdd(list emps){
Session session = HibernateUtil.getSession();
Transaction ts = session.beginTransaction();
for(Emp e: emps){
sessino.save(e)
}
ts.commit();
HibernateUtil.close();
}

什么是延时加载?

在使用某些Hibernate方法查询数据时,Hibernate返回的只是一个空对象(除id外属性都为null),并没有真正的
查询数据库,而是在使用这个对象时才会触发查询数据库,并将查询到的数据注入到这个空对象中.

为什么使用延时加载?

可以提升内存资源的使用率,可以降低数据库的访问次数

采用延时加载的的方法?

session.load(), query.iterate(), 关联映射中对应属性的加载.

使用延时加载需要注意的问题?

采用具有延时加载机制的操作,需要避免session提前关闭,避免在使用对象之前关闭session.
可以采用已下2种方案解决此问题:
采用非延时加载的方法,入query.get(), sessoin.list()等;在使用对象之后再关闭session.

Open session inview

在项目中,Dao只是负责查询数据,而使用数据时机是jsp解析的过程中,因此要避免在Dao中关闭session.
项目中解决这个问题的手段称之为Open session in view,在不同的技术框架下,实现Open session in view
的手段不同:
在sevlet中,使用过滤器实现,在struts2中使用拦截器实现,在spring中使用AOP实现.

延时加载实现原理:

采用延时加载方法,返回的对象类型是hibernate采用CGLB技术在内存中动态生成的类型,该类型是原实体类的子类,并在子类中重写了属性的get方法.

什么是关联映射?

若两张表具有关联关系,我们可以在实体对象和映射关系文件中配置这种关系,然后使用Hibernate操作其中
一张表时,它可以通过配置关系帮我们操作到另外一张表,这种操作就是关联映射.

关联关系操作包括?

关联查询出关系表的数据; 关联新增,修改关系表的数据; 关联删除关系表的数据.

关联映射类型?

一对多关联; 多对一关联; 多对多关联; 一对一关联; 继承关系.

一对多案例配置:以account与service为例,account 与service具有一对多关系,关系字段是service.account_id

在”一”方实体类(本案例为account实体类)中,添加集合属性,添加set, get方法
private Set services;
public Set getServices(){
return this.services;
}
public void setServices(Set services){
this.services = services;
}
在”一”方hbm文件中配置关联关系,在Account.hbm.xml中配置与Service的关联关系:



延时加载:

默认情况下,关联属性是采用延时加载的,可以通过映射关系文件中lazy属性修改
lazy=”true”,表示采用延时加载 lazy=”false”,表示不采用延时加载

抓取策略:

fetch=”join” ,表示在查询时使用连接查询,一次把对方的数据抓取过来.
fetch=”select”, 表示在查询时不使用连接查询,这是默认选项.
注:fetch=”join”, 关联属性的延时加载失败.

什么是级联操作?

Hibernate中,通过关联映射,在对一方进行增,删,改 操作时,被关联方也会进行相应的操作.

级联添加/修改

要实现级联增加/修改, cascade=”save-updaet”
级联删除
cascade=”delete”
cascade=”all” ,支持增加/修改/删除

控制反转:

在一对多关联中,使用级联新增,删除时,当操作的”一”方试图维护关联字段,然后关联字段是在多方对象中,
它会自动维护这个字段,因此”一”方没必要做这样的处理,
inverse=”true” ,表示控制反转,即交出控制权,”一”方将不再维护关联字段.
inverse=”false”,表示不控制反转,”一”方将维护关联字段,这是默认情况.

按照条件查询,条件中写的是属性名

String hql = “from Service where unixHost=?”
Session session - HibernateUtil.getSession();
Query query = session.createQuery(hql);
query.StringString(0,”192.168.1.1”);
List services = query.list();

查询一部分字段:

使用HQL查询时,query.list() 返回一个Object,数组中的值与select语句后面的属性顺序对应.

分页查询:行数0开始,跟JDBC从1开始不同.如果是JDBC, (page-1)pageSize +1

int from = (page-1)*pageSize;开始的行数,从0开始计数
query.setFirstResult(from);
query.setMaxResult(pageSize);页数

多表联合查询:

-对象方式关联; -join方式关联; -select子句关联
对象方式关联,参考如下:

String hql = “select s.id,s.osUserName,s.unixHost,a.id,a.realName,a.realName,a.idcardNo”+”from Service s , Account a where s.account.id=a.id”

Join方式关联,参考如下,注意:join时,不能直接join对象,需要join关联属性

String hql = “select s.id,s.osUserName,s.unixHost,a.id,a.realName,a.realName,a.idcardNo”+”from Account a inner join a.services s”;

select子句关联,

String hql = “select id,osUserName,unixHost,account.id,account.realName,account.idcardNo from Service”;

直接使用SQL查询(如果业务太复杂)          

String sql = “select * from service where os_username=?”
Session session = HibernateUtil.getSession();
SQLQuery query = sessino.createSQLQuery(sql);
query.setString(0,”huang”);
query.addEntity(Service.class); //指定集合中封装的类型,如果不指定,则返回List
List list = query.list();

使用Criteria查询:

Hibernate还支持使用Cirteria的API来动态拼接一个HQL,参考如下:
Criteria c = session.CreateCriteria(Service.class);
c.add(Restrictions.eq(“nuixHost”,”192.168.1.1”))
List list = c.list();

Hibernate高级特性:什么是二级缓存?

二级缓存类似于一级缓存,可以缓存对象,但是它是SessionFactory级别的缓存,由SessionFactory负责管理.
因此,二级缓存的数据都是Session间共享的,不同的Session对象都可以共享二级缓存中的数据.
二级缓存适用的场景:
对象数据频繁共享; 数据变化频率低

如何使用二级缓存:

导入ehcache.jar;
src下添加配置 ehcache.xml;
在hiber.cfg.xml中开启二级缓存,指定采用的二级缓存驱动类;
在要缓存的对象对应的映射文件中,开启当前对象的二级缓存支持,并指定缓存策略.

二级缓存策略:

只读型(read-only),缓存不会更新,适用于不会发生变化的数据,效率极高,事务隔离级别最低.
读写型(read-write),缓存会在数据变化时更新,适用于变化的数据.
不严格读写型(nonstrict-read-wirte),缓存会不定期更新,适用于变化频率低的数据.
事务型(transaction),缓存会在数据变化时更新,并支持事务,效率最低,事务隔离级别最高.

什么是查询缓存:

查询缓存依赖于二级缓存,可以理解为特殊的二级缓存,也是SessionFactory级别的,也是SessionFactory复制维护.
查询缓存可以缓存任何查到到的结果.
查询缓存是以hql为key,缓存该hql查询到的整个结果.即如果执行2次同样的hql,那么第二次执行时,此次
查询可以从查询缓存中娶到第一次查询缓存的内容.

查询缓存适用的场景:

频繁使用同样的sql做查询

如何使用二级缓存?

开启二级缓存;
在hibernate.cfg.xml中,开启查询缓存;
在查询代码执行前,指定开启查询缓存.

原创粉丝点击