3、list和iterate不同
a)list取所有
b)literate先取ID,等到用的时候根据ID取对象
c)session中list第二次发出,仍会到数据库查询。
d)iterate第二次,先找session级缓存。
4、一级缓存和二级缓存和查询缓存
a)什么是缓存
可以在内存中开辟一块空间,把本来在数据库中读的东西 放在内存中,这样读的时候直接从内存中读取。
b)一级缓存
session级别的缓存。一个session不能取另一个session的内容。
c)二级缓存
sessionFactory级别的缓存
弄一个大的缓存,把所有的session全部放在里面
适合场景:
经常被访问,改动不大,数量有限。比如用户的权限,组织机构。
用法:在需要接入缓存的类的上面加@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)//表示既能读也能改
loadt默认使用二级缓存,iterate默认使用二级缓存
d)查询缓存
list默认使用二级缓存加数据,但是查询的时候不用,也就是说,在内存中有对象,但是会去从数据库中查询。
原因是每次执行query查询的时候可能语句不一样,或许查询的数据部分不在缓存中。如果第一次查的语句和第二次
查的一样,会去内存中查,这就是查询缓存。
使用方法:
i.在配置hibernate.cfg.xml中加入
<property name = "cache.use_query_cache">true</property>
当然缓存的配置中必须开启缓存。
ii.session.createQuery("").setChacheable(true).list();
iii.如果使用两次session,不会发出两条查询语句,则证明查询缓存开启。
e)缓存算法
内存里的对象一旦满了,新来的对象会把哪个对象替换掉?
LRU,LFU,FIFO
LRU:Least Recently Used,最近很少被使用。
LFU:Least Frequently Used ,最近使用频度最低替换, 比如说最近访问100次,哪个命中率最低,哪个被替换掉。
FIFO:First In First Out ,谁先进来谁先出去。
设置:
ehcache.xml中在<cache>标签中设置memoryStoreEvictionPolicy=”LRU“
5、事务的并发处理
a)什么是事务?
要么都完成,要么都不完成。
b)常见特性:具有ACID特性
i.原子性
ii.一致性
iii.独立性
iv.持久性
c)事务并发可能出现的问题
i.第一类丢失更新(数据库只要支持事物,这个问题就可以解决)
ii.脏读(*)
读了别的事务没有提交的数据
iii.不可重复读(*)(用在更新操作)
同一个事物前后读的数据不一样,被另一个事务影响了。
iv.第二类丢失更新(不可重复读的特殊情况)
v.幻读(插入和删除的操作)(*)
同一个事务前后读的数据不一样,被另一个事务影响了,在读的过程中,
另外一个事务可能插入一条新的纪录。
d)解决方案
i.让它不要并发
数据库的事务隔离机制
MySQL中查询事务机制:select @@tx_isolation.
serial解决一切问题,但是不设这个级别,当检查问题时才会使用。
我们一般使用的是read-committed,避免脏读,并发性也比较好,通过其他手段
设定hibernate的事务隔离级别
hibernate.connection.isolation=2
但是这样做还是会出现不可重复读,幻读的问题
ii.在hibernate中使用悲观锁解决repeatable read 的问题(依赖于数据库的锁)
一般情况下查询总数,不会在一个session中查询,所以暂时不用解决幻读的问题,
实际应用中不太用到悲观锁。
iii.在load第三个参数中加LockMode.UPGRADE
iv.悲观锁是为了防止别人修改,直接加把锁,乐观锁是设置字段,前后进行对比,查看
是否一致,如果一致,则证明没有被改过,如果不一致,则进行响应的处理。
v.乐观锁的实现
增加@version注解,如果有人更新,则会报错,然后根据需要做出相应的解决。