收藏 分享(赏)

二级缓存的简单理解.txt

上传人:weiwoduzun 文档编号:3263190 上传时间:2018-10-09 格式:TXT 页数:18 大小:28.84KB
下载 相关 举报
二级缓存的简单理解.txt_第1页
第1页 / 共18页
二级缓存的简单理解.txt_第2页
第2页 / 共18页
二级缓存的简单理解.txt_第3页
第3页 / 共18页
二级缓存的简单理解.txt_第4页
第4页 / 共18页
二级缓存的简单理解.txt_第5页
第5页 / 共18页
点击查看更多>>
资源描述

1、 1. 关于hibernate缓存的问题:1.1.1. 基本的缓存原理Hibernate缓存分为二级,第一级存放于session中称为一级缓存,默认带有且不能卸载。第二级是由sessionFactory控制的进程级缓存。是全局共享的缓存,凡是会调用二级缓存的查询方法 都会从中受益。只有经正确的配置后二级缓存才会发挥作用。同时在进行条件查询时必须使用相应的方法才能从缓存中获取数据。比如Query.iterate()方法、load、get方法等。必须注意的是session.find方法永远是从数据库中获取数据,不会从二级缓存中获取数据,即便其中有其所需要的数据也是如此。查询时使用缓存的实现过程为:

2、首先查询一级缓存中是否具有需要的数据,如果没有,查询二级缓存,如果二级缓存中也没有,此时再执行查询数据库的工作。要注意的是:此3种方式的查询速度是依次降低的。1.2. 存在的问题1.2.1. 一级缓存的问题以及使用二级缓存的原因因为Session的生命期往往很短,存在于Session 的第一级 缓存的生命期 也很短,所以第一级缓存的命中 是很低的。其 能的 也是很有 的。 , Session 缓存的 要作用是Session 数据 同 。 是hibernate为 能所 的。为 使用hibernate的 能, 的一需要注意的方法比如:使用载、currency1、查询过“等以,需要配置hiberna

3、te的二级缓存。其 能的 往往具有fifl 的果经过 以作的经”,一会有34的 能 1.2.2. N+1次查询的问题执行条件查询时,iterate方法具有 的 n+1”次查询的问题,也是在第一次查询时iterate方法会执行条件的查询果数再一次n+1的查询。是此问题只存在于第一次查询时,在后执行相同查询时 能会 的 。此方法 于查询数据 的数据。是注意: 数据 时比如 数据等需要 此 配置其具的缓存 ,比如 置其存在于缓存中的 数、缓存存在的时 等 数,以 的数据同时 载 存中 存的速 , 降低 的 能1.3. 使用hibernate二级缓存的其 注意 :1.3.1. 关于数据的有 ,hibe

4、rnate会 行 二级缓存中的数据,以 缓存中的数据数据库中的 实数据的一 时, 调用save()、update() saveOrUpdate()方法 一 时, 使用load()、 get()、list()、iterate() scroll()方法获一 时, 都被 Session的 缓存中。 随后flush()方法被调用时, 的 会数据库取同 。也是删 、更新、增数据的时候,同时更新缓存。 也包括二级缓存只要是调用hibernate API执行数据库相关的工作。hibernate都会为 动 缓存数据的有 是,如果使用 JDBC绕过hibernate直执行 数据库的操作。此时,Hibernate

5、不会/也不可能 行感知 数据库被进行的变 动,也不能再 缓存中数据的有 也是所有的ORM产品共同具有的问题。幸运的是,Hibernate为我们暴露 Cache的清 方法, 给我们 一 手动 数据有 的机会一级缓存,二级缓存都有相应的清 方法。其中二级缓存 的清 方法为:按 class清空缓存按 class 的 键id清空缓存清空 的集 中的缓存数据等。1.3.2. 使用的情况所有的情况都 于使用二级缓存,需要根据具情况来决定。同时可以 某一 配置其具的缓存 。 于使用二级缓存的情况:1、数据不会被第三方修 ;一情况下,会被hibernate以修 的数据 好不要配置二级缓存,以 不一 的数据。是

6、如果此数据因为 能的原因需要被缓存,同时又有可能被第3方比如SQL修 ,也可以为其配置二级缓存。只是此时需要在sql执行修 后手动调用cache的清 方法。以 数据的一 2、数据 小在可收范围之 ;如果数据表数据 巨 ,此时不 于二级缓存。原因是缓存的数据过 可能会 存紧张, 降低 能。如果数据表数据 巨 ,是经 使用的往往只是新的那 分数据。此时,也可为其配置二级缓存。是必须单独配置其 类的缓存 ,比如 缓存数、缓存过期时 等, 数降低至一 理的范围太 会 存紧张,太低 缓存的意义不 。3、数据更新频 低;于数据更新频 过 的数据,频繁同 缓存中数据的代价可能 查询缓存中的数据从中获的好处相

7、 ,坏处益处相抵消。此时缓存的意义也不 。4、 关键数据不是财数据等财数据等是 重要的数据,绝 不允许出现 使用的数据,所以此时为 安全 好不要使用二级缓存。因为此时 正确 ”的重要 远远 于 能”的重要 。2. 中使用hibernate缓存的建议1.4. 情况一 中有三种情况会绕开hibernate执行数据库操作:1、多 应用 同时访问一 数据库此种情况使用hibernate二级缓存会不可 的造成数据不一 的问题,此时要进行详细的 计。比如在 计上 同一数据表的同时的写 操作,使用数据库各种级 的锁定机制等。2、动 表相关所谓 动 表”是指在 运行时根据用户的操作 动建fi的数据表。比如 定

8、义表单”等属于用户 定义扩展开发 质的功能模块,因为此时数据表是运行时建fi的,所以不能进行hibernate的映射。因此 它的操作只能是绕开hibernate的直数据库JDBC操作。如果此时动 表中的数据没有 计缓存,不存在数据不一 的问题。如果此时 行 计 缓存机制,则调用 的缓存同 方法即可。3、使用sql hibernate 表进行批删 时此时执行批删 后,缓存中会存在已被删 的数据。分析: 执行 第3条sql批删 后,后续的查询只可能是以下三种方式:a. session.find方法:根据的总,find方法不会查询二级缓存的数据, 是直查询数据库。所以不存在数据有 的问题。b. 调用

9、iterate方法执行条件查询时:根据iterate查询方法的执行方式,其每次都会 数据库中查询条件的id值, 后再根据此id 缓存中获取数据, 缓存中没有此id的数据才会执行数据库查询;如果此 已被sql直删 ,则iterate在执行id查询时不会此id查询出来。所以,即便缓存中有此条 也不会被客户获,也不存在不一 的情况。此情况经过测试” c. 用get load方法按id执行查询:客观上此时会查询 已过期的数据。是又因为 中执行sql批删 一是中 关联数据表, 于中 关联表的查询一都是采用条件查询 ,按id来查询某一条关联关 的几 很低,所以此问题也不存在!如果某 值 确实需要按id查询

10、一条关联关 ,同时又因为数据 使用 sql执行批删 。 此两 条件时,为 按id 的查询 正确的果,可以使用手动清楚二级缓存中此 的数据的方法!(此种情况出现的可能 小)1.5. 建议1、建议不要使用sql直执行数据 的数据的更新,是可以执行 批删 。 中需要批更新的地方也少2、如果必须使用sql执行数据的更新,必须清空此 的缓存数据。调用SessionFactory.evict(class) SessionFactory.evict(class,id)等方法。3、在批删 数据不 的时候可以直采用hibernate的批删 , 样不存在绕开hibernate执行sql产生的缓存数据一 的问题。4

11、、不推荐采用hibernate的批删 方法来删 批的 数据。原因是hibernate的批删 会执行1条查询 条件的n条删 。 不是一次执行一条条件删 删 的数据很多时会有很 的 能 如果批删 数据 ,比如 过50条,可以采用JDBC直删 。 样作的好处是只执行一条sql删 , 能会有很 的 。同时,缓存数据同 的问题,可以采用 hibernate清 二级缓存中的相关数据的方法。调用 SessionFactory.evict(class) ;SessionFactory.evict(class,id)等方法。所以, 于一的应用 开发 不 及 集 ,分 式数据同 问题等,因为只在中 关联表执行批删

12、 时调用 sql执行,同时中 关联表一是执行条件查询不太可能执行按id查询。所以,此时可以直执行sql删 , 至不需要调用缓存的清 方法。 样 不会 以后配置 二级缓存 数据有 的问题。一 ,即使以后 的调用 按id查询中 表 的方法,也可以 过调用清 缓存的方法来 决。4、具的配置方法 根据我 的很多hibernate的使用 在调用其相应方法时都 的相 hibernate会 行为我们处理能的问题”, hibernate会 动为我们的所有操作调用缓存”,实 的情况是hibernate 为我们 很好的缓存机制扩展缓存 的 ,是必须经过正确的调用其才有可能发挥作用所以造成很多使用hibernate

13、的 的 能问题,实 上 不是hibernate不行 不好, 是因为使用 没有正确的 其使用方法造成的。相 ,如果配置 hibernate的 能表现会 有相 的”发现。下我 具的配置方法.ibernate 二级缓存的 : net.sf.hibernate.cache.Provider, 同时 一 默认的 实现net.sf.hibernate.cache.HashtableCacheProvider, 也可以配置 其 的实现 比如ehcache,jbosscache等。 具的配置 置 于hibernate.cfg.xml 件中 property name=hibernate.cache.use_q

14、uery_cachetrue/property property name=hibernate.cache.provider_classnet.sf.hibernate.cache.HashtableCacheProvider/property 很多的hibernate使用 在 配置 一 以为 , 注意:其实 样配,根本 没有使用hibernate的二级缓存。同时因为 们在使用hibernate时 多时候是上关session,所以,一级缓存也没有 作用。果是没有使用缓存,所有的hibernate操作都是直操作的数据库 能可以 。 正确的法是 以上的配置应 配置每一 vo 的具缓存 ,在射 件中

15、配置。如: hibernate-mapping class name=com.sobey.sbm.model.entitySystem.vo.DataTypeVO table=dcm_datatype cache usage=read-write/ id name=id column=TYPEID type=java.lang.Long generator class=sequence/ /id property name=name column=NAME type=java.lang.String/ property name=dbType column=DBTYPE type=java.l

16、ang.String/ /class /hibernate-mapping 关键是 cache usage=read-write/,其有几 currency1 read-only,read-write,transactional,等 后在执行查询时 注意 ,如果是条件查询, “所有果的查询,此时session.find()方法 不会获取缓存中的数据。只有调用query.iterate()方法时才会调缓存的数据。 同时 get load方法 是都会查询缓存中的数据 .于不同的缓存 具的配置方法会有不同,是 是以上的配置, 于 ,以及 集 的的配置我会fi取在后续的 fl中中 发表出来 3. 总总

17、之是根据不同的情况情况 hibernate进行有的配置正确的使用, 短。不存在 于情况的一 能”的方。以上及建议建fi在 在 Hibernate 2.1.2中的测试果以及以的经”的基 上。如有处, 出指正:)!后,” 新 在新的一 取 生的进 -Hibernate 所有缓存机制详 hibernate 的一级缓存 hibernate是一 程 应一 session,一 程可以成一 用户。也是session级缓存(一级缓存)只能给一 程用, 的 程用不 ,一级缓存是 程 定 。hibernate一级缓存生命期很短,session生命期一样,一级缓存也称session级的缓存 级缓存。如果tb “ ,

18、我们称session关 ,生命期 。缓存currency1的 :缓存都是放在 存,实现是一样的,都是为 能的。有细的 ,是重级的,的数据是一样的,比如一 放100 Connectioncurrency1 , 100 都是一样的。缓存的数据,每 都不一样。比如 取100条数据库 放 缓存, 100条 都不一样。缓存 要是用于查询/同一 session中,发出两次load方法查询Student student = (Student)session.load(Student.class, 1);System.out.println(student.name= + student.getName();

19、/不会发出查询 ,load使用缓存student = (Student)session.load(Student.class, 1);System.out.println(student.name= + student.getName();第二次查询第一次相同的数据,第二次load方法是从缓存取数据,不会发出sql 数据库查询。/同一 session,发出两次get方法查询Student student = (Student)session.get(Student.class, 1);System.out.println(student.name= + student.getName();/不

20、会发出查询 ,get使用缓存student = (Student)session.get(Student.class, 1);System.out.println(student.name= + student.getName();第二次查询第一次相同的数据,第二次不会发出sql 查询数据库, 是 缓存取数据。/同一 session,发出两次iterate查询实 Iterator iter = session.createQuery(from Student s where s.id5).iterate();while (iter.hasNext() Student student = (St

21、udent)iter.next();System.out.println(student.getName();System.out.println(-);/它会发出查询id的 ,不会发出根据id查询生的 ,因为iterate使用缓存iter = session.createQuery(from Student s where s.id5).iterate();while (iter.hasNext() Student student = (Student)iter.next();System.out.println(student.getName();一 iterater查询要fi :iter

22、ater查询在没有缓存的情况下会有N+1的问题。执行上代 查控制的sql ,第一次iterate查询会发出N+1条sql ,第一条sql 查询所有的id, 后根据id查询实 ,有N id发出N条 查询实。第二次iterate查询,只发一条sql ,查询所有的id, 后根据id 缓存取实 ,不再发sql 数据库查询 。/同一 session,发出两次iterate查询,查询 属 Iterator iter = session.createQuery(select s.name from Student s where s.id5).iterate();while (iter.hasNext()

23、String name = (String)iter.next();System.out.println(name);System.out.println(-);/iterate查询 属 ,一级缓存不会缓存,所以发出查询 /一级缓存是缓存实 的iter = session.createQuery(select s.name from Student s where s.id5).iterate();while (iter.hasNext() String name = (String)iter.next();System.out.println(name);执行代 控制sql ,第一次发出N+

24、1条sql ,第二次是发出 N+1条sql 。因为一级缓存只缓存实 ,tb不会缓存 属 ,所以第二次是发出sql查询 。/两 session,每 session发出一 load方法查询实 try session = HibernateUtils.getSession();session.beginTransaction();Student student = (Student)session.load(Student.class, 1);System.out.println(student.name= + student.getName();session.getTransaction().c

25、ommit();catch(Exception e) e.printStackTrace();session.getTransaction().rollback();finally HibernateUtils.closeSession(session);第二 session调用load方法try session = HibernateUtils.getSession();session.beginTransaction();Student student = (Student)session.load(Student.class, 1);/会发出查询 ,session 不能共享一级缓存数据/

26、因为 会随 session的消 消 System.out.println(student.name= + student.getName();session.getTransaction().commit();catch(Exception e) e.printStackTrace();session.getTransaction().rollback();finally HibernateUtils.closeSession(session);第一 session的load方法会发出sql 查询实 ,第二 session的load方法也会发出sql查询实 。因为session 不能共享一级缓

27、存的数据,所以第二 session的load方法查询相同的数据是要 数据库中查询,因为它 不 第一 session缓存的数据。/同一 session,先调用save方法再调用load方法查询 save的数据Student student = new Student();student.setName(张三);/save方法“实 的idSerializable id = session.save(student);student = (Student)session.load(Student.class, id);/不会发出查询 ,因为save 缓存System.out.println(stud

28、ent.name= + student.getName();先save 存实 ,再用load方法查询 save的实 ,则load方法不会发出sql 数据库查询的, 是 缓存取数据,因为save方法也 缓存。 是同一 session。/ 批的数据 for (int i=0; i100; i+) Student student = new Student();student.setName(张三 + i);session.save(student);/每20条更新一次if (i % 20 = 0) session.flush();/清 缓存的 session.clear();批数据 时,会造成 存

29、 出的,因为save方法 缓存,每save一 往缓存放,如果 多 存 定要 出。一的 法是先 一下save 多少 ,如果save 20 缓存手动的清理缓存, 样不会造成 存 出。注意:清理缓存,要手动调用flush方法同 数据库,否则save的 没有 存 数据库。注意: 批数据的 是不要使用hibernate, 是hibernate 。可以使用jdbc(速度也不会太,只是比hibernate好一 ), 使用工具产品来实现,比如oracle的Oracle SQL Loader, 数据 。 Hibernate 二级缓存 二级缓存需要sessionFactory来 理,它是进 级的缓存,所有 都可以

30、使用,它是共享的。二级缓存比 ,一用第三方产品。hibernate 一 单实现,用Hashtable 的,只能作为我们的测试使用,用是需要第三方产品。使用缓存, 定是时 不 变的数据,如果经 变 的数据放 缓存没有太 意义 。因为经 变 ,是需要经 数据库查询,那没有必要用缓存 。hibernate 一 ,一第三方的缓存产品 集成。 采用EHCache缓存产品。EHCache二级缓存产品集成:EHCache的jar 件在hibernate的lib,我们需要 置一 的缓存使用 ,需要一 配置 件ehcache.xml来配置。 件放在类下。/默认配置,所有的类都 配置defaultCache/缓存

31、可以放10000 maxElementsInMemory=10000/过不过期,如果是true是永远不过期eternal=false/一 被访问后多时 没有访问 (120 没有再次访问 )timeToIdleSeconds=120/ 存 时 (120 ),如果 置永不过期, 没有必要 timeToLiveSeconds=120/ 出的问题,如果 成true,缓存 过10000 存 overflowToDisk=true/我们也可以 某 单独配置:cache name=com.bjpowernode.hibernate.StudentmaxElementsInMemory=100eternal=

32、falsetimeToIdleSeconds=10000timeToLiveSeconds=10000overflowToDisk=true/需要在hibernate.cfg.xml配置 件配置缓存, hibernate知我们使用的是那 二级缓存。!- 配置缓存 -property name=hibernate.cache.provider_classorg.hibernate.cache.EhCacheProvider/property!- 用二级缓存, 也是它的默认配置 -property name=hibernate.cache.use_second_level_cachetrue/pr

33、operty用二级缓存的配置可以不写的,因为默认是true开 二级缓存。必须手动指定那实类的 放 缓存在hibernate.cfg.xml:/在sessionfactory ,在mapping 后配置class-cache class=com.bjpowernode.hibernate.Studentusage=read-only/在实类映射 件:/在class ,id 配置cache usage=read-only/usage属 表使用缓存的 ,一 先使用read-only,表如果 数据放 缓存 ,则不允许修,如果修 会 。 要注意我们放 缓存的数据不允许修 。因为放缓存的数据经 修 ,也没

34、有必要放 缓存。使用read-only 好,因为不能 缓存。是可能会出现数据的问题, 问题 决方法只能依缓存的 时,比如上我们 置 时为120 ,120后可以 缓存 进行修 , 在120 之 访问 可能会查询数据的问题,因为我们修 后数据库 变 , 缓存不能 变, 样造成数据不同 ,也是数据的问题。第二种缓存 read-write, 发生变 ,缓存会 变 ,数据库中也 变 。 种方式需要 锁, 要比第一种。有两种 ,hibernate , 用是第一二种 。二级缓存测试代 :注意上我们 的两 session分 调用load方法查询相同的数据,第二 session的load方法是发 sql 数据库

35、查询数据, 是因为一级缓存只在 session中共享,也是一级缓存不能 session访问。/开 二级缓存,二级缓存是进程级的缓存,可以共享/两 session分 调用load方法查询相同的实 try session = HibernateUtils.getSession();session.beginTransaction();Student student = (Student)session.load(Student.class, 1);System.out.println(student.name= + student.getName();session.getTransaction(

36、).commit();catch(Exception e) e.printStackTrace();session.getTransaction().rollback();finally HibernateUtils.closeSession(session);try session = HibernateUtils.getSession();session.beginTransaction();Student student = (Student)session.load(Student.class, 1);/不会发出查询 ,因为配置二级缓存,session可以共享二级缓存中的数据/二级缓存

37、是进程级的缓存System.out.println(student.name= + student.getName();session.getTransaction().commit();catch(Exception e) e.printStackTrace();session.getTransaction().rollback();finally HibernateUtils.closeSession(session);如果开 二级缓存,那 第二 session调用的load方法查询第一次查询的数据,是不会发出sql 查询数据库的, 是去二级缓存中取数据。/开 二级缓存/两 session

38、分 调用get方法查询相同的实 try session = HibernateUtils.getSession();session.beginTransaction();Student student = (Student)session.get(Student.class, 1);System.out.println(student.name= + student.getName();session.getTransaction().commit();catch(Exception e) e.printStackTrace();session.getTransaction().rollbac

39、k();finally HibernateUtils.closeSession(session);try session = HibernateUtils.getSession();session.beginTransaction();Student student = (Student)session.get(Student.class, 1);/不会发出查询 ,因为配置二级缓存,session可以共享二级缓存中的数据/二级缓存是进程级的缓存System.out.println(student.name= + student.getName();session.getTransaction(

40、).commit();catch(Exception e) e.printStackTrace();session.getTransaction().rollback();finally HibernateUtils.closeSession(session);注意:二级缓存必须 sessionfactory 理, sessionfactory来清 二级缓存。sessionFactory.evict(Student.class);/清 二级缓存中所有student ,sessionFactory.evict(Student.class,1);/清 二级缓存中id为1的student 。如果在第

41、一 session调用load get方法查询数据后,把二级缓存清 ,那 第二 session调用load get方法查询相同的数据时,是会发出sql 查询数据库的,因为缓存没有数据只能 数据库查询。我们查询数据后会默认 动的放 二级一级缓存,如果我们查询的数据不放 缓存,也是可以的。也是我们可以控制一级缓存二级缓存的换。session.setCacheMode(CacheMode.IGNORE);禁止一级缓存中的数据往二级缓存放。是用上代 测试,在第一 session调用load方法,执行session.setCacheMode(CacheMode.IGNORE); 样load方法查询的数据

42、不会放 二级缓存。那 第二 session执行load方法查询相同的数据,会发出sql 数据库中查询,因为二级缓存没有数据,一级缓存因为不同的session不能共享,所以只能 数据库查询。上我们 过 批的数据 时可能会出现 出, 决法是每 天20 后清理一次一级缓存。如果我们使用 二级缓存, 清理一级缓存是不 的,要禁止一二级缓存互,在save方法调用session.setCacheMode(CacheMode.IGNORE)。二级缓存也不会存放 属 的查询数据, 一级缓存是一样的,只存放实 。session级的缓存 能的 没有太 的意义,因为生命期太短 。Hibernate 查询缓存 一级缓存二级缓存都只是存放实 的,如果查询实 的 属 的数据,只能放 查询缓存,查询缓存存放查询实 的id。查询缓存的生命期不确定, 它关联的表发生修 ,查询缓存的生命期。 表的修 指的是

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 企业管理 > 管理学资料

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报