hibernate学习笔记四

来源:互联网 发布:阳光科学发声法知乎 编辑:程序博客网 时间:2024/05/18 17:01

用in还是exists
用exists,原因是效率比in高

使用本地sql
SQLQuery q = session.createSQLQuery("select * from category limit 2,4").addEntity(Category.class);---转换成Category对象
List<Category> categories = (List<Category>)q.list();

HQL语言详细使用的时候查一下hibernate_2400和2500

q.executeUpdate();
q.list();
q.uniqueResult() 返回的是唯一的结果

有经验的项目经理要求只用某一种查询方式
1.native sql 》HQL 》EJBQL 》QBC(QUERY by Criteria) >QBE(Query By Example)
Criteria->Criterion
Criteria c = session.createCriteria(Topic.class) //from Topic 为这个类创建一系列的约束
 .add(Restrictions.gt("id", 2)) //greater than = id > 2
 .add(Restrictions.lt("id", 8)) //little than = id < 8
 .add(Restrictions.like("title", "t_"))
 .createCriteria("category")
 .add(Restrictions.between("id", 3, 5)) //category.id >= 3 and category.id <=5;
for(Object o : c.list()) {
 Topic t = (Topic)o;
 System.out.println(t.getId() + "-" + t.getTitle());
}

性能优化
1.注意session.clear()的运用,尤其在不断分页循环的时候
a)在一个大集合中进行遍历,遍历msg,取出其中含有敏感字样的对象
b)另外一种形式的内存泄露
在同一个session中不断处理对象,需要手动清除session的缓存对象,应该每处理完50条调用session.clear()
java有内存泄露吗?语法级别没有,但是对于资源的使用有可能造成该问题,像打开文件。上面这个session场景可能就会造成内存泄露

2.1+N问题 ----典型的面试题
a)lazy
b)BatchSize
c)join fetch
session.createCriteria默认就解决了1+N的问题
一对多或者多对一经常会出现,只要fetch=FetchType.EAGER,本来一条sql能解决问题,结果用了1+N条sql才解决
三种解决方案:
<1>fetch设置为lazy ----N条sql语句用到的时候发出,不用的时候不发出
<2>BatchSize的使用位置,一定程度上帮你提高效率,对于解决这个问题不太正规----这种方法该取的还是要取,只是每次取设定的条数来减少取的次数
如N=10的时候BatchSize为5的话,会分为2次取,每次取5条
<3>from Topic t left join fetch t.category c ---这个类似于使用session.createCriteria

2012-3-19
3.list和iterator不同之处----不太重要,一般用list就可以,两个都不允许用join
Iterator在hasNext()为false的时候不允许调用next()否则报错
a)list取所有----同一个session中执行2遍就会发2次sql语句
b)iterator先取id,等用到的时候再根据id取对象(用的不多,会利用session级缓存,对程序精益求精)
c)session中list第二次发出,仍会到数据库查询
d)iterator第二次,找到id,然后首先找session级缓存


4.一级缓存、二级缓存和查询缓存
查询缓存,只有在两个查询语句一样的情况下,才能起作用。
a)什么是缓存
b)什么是一级缓存,session级的缓存
c)什么是二级缓存,sessionFactory级别的缓存,可以跨越session存在
(1)经常访问的
(2)改动不大,不会经常改动
(3)数量有限

d)打开二级缓存
i.hibernate.cfg.xml设定:
 <property name="cache.use_second_level_cache">true</property>
 <property name="cache.provider_class">org.hibernate.cache.EhcacheProvider</property>
ehcache需要有自己的配置文件
改动频繁不适合放缓存.(1)经常访问的(2)改动不大(3)数量有限
比如:用户的权限
二级缓存中有一种特殊的缓存,查询缓存,重复查询才能使用的缓存
ii.@Cache注解
e)load默认使用二级缓存,iterator默认使用二级缓存
f)list默认往二级缓存加数据,需要打开查询缓存,查询的时候不用
g)如果要query用二级缓存,需要打开查询缓存
i.<property name="cache.use_query_cache">true</property>--------查询缓存是依赖于二级缓存的,要先打开二级缓存再打开查询缓存
ii.调用Query的setCachable(true)方法指明使用二级缓存--------list()方法可以使用查询缓存
h)缓存算法:(纯为了面试)----内存中对象满了以后,新来对象后怎么处理原来的对象,哪个对象被拿走
i.LRU,LFU,FIFO
<1>Least Recently Used  最近很少使用
<2>Least Frequently Used (命中率高低) 
<3>First In First Out  先进先出
ii.memoryStoreEvictionPolicy="LRU"(ecache)

5.事务并发处理
a)事务:ACID
<1>Atomic 原子性
<2>Consistency 一致性
<3>Itegrity 独立性
<4>Durability 持久性

b)事务并发时可能出现的问题
脏读:读到了别的事物还没有提交的数据
不可重复读:在两次读数据间,数据被其他事务改变了
幻读:插入和删除的操作,读的过程中,另外一个事物插入了一个新记录

c)数据库事物隔离机制
<1>查看java.sql.Connection
<2>1.read-uncommitted 2.read-committed 4.repeatable-read 8.serializable
a) 0001 0010 0100 1000
b) C    R    U     D
c)C|U 0101
d)0101 & 0001 == 0001
java注重的是开发效率,而不是程序效率
oracle支持2种 mysql支持4种
mysql:select @@tx_isolation;
read-uncommitted:能够读那些没有提交的数据,会产生dirty-read,phantom-read,non-repeatable read问题
read-committed:提交了之后才能读出来,不会出现dirty-read,会出现non-repeatable read,phantom-read
repeatable-read:可重复读,读出来之后加一把锁,该事物用完了才能被其他事物更新
serial:解决一切问题
----------效率从上到下变低,安全从下到上变高

解决phantom read只能serial

d)设定hibernate的事务隔离级别
<1> hibernate.connection.isolation=2-----如果不设置,那么依赖于数据库read-committed
<2> 用悲观锁解决repeatable read的问题(依赖于数据库的锁)
 1.select ... for update;
 2.load(xx.class, i, LockMode.UPGRADE)
 load()第三个参数用LockMode.UPGRADE,几个锁中只能使用这个锁

悲观,先上把锁,不让别人更新,使用数据库的锁
乐观,做一个标记,然后运行,改变值前检查标记是否变化,如果没有变化,就正常更新。如果有变化,就重新读数据,重新计算。
加一个@Version的字段