2015-03-31 120 views
0

所以,我的问题是我不确定我的查询是否被缓存。我现在拥有的hibernate.xml使用ehcache作为二级缓存。使用Criteria查询进行Hibernate缓存

现在这是我的测试代码:

Session session = HibernateUtil.getCurrentSession(); 
    Criteria criteria = session.createCriteria(Users.class); 
    criteria.add(Restrictions.eq("id", "777008")); 

    Users user = (Users) criteria.uniqueResult(); 

    HibernateUtil.closeCurrentSession(); 

    Session anotherSession = HibernateUtil.getCurrentSession(); 
    Criteria anotherCriteria = anotherSession.createCriteria(Users.class); 
    anotherCriteria.add(Restrictions.eq("id", "777008")); 

    Users anotherUser = (Users) anotherCriteria.uniqueResult(); 

HibernateUtil.getCurrentSession()方法在ThreadLocal变量检索当前的会话,如果它是可用的。如果会话为空,则会创建一个会话。

HibernateUtil.closeCurrentSession()ThreadLocal变量中获取会话,如果它不为空则关闭它。当我运行上面的代码(这是一个JUnit测试)时,我只能看到一个从数据库中选择的Hibernate日志。因为我没有用Criteria.setCaching(true)来强制缓存任何东西,所以我期待有两个。

我相信一级缓存只存在于会话范围内,二级缓存基本上是应用程序缓存。在上面的两个criteria.uniqueResult()调用的中间,我关闭了会话。

我的问题是,为什么我只看到一个Hibernate SELECT语句日志?我不应该看到两个吗?另外,当我去我的hibernate.xml并禁用第二级缓存时,仍然会出现相同的输出,这真是令我困惑不已。

我看到的SELECT语句日志的例子:`Hibernate:select this_.id as id8_0_,this_.nameas name8_0_,from users this_ where this_.id =?

编辑:我这次尝试了不同的方法。请参阅下面的下面的代码片段:

@Test 
public void testCaching(){ 

    for (int i = 0; i < 10; i++){ 


     try { 
      Thread.sleep(3000); 

      logger.info("Retrieving user."); 
      Session session = HibernateUtil.getCurrentSession(); 
      Criteria criteria = session.createCriteria(Users.class); 
      criteria.add(Restrictions.eq("id", "777008")); 
      criteria.setCacheable(true); 

      Users user = (Users) criteria.uniqueResult(); 

     } 
     catch (Exception ex){ 
      System.out.println("Got it"); 
     } 
     finally{ 
      HibernateUtil.closeCurrentSession(); 

     } 
    } 
} 

所以,现在,每一个测试调用Criteria.uniqueResult()时,它会显示一个Hibernate日志。那么现在,我关心的是我甚至缓存了什么?使用此测试启用第二级缓存(ehcache)。编辑2:好吧,现在,我有点想法为什么它不缓存。原来,我必须把<cache usage="read-write"/>放在我对象的XML的<class>之内。但是,我不能这样做,因为其他应用程序也在使用XML。无论如何只能在应用程序上启用缓存吗?

回答

0

您会看到一个查询,因为id = 777008的User对象已经在Hibernate上下文中。尝试使用名称字段而不是@Id字段查询,您应该看到两个查询。

还可以在您的配置中全局地打开查询缓存,而无需为特定查询设置该缓存。

+0

因此,它已经在Hibernate环境中,这是否意味着它被缓存?为什么我应该使用名称字段?我只能使用ID字段进行查询。由于我不被允许,我无法真正全局配置它来缓存。 hibernate.xml也被其他应用程序使用。 – mpmp 2015-03-31 18:29:06

+0

对不起,我的意思是,如果您使用的查询不是基于id的查询,而是使用其他属性,则会看到两个查询。是的,最近的对象被缓存在hibernate上下文中,并且基于id的搜索首先进入该上下文。例如,如果您有一些@OneToMany用户集合(除非您有批量提取),那么您将不会看到所有用户的sql语句,但仅针对那些尚未处于上下文中的用户。 – Zielu 2015-03-31 18:34:15

+0

嗯..你在Hibernate上下文中失去了我。我相信只有两种类型的缓存:一级缓存(会话作用域)和二级缓存(应用程序作用域)。你指的是哪个范围?它不能在会话范围内,因为我在第一次查询后关闭会话。它可能不在应用程序范围内,因为当我在Hibernate中转换第二级缓存时,我仍然得到相同的结果:/ – mpmp 2015-03-31 19:42:30

相关问题