hibernate-性能优化(3种缓存)-19

来源:互联网 发布:js数字转化成中文数字 编辑:程序博客网 时间:2024/06/05 02:24

1. 注意session.clear()的运用,尤其是在不断分页循环的时候

a.在一个大集合中进行遍历,遍历msg,取出其中含有敏感字体的对象
b.另外一种形式的内存泄漏 // java有内存泄漏吗? 代码级别没有,实际操作中会有,例如:打开数据库、读文件不关闭链接,hibernate的分页没有进行session.clear()

2. 1+N问题(典型面试题)

例如:一个Category,对应一个topic,Category和topic各有10条,当想取出所有topic时,默认hibernate会发出1+10(取10个category)条sql语句,这种情况被称为1+N问题。

a和c根据具体情况使用

解决方案: a. 把fetchtype设成lazy
b.@BatchSize(size=5) 设置在Category的类名上(此方案不特别好)
c. join fetch
使用session.createCriteria(Topic.class),默认使用join fetch,只发出一条sql语句

3. list和iterate(不太重要,一般情况下用list(),面试可能会问)

a. list取所有
b. iterate先取ID,等用到的时候再根据ID取对象
c. session中list第二次发出,仍会查询数据库
d.iterate第二次,首先找session缓存

4. 一级缓存、查询缓存、查询缓存(面试题)

a. 什么是缓存
经常被访问的数据,存放到内存中,便于访问
b. 什么是一级缓存
session级别的缓存
e.g. 同一个session,load某条数据两次,但hibernate只发出一条sql语句(即只查询一次数据库),因为第二次已从缓存中取得结果
不同的session,各load某条数据一次,hibernate还是发出两条sql语句,它们的session缓存不共享
c. 什么是二级缓存
SessionFactory级别的缓存,可以跨越session存在(让多个session共享同一块缓存)
什么样的数据适合放入二级缓存?e.g. 组织机构、用户权限等
1. 经常被访问
2. 改动不大不会经常改动
3. 数量有限
d. 打开二级缓存
hibernate.cfg.xml中设定

<property name="cache.use_second_level_cache">true</property>        <property name="hibernate.cache.region.factory_cl‌​ass">org.hibernate.cache.ehcache.EhCacheRegionFactory</property>

添加ehcache.xml文件

... <defaultCache        maxElementsInMemory="10000"        eternal="false"        timeToIdleSeconds="120"        timeToLiveSeconds="120"        overflowToDisk="true"        />...

给需要二级缓存的对象,配置二级缓存

@Entity@Cache(usage =CacheConcurrencyStrategy.READ_WRITE  //  放到二级缓存中可读可改       ,region = "sampleCache1") // 二级缓存的名字  对应ehcache.xml文件中的名字public class Category {    private int id;    private String name;    @Id    @GeneratedValue    public int getId() {        return id;    }    public void setId(int id) {        this.id = id;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }}

e. load默认用二级缓存,iterate默认用二级缓存
f. list默认向二级缓存加数据,但查询的时候不用二级缓存(因为查询的条件不同,没发用;如果查询条件相同时,可以从二级缓存查,这种缓存被称为查询缓存(三级缓存))
g. 如果query需要用二级缓存,第一步:那么需要打开查询缓存

        <property name="hibernate.cache.use_query_cache">true</property>

第二步:需要在查询的时候设置一些参数
Query q = session.createQuery(” from Category “);
(List)q.setCacheable(true).list();

//  只发一条sql语句@Test    public void testQueryCache(){        Session session = sf.getCurrentSession();        session.beginTransaction();        Query q = session.createQuery(" from Category ");        List<Category> categories = (List<Category>)q.setCacheable(true).list();        for(Category c:categories){            System.out.println(c.getName());        }        session.getTransaction().commit();        Session session2 = sf.getCurrentSession();        session2.beginTransaction();        Query q2 = session2.createQuery(" from Category ");        List<Category> categories2 = (List<Category>)q2.setCacheable(true).list();        for(Category c:categories2){            System.out.println(c.getName());        }        session2.getTransaction().commit();    }