8.Hibernate性能优化

性能优化

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

    a) 在一个大集合中进行遍历,遍历msg,取出其中额含有敏感字样的对象

    b) 另外一种形式的内存泄漏( //面试题:Java有内存泄漏吗?语法级别没有,但是可由java引起,例如:连接池不关闭,或io读取后不关闭)

  2.1+N 问题(典型的面试题)

    举例:当存在多对一关系时,多的一方默认是可以取出一的一方的

      @ManyToOne 中 默认为fetch=FetchType.Eager

      当load多的一方时,也会加载一的哪一方,会造成执行不必要的SQL语句

    解决办法,以下几种:

      a) @ManyToOne(fetch=FetchType.LAZY)

      //当多对一(@ManyToOne)已经设定属性" fetch=FetchType.LAZY "时

      //只有当需要时(如:t.getCategory().getName()时)才会去获取关联表中数据 可以解决N+1问题

      b) @BatchSize

      //在与查询表(此例中为Topic类)关联的表类(此例中为Category类)头处加@BatchSize(size=5)

      //表示每次可查出5条记录 从而减少了select语句的个数 

      c) join fetch  

      //修改hql语句为--"  from Topic t left join fetch t.category c 

      d) QBC

      //原理和上面那条是一样的,使用QBC的 createCriteria(*.class)执行查询 也可避免N+1问题

  

  3.list 和 iterate 不同之处( //主要为了面试)

    a) list 取出表中所有数据构成对象

    b) iterate 先取ID,等用到的时候再根据ID 来取对象

    c) session 中list 第二次发出,仍回到数据库查询

    d)iterate 第二次,会先去找 session 缓存

Hibernate 缓存机制

前面Hibernate中持久化对象的三种状态有提到,处于Persistent状态的对象的标志是 缓存中也有这个对象

缓存中类似于一个一个的键值对,key 为 id,然后value为这个缓存的对象

当想要对该对象进行读写时,会先去查缓存,

/*一级缓存和二级缓存和查询缓存*/

  一级缓存:session级的缓存,每个session拥有自己的session缓存,不同session的session缓存不能共享

  二级缓存:sessionFactory级的缓存,所有的session都可以去访问二级缓存

  查询缓存:相同的SQL语句只执行一次

  当缓存的对象  1.经常被访问  2.不会经常改动  3.数量不大  时使用二级缓存

  打开二级缓存(两步):

    1.在 hibernate.cfg.xml中设定:

1         <property name= "cache.use_second_level_cache">true</property>
2         <property name="cache.provider_class">org.hibernate.cache.EhCacheProvider</property>

    [email protected] 注解 (由hibernate扩展提供)

     @Cache (usage=CacheConcurrencyStrategy.READ_WRITE)

    (为某个类开启二级缓存,针对该类的对象进行的 读写操作,会创建二级缓存)

    注:使用EhCache 二级缓存需要导入 ehcache-1.2.3.jar 及 commons-logging-1.0.4.jar 包

 注: 

  1.load 默认使用二级缓存,iterate 默认使用二级缓存

  2.list 默认往二级缓存加数据,但是查询的时候不使用

  意思是:session.createQuery("from Category").list();  会将查出来的数据加到缓存中,但是不会去缓存中查询

  3.可以使用<property name="hibernate.cache.use_query_cache">true</property>来打开查询缓存,默认为关闭,

  查询缓存来标识某个查询使用缓存,当执行同一条SQL语句时,就不会再去数据库找,也是从缓存中去找该语句

  在打开了查询缓存之后,需要注意,调用query.list()操作之前,必须显示调用query.setCacheable(true)

  例如:session.createQuery("from Category").setCacheable(true).list();

  注:查询缓存只对query.list()起作用,query.iterate不起作用,也就是query.iterate不使用

  

  4.缓存算法(新的缓存对象要进来,怎么替换):(面试)

  LRU LFU FIFO

  1.Least Recently Used  最近最少使用的被替换

  2.Least Frequently Used  命中率高低  使用频率最低的被替换

  3.First In First Out  按顺序替换

  在ehcache.xml中配置   memoryStoreEvictionPolicy="LRU"

事务并发处理

a) 事务:ACID
  Atomic Consistency Itegrity Durability

b) 事务并发时可能出现的问题:

  1.脏读  (读到了另一个事务在处理中还未提交的数据)

  2.不可重复读 (在事务A的执行过程中,事务B进行了开启,对列中的数据进行修改和提交,

  导致事务A在事务B执行前读取的数据和事务B执行后读取的数据不一致)

  3.虚读 (在查询某一条件的数据时,开始查询后,别人又加入或删除某些数据,再读取时与原来的数据不一样了,

  和 不可重复读 类似,不过不可重复读针对的列里面数据的修改,而幻读针对的是列整体的增删)

c) 数据库事务的隔离级别

  1------read-uncommitted

  2------read-committed

  4------repeatable read

  8------serializable

  前面的数字为Hibernate的事务隔离级别对应的数字

  为什么要使用1 2 4 8 而不是 1 2 3 4

  1=0000  2=0010  4=0100  8=1000  位运算效率高

  

  read-uncommitted(允许读取未提交的数据) 会出现dirty read, phantom-read, non-repeatable read 问题

  read-commited(读取已提交的数据 项目中一般都使用这个)不会出现dirty read,

  因为只有另一个事务提交才会读出来结果,但仍然会出现 non-repeatable read 和 phantom-read

  /*使用read-commited机制可用悲观锁 乐观锁来解决non-repeatable read 和 phantom-read问题*/

  repeatable read(事务执行中其他事务无法执行修改或插入操作     较安全)

  serializable  解决一切问题(顺序执行事务 不并发,实际中很少用)

  如何设定Hibernate 的事务隔离级别(使用hibernate.connection.isolation配置 取值1、2、4、8)

    1.hibernate.connection.isolation = 2 (如果不设 默认依赖数据库本身的级别)

    2.用悲观锁解决repeatable read的问题(依赖于数据库的锁(select... for update))

    hibernate使用Load进行悲观锁加锁    session.load(Inventory.class, 1, LockMode.UPGRADE);   在生成select语句时,会加上for update 进行使用悲观锁

      a)LockMode.None   无锁的机制,Transaction结束时,切换到此模式

      b)LockMode.read   在査询的时候hibernate会自动获取锁

      c)LockMode.write  insert  update hibernate 会自动获取锁

      d)以上3种锁的模式,是hibernate内部使用的(不需要设)

      e)LockMode.UPGRADE_NOWAIT   是 ORACLE 支持的锁的方式

  3.乐观锁(其实不是锁,是一种冲突检测机制)

  实体类中增加version属性 (数据库也会对应生成该字段初始值为0),并在其get方法前加入 @Version 注解

  则在操作的过程中每更新一次该行数据则version值 加 1,即可在事务提交前判断该数据是否被其他事务修改过

  (提交事务时,通过对比内存中的version值和数据库中的version值)

  注:乐观和悲观的区别:

  1.悲观锁比较悲观,觉得会有并发的情况发生,所以提前加了一把锁,

  2.乐观锁比较乐观,不着急加锁,而是先判断是否出现了并发访问的情况,如果出现了,再做相应的处理

          

时间: 2024-10-09 22:07:56

8.Hibernate性能优化的相关文章

Hibernate性能优化之EHCache缓存

像Hibernate这种ORM框架,相较于JDBC操作,需要有更复杂的机制来实现映射.对象状态管理等,因此在性能和效率上有一定的损耗. 在保证避免映射产生低效的SQL操作外,缓存是提升Hibernate的关键之一. 加入缓存可以避免数据库调用带来的连接创建与销毁.数据打包拆包.SQL执行.网络传输,良好的缓存机制和合理的缓存模式能带来性能的极大提升,EHCache就提供了这种良好的缓存机制. 在考虑给系统加入缓存进行优化前,复用SessionFactory是Hibernate优化最优先.最基础的

Hibernate性能优化

性能优化 1.Session.clear()的应用 不断分页循环的时候,使用clear()方法. Java中的内存泄漏: 如果使用java打开某一个资源后,一定要关闭,否则就有可能导致内存泄漏.比如:使用java打开一个文件,实际上是java调用了C,C调用了windows底层的API,如果不手动将资源关闭,C语言必须手动回收内存,这就导致了有java引起的内存泄漏. 2.1+N问题 (1)使用@ManyToOne的时候,默认FetchType=EAGER,此时会自动取出One这一方的信息. (

Hibernate性能优化之SessionFactory重用

Hibernate优化的方式有很多,如缓存.延迟加载以及与SQL合理映射,通过对SessionFactory使用的优化是最基础的. SessionFactory负责创建Session实例,Session相当于JDBC里的Connection. SessionFactory的创建 SessionFactory是通过Configuration来构建的,Configuration会根据配置信息来构建SessionFactory. SessionFactory中保存了对应当前数据库配置的所有映射关系,还

Hibernate 性能优化及缓存的使用

1 clear()方法的运用: 由于hibernate在查询出来数据之后,会把数据进行缓存,对于同一个session多次大数据的查询,由于缓存会占用一定的内存空间,因此要多用seesion.clear(0方法清空缓存: 2 对于多发的sql语句合理设置tetch: 在关联查询时候,有时候只查询其中一个表里的数据,而hibernate会发出多条sql语句把另外一张表的数据也进行查询,影响性能,可以通过设置fetch的值来进行关联查询时候的懒加载:例如在多对一查询时候 @ManyToOne(casc

第七章 Hibernate性能优化

一对一关联 实体类关系 一对多 多对多 一对一 Hibernate提供了两种映射一对一关联关系的方式:按照外键映射和按照主键映射.下面以员工账号和员工档案表为例,介绍这两种映射方式,并使用这两种映射方式分别完成以下持久化操作: (1)保存员工档案的同时分配给员工一个账号. (2)加载员工档案的同时加载账号信息. 1.按照外键映射 步骤一:创建实体类Users1和Resume1 Users1创建如下: public class Users1 { private Integer userid; pr

Hibernate 性能优化之抓取策略

fetch 抓取策略 前提条件:必须是一个对象操作其关联对象. 1. 根据一的一方加载多的一方,在一的一方集合中,有三个值:join/select/subselect 2.根据多的一方加载一的一方, 这种情况不考虑,因为关联对象就一个数据,怎么样都可以join 连接  [一次性的把两张表的数据全部查询出来,只发出一条sql语句]    *  在页面上既包括一的一方的数据,又包括多的一方的数据    *  数据库的数据量比较小select 默认的查询方式    [先加载classes,当得到stu

Hibernate 性能优化之懒加载

针对数据库中的大数据,不希望特别早的加载到内存中,当用到它的时候才加载 懒加载分为:类的懒加载.集合的懒加载.单端关联的懒加载 类的懒加载    1.在默认情况下,类就是执行懒加载        2.只有使用了load方法以后才能用懒加载    3.如果在相应的映射文件中,设置<class>的lazy="false"懒加载将失去效果集合的懒加载     1.针对一多对的情况或者多对多的情况    2.根据一方加载set集合,决定在什么时候给set集合填充数据        

Hibernate 性能优化之查询缓存

查询缓存是建立在二级缓存基础之上的,所以与二级缓存特性相似,是共享的,适合修改不是很频繁的数据 查询缓存不是默认开启的,需要设置      1.在cfg文件中配置 <property name="cache.use_query_cache">true</property> 2.在代码中进行设置 query.setCacheable(true);

hibernate之性能优化

hibernate是建立在JDBC基础上的框架,但他有很多JDBC所无法比拟的性能优化技术.下面介绍几种优化策略. 1.使用dynamic-insert与dynamic-update 在class标签中使用该属性,可以设置hibernate动态的生成SQL语句,而不是在hibernate启动时就生成预设的SQL语句. 当其设置为true时,hibernate会根据实际需求设置新增或更新的字段,而不是所有的字段. <class name="com.hibernate.book" t