hibernate查询缓存

2019-03-03 16:20|来源: 领悟书生

查询缓存是针对HQL语句的缓存,查询缓存仅仅只会缓存id而不会缓存对象


首先在hibernate.cfg.xml设置查询缓存

<!--设置相应的查询缓存 -->

<property name="hibernate.cache.use_query_cache">true</property>


使用setCacheable(true)开启查询缓存,查询缓存也是SessionFactory级别的缓存

Session session = null;
try {
    /**
     * 此时会发出一条sql取出所有的学生信息
     */
    session = HibernateUtil.openSession();
    List<Student> ls = session.createQuery("from Student")
            .setCacheable(true)
            .setFirstResult(0).setMaxResults(50).list();
    Iterator<Student> stus = ls.iterator();
    for(;stus.hasNext();) {
        Student stu = stus.next();
        System.out.println(stu.getName());
    }
    ls = session.createQuery("from Student")
            .setCacheable(true)
            .setFirstResult(0).setMaxResults(50).list();
    stus = ls.iterator();
    for(;stus.hasNext();) {
        Student stu = stus.next();
        System.out.println(stu.getName()+"---");
    }
} catch (Exception e) {
    e.printStackTrace();
} finally {
    HibernateUtil.close(session);
}


只要HQL语句不一样,就不会开启查询缓存,查询缓存缓存的是HQL语句,只要两个HQL完全一致(参数也要一致),才能使用查询缓存

Session session = null;
try {
    session = HibernateUtil.openSession();
    List<Student> ls = session
            .createQuery("from Student where name like ?")
            .setCacheable(true)
            .setParameter(0, "%王%")
            .setFirstResult(0).setMaxResults(50).list();
    Iterator<Student> stus = ls.iterator();
    for(;stus.hasNext();) {
        Student stu = stus.next();
        System.out.println(stu.getName());
    }
} catch (Exception e) {
    e.printStackTrace();
} finally {
    HibernateUtil.close(session);
}
 
session = null;
try {
    session = HibernateUtil.openSession();
    List<Student> ls = session
            .createQuery("from Student where name like ?")
            .setCacheable(true)
            .setParameter(0, "%王%")
            .setFirstResult(0).setMaxResults(50).list();
    Iterator<Student> stus = ls.iterator();
    for(;stus.hasNext();) {
        Student stu = stus.next();
        System.out.println(stu.getName());
    }
} catch (Exception e) {
    e.printStackTrace();
} finally {
    HibernateUtil.close(session);
}

如果关闭二级缓存,就会出现N+1的问题,所以要用查询缓存,就必须开启二级缓存

Session session = null;
try {
    session = HibernateUtil.openSession();
    List<Student> ls = session
            .createQuery("from Student where name like ?")
            .setCacheable(true)
            .setParameter(0, "%王%")
            .setFirstResult(0).setMaxResults(50).list();
    Iterator<Student> stus = ls.iterator();
    for(;stus.hasNext();) {
        Student stu = stus.next();
        System.out.println(stu.getName());
    }
} catch (Exception e) {
    e.printStackTrace();
} finally {
    HibernateUtil.close(session);
}
 
session = null;
try {
    /**
     * 查询缓存缓存的是id,
     * 此时由于在缓存中已经存在了这样的一组学生数据,
     * 但是仅仅只是缓存了id,所以此处会发出大量的sql语句根据id取对象,
     * 这也是发现N+1问题的第二个原因
     * 所以如果使用查询缓存必须开启二级缓存
     */
    session = HibernateUtil.openSession();
    List<Student> ls = session
            .createQuery("from Student where name like ?")
            .setCacheable(true)
            .setParameter(0, "%王%")
            .setFirstResult(0).setMaxResults(50).list();
    Iterator<Student> stus = ls.iterator();
    for(;stus.hasNext();) {
        Student stu = stus.next();
        System.out.println(stu.getName());
    }
} catch (Exception e) {
    e.printStackTrace();
} finally {
    HibernateUtil.close(session);
}

补充一下,

基于annotation的方式开启二级缓存的方式

@Cache(usage=CacheConcurrencyStrategy.READ_ONLY)

public class Student {


本文链接:hibernate查询缓存,领悟书生学习笔记,转载请注明出处:http://www.656463.com/article/421

相关问答

更多
  • 查询缓存的工作方式是只缓存查询返回的对象的ID 。 因此,您的初始SELECT语句可能会返回所有对象,Hibernate会将它们还给您并记住ID。 然而,当你下一次发出查询时,Hibernate会遍历ID列表,并意识到它需要实现实际数据。 所以它返回到数据库来休息。 它每行都有一个SELECT,这正是你所看到的。 现在,在你认为“这个特性显然被破坏了”之前,它这样工作的原因是查询缓存被设计为与二级缓存协同工作。 如果这些对象在第一次查询后存储在二级缓存中,那么Hibernate将会在那里查找,以满足每个ID ...
  • 查询级缓存 这是一个可选功能,需要两个额外的物理缓存区域,用于保存缓存的查询结果和上次更新表时的时间戳。 这仅适用于使用相同参数频繁运行的查询。 Query q = this.getEntityManager().createQuery("FROM " + entityClass.getSimpleName()); query.setCacheable(true); List result = q.getResultList(); return result; 更多关于查询缓存的信息 Query-l ...
  • Hibernate没有提供用于控制缓存细节的接口,例如您请求的。 相反,您必须选择提供该功能的缓存实现,并对其进行适当配置。 例如,您可以使用EhCache并像这样配置它:
  • Hibernate将只缓存Pays p对象,这是真的,因为Criteria只在那个上创建。 如果要缓存其他集合,则必须在集合属性的getter方法上使用Cachebale。 您也可以在每个Entity对象上使用Cache注释。 I resolved my issues,simply by applying a filter in my web.xml like this : openSessionInViewFilter ...
  • 二级缓存缓存由ID索引的实体状态。 但它是一个缓存。 它只存储一些实体(通常是最近使用的实体)。 因此,即使Hibernate可以解析查询,分析它,注意它只包含对实体ID的限制,它不能使用它的缓存绕过数据库,因为它不知道是否所有实体都将返回数据库是在缓存中还是不在缓存中。 因此它不会像所有其他查询那样完成所有这些操作,而只是执行查询。 但您可以做的是配置查询缓存。 这会使它缓存先前执行的查询返回的实体的ID。 在这种情况下,将绕过相同查询的第二次执行(具有相同的参数),将从查询缓存返回ID,并且将从第二级缓 ...
  • 它似乎与此处描述的类似问题https://hibernate.atlassian.net/browse/HHH-610 解决方法是使用文档http://docs.jboss.org/hibernate/orm/4.1/devguide/en-US/html_single/#querysql-load中所述的@Loader 为Hotel类添加以下注释修复了问题@Loader(namedQuery =“fetchHotel”) It seems its similar issue as described he ...
  • 当我通过多个线程反复执行相同的操作集时,我已经设置了一个简单的压力测试。 当我检查hibernate统计信息时,结果是查询缓存hitCount为零! 好吧,虽然可以从统计信息中获取有关缓存命中的统计信息( 如果通过在配置中设置属性hibernate.generate_statistics=true来启用统计信息),这是IMO不是诊断缓存“问题”的最佳方法。 我的建议是激活1.执行的DML语句和2.缓存活动的日志记录。 相关的日志记录类别是: org.hibernate.SQL在执行时记录所有SQL DML语 ...
  • 是的,您可以使用Hibernate 执行普通的SQL查询 。 不,你不需要单独的hbm.xml映射文件(除非你想将sql查询与其他文件分开,在这种情况下你可以这样做)。 您可以使用与命名HQL查询相同的方式映射命名的SQL查询。 您是否能够“利用缓存”取决于您通过“缓存”所了解的内容以及如何映射SQL查询; 不知道更多细节就无法回答。 所有这一切,你可能不需要求助于SQL查询; HQL功能非常强大,并且很有可能(假设存在适当的映射)将您的查询编写为HQL。 你能发布相关的映射/模式和你的SQL查询吗? Ye ...
  • 尝试在Hibernate配置文件中命名SessionFactory。 在以后版本的Hibernate上,通过RMI处理缓存复制似乎存在问题(参见https://hibernate.onjira.com/browse/HHH-6162 )。 Try to name your SessionFactory on your Hibernate configuration file. It seems there is a problem on later versions of Hibernate on hand ...
  • 您启用的是二级缓存。 此缓存缓存实体的状态,并按ID对其进行索引。 它就像Map 。 仅当您通过ID获取实体时才使用此缓存: 通过调用session.get() 通过调用session.load() 通过浏览目标实体的XxxToOne关联 您的查询不属于此类别:它通过其中一个字段查找您的实体,而不是按其ID查找。 对于其余的,Hibernate不能对缓存执行任意SQL查询,即使可以,缓存也只包含表的子集,因此它必须查询数据库。 但是,您也可以缓存查询结果。 您需要启用查询缓 ...