1. 循环分页或者循环进行部分读取处理数据的时候,使用 session.clear() ;
2. 对应1+n(n+1)问题使用如下解决方式:
1): 使用createcriteria进行查询(join fetch)
2):hql -> join fetch
3): 使用@fetch设置lazy
4):在@entity下使用注解@batchsize(size=5)
@batchsize 指定每次 读 取数据的数量
3. list 与 iterate 进行遍历取出数据库数据的list();
区别1)list 直接取出对象 iterate先会取出组件,需要使用才会使用
区别2)同一个session中每次执行list()取出数据时都会发送sql语句,但是iterate只会发出一条,默认会去session缓存去找;
4. 缓存,session级别的缓存称为一级缓存,每个session都有独立的一级缓存,例如多个线程同时取同一个对象数据;
解决方案:建立一个共用的总缓存(总缓存)二级缓存,如果找不到然后再到各自的session一级混村中寻找;具体操作如下:首先看缓存策略,

type : 其中memory支持缓存内存中,disk支持缓存存放硬盘中;
cluster safe :是否支持使用在集群环境;
query cache supported:是否支持查询缓存(3级缓存)
假设使用ehcacheprovider二级缓存:
1)修改hibernate.cfg.xml配置文件:
1
2
<property name="cache.use_second_level_cache">true</property>
<property name="cache.provider_class">org.hibernate.cache.ehcacheprovider</property>
2) 在/hibernate-distribution-3.3.2.ga/project/etc/ehcache.xml 配置文件拷贝到项目中;
在ehcache.xml中默认如下设置:
<diskstore path="java.io.tmpdir"/>
3
4
5
6
7
<defaultcache
maxelementsinmemory="10000"
eternal="false"
timetoidleseconds="120"
timetoliveseconds="1200"
overflowtodisk="true"
/>
maxelementsinmemory:在内存中最多缓存的对象数量
eternal: 缓存内存对象是否永久保存不删除
timetoidleseconds: 当timetoidleseconds 周期时间没有被使用过,自动清除掉;(秒)
timetoliveseconds: 缓存对象的生存时间(秒)后自动清楚;
overflowtodisk:溢出的时候是否放置在硬盘上
diskstore path:默认临时存放硬盘缓存的路径
注意:<cache name=”samplecache1″ /> 可以自定义cache名,不自定义不指定默认是用 <defaulecache ….. />
3)将类使用二级缓存,直接在@entity下使用注解 @cache 其设置如下:
常用的read_only (只读), read_write(读写)
其中@cache(region=””) 使用自定义ehcache.xml的自定义缓存策略设置 ~
4)加入ehcache的jar包,路径如下:/hibernate-distribution-3.3.2.ga/lib/optional/ehcache/ehcache.jar
加入 commons-logging.jar包
1. 放入二级缓存如下规则:
a) 经常访问 b) 不经常改动(改动不大) c) 数据不是很大 例如用户权限;
2. load 默认使用二级缓存,iterate 默认使用二级缓存
3. list 默认往二级缓存加数据,list查询的使用不使用缓存
4. 如果要 query 查询语句使用二级缓存,需要打开查询缓存(同样的重复的查询!)
1) hibernate.cfg.xml配置文件加入配置:
<property name=”cache.use_query_cache”>true</property>
2) 使用query的setcachable(true) 方法指明使用二级缓存 ;
5. 缓存算法:lru 、 lfu 、 fifo
lru: 最近最少被使用的; (时间)
lfu: 使用率比较少的;(次数)
fifo:按照数据从0开始拿走(堆栈)
设置方法:在ehcache.xml继续设置一个参数: memorystoreevictionpolicy=”lru”
6. 事务隔离机制(为了避免事务并发出现的问题)
1. read-uncommitted : 能读取没有提交的数据; 【会出现脏读等问题,一般不设置此种】
2. read-committed : 只有提交后才读;hibernate建议使用!【能解决脏读但会出现不可重复读和幻读问题(手动解决)】
3. repeatable read : 加锁;(mysql默认使用 repeatable read )
4. serializable : 序列化,解决任何问题,但是效率最低;
mysql 支持这四种事务隔离机制; 事务隔离级别越高效率越慢~
使用 select @@tx_isolation; 查询事务隔离机制;
设置隔离机制: set session tx_isolation=’xxx’;
hibernate解决并发事务方案:使用hibernate悲观锁和乐观锁进行设置;
1)事务机制的值为1,2,4,8 (ps. 二进制为0001 ,0010,0100,1000 这样算法效率高)
1.a)使用悲观锁:(依赖于数据库的锁 解决 repeatable read问题)
在读取load数据的时候,加入第三个参数::
session.load(xxx.class, 1,lockmode.xxx);
lockmode的值如下:
一般只设置lockmode.upgrade
原因:
none: 无锁的机制,transaction结束时切换到此模式;
read :在查询的时候 hibernate会自动获取锁;
write ,insert, update hibernate 会自动获取锁;
以上 3种锁的模式是hibernate内部使用的;
upgrade—nowait ->是oracle数据库 支持的锁;
1.b)使用乐观锁:(程序内使用字段version进行加锁,与数据库没有关系)
可以定义一个version属性,然后在getversion上使用注解 @version
注意:当并发的时候会报错,那么找个错误交给我们自己来处理;
悲观与乐观:悲观一开始就进行加锁,不论是否有其他事务来同时并发;但是乐观锁则不进行直接加锁,而是等待更新时候进行检查对比下,如果与去之前version不一致那么更新下即可;乐观锁效率高;