JPA2.0和Hibernate二级缓存浅析(1)-——查询缓存

技术文档网 2021-04-27

最近项目里用到Spring-Data-JPA,JPA的实现用的是Hibernate,有一个场景特别适合用二级缓存。背景如下:

@Entity
@Table(name = "T_A")
@Cacheable
class A{

}

@Entity
@Table(name = "T_B")
@Cacheable
class B{
    @ManyToOne
    @JoinColumn(name = "a_id", nullable = false)
    private A a;

    @org.hibernate.annotations.Cache(usage=CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, mappedBy = "updateConfig",   orphanRemoval=true)
    private List<C> cs = new ArrayList<C>();
}


@Entity
@Table(name = "T_C")
@Cacheable
class C{
    @ManyToOne
    @JoinColumn(name = "b_id", nullable = false)
    private B b;
}

这三个对象都是全局的配置对象,很少修改,适合缓存,其中B比较关键,它和A,C都有管理,和A是单向的多对一管理,和C是双向一对多关联,C是一个值对象,只有通过B才能访问到它。

这一节里主要探讨Spring JPA Data里如何使用查询缓存

参考 这篇文章,关键的几点:

  • 在repository方法上加Cache注解

    public interface ServiceRepository extends CrudRepository<Service, Long>, JpaSpecificationExecutor<Service> {
      @Cacheable("merchantServices")
      @Query("select s from Service s JOIN s.statusList sas where s.status=?1 and s.priviligedUser.priviligedUserType IN (2,4) and (s.id IN (select st.id from Service st inner join st.tags tag where tag IN (?3)) or s.serviceType IN (?2)) and sas.active=true and sas.transactorType=?4 ORDER BY s.name")
      List<Service> getAllMerchantServicesByStatusTypeAndTags(ServiceStatus status, List<ServiceType> type, List<String> tags, TransactorType transactor);
    }
    
  • 在Spring里配置

<?xml version="1.0" encoding="UTF-8"?>
<beans
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:cache="http://www.springframework.org/schema/cache"
    xmlns:mvc="http://www.springframework.org/schema/mvc"
    xmlns:context="http://www.springframework.org/schema/context" xmlns:tx="http://www.springframework.org/schema/tx"
    xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
        http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.0.xsd
        http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd
        http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd
        http://www.springframework.org/schema/cache
        http://www.springframework.org/schema/cache/spring-cache.xsd"
    default-autowire="byName">

    <tx:annotation-driven />

    <cache:annotation-driven />

    <bean id="cacheManager" class="org.springframework.cache.support.SimpleCacheManager">
      <property name="caches">
         <set>
          <bean class="org.springframework.cache.concurrent.ConcurrentMapCacheFactoryBean" p:name="merchantServices"/>
        </set>
      </property>
    </bean>
</beans>
  • 添加Hibernate的配置
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
        "-//Hibernate/Hibernate Configuration DTD 3.0//EN"
        "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
    <session-factory>
        <property name="hibernate.default_batch_fetch_size">16</property>
        <property name="hibernate.max_fetch_depth">5</property>

        <property name="hibernate.cache.use_query_cache">true</property>
        <property name="hibernate.cache.use_second_level_cache">true</property>
        <property name="hibernate.generate_statistics">true</property>
        <property name="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</property>
        <property name="hibernate.c3p0.timeout">300</property>

    </session-factory>
</hibernate-configuration>
  • 添加EhCache配置
<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd">

<diskStore path="/home/prayag/cache_"/>
<defaultCache
        eternal="false"
        maxElementsInMemory="1000"
        overflowToDisk="true"
        diskPersistent="true"
        timeToLiveSeconds="300"
        />
</ehcache>

以上配置需在自己的环境中验证,另外有一些疑问(1)当对象保存更新或删除时,查询缓存会自动失效吗?(2)必须显示指定@Query吗?用Spring-Data-JPA的默认方法是否可行?(3)SimpleCacheManager和EhCache的配置好像不匹配。Which is referenced as ehcache.xml in resources/hibernate.cfg.xml.

相关文章

  1. 基于-SLF4J-MDC-机制的日志链路追踪配置属性

    ums: # ================ 基于 SLF4J MDC 机制的日志链路追踪配置属性 ================ mdc: # 是否支持基于 SLF4J MDC

  2. ajax-跨域访问

    ajax 跨域访问 &lt;!DOCTYPE html&gt; &lt;html xmlns:th="http://www.w3.org/1999/xhtml"&gt; &lt;head&gt;

  3. 给第三方登录时用的数据库表-user_connection-与-auth_token-添加-redis-cache

    spring: # 设置缓存为 Redis cache: type: redis # redis redis: host: 192.168.88.88 port

  4. Java动态代理

    Jdk动态代理 通过InvocationHandler和Proxy针对实现了接口的类进行动态代理,即必须有相应的接口 应用 public class TestProxy { public

  5. Java读取classpath中的文件

    public void init() { try { //URL url = Thread.currentThread().getContextClassLo

随机推荐

  1. 基于-SLF4J-MDC-机制的日志链路追踪配置属性

    ums: # ================ 基于 SLF4J MDC 机制的日志链路追踪配置属性 ================ mdc: # 是否支持基于 SLF4J MDC

  2. ajax-跨域访问

    ajax 跨域访问 &lt;!DOCTYPE html&gt; &lt;html xmlns:th="http://www.w3.org/1999/xhtml"&gt; &lt;head&gt;

  3. 给第三方登录时用的数据库表-user_connection-与-auth_token-添加-redis-cache

    spring: # 设置缓存为 Redis cache: type: redis # redis redis: host: 192.168.88.88 port

  4. Java动态代理

    Jdk动态代理 通过InvocationHandler和Proxy针对实现了接口的类进行动态代理,即必须有相应的接口 应用 public class TestProxy { public

  5. Java读取classpath中的文件

    public void init() { try { //URL url = Thread.currentThread().getContextClassLo