如何使用Spring数据JPA启用基本缓存

如何使用Spring数据JPA启用基本缓存,spring,caching,spring-boot,spring-data,spring-data-jpa,Spring,Caching,Spring Boot,Spring Data,Spring Data Jpa,我正在尝试使用Spring数据JPA启用基本缓存。但是我无法理解为什么DAO方法仍然在查询数据库而不是使用缓存 给定以下Spring Boot 1.5.1应用程序 import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cache.annotation.Enab

我正在尝试使用Spring数据JPA启用基本缓存。但是我无法理解为什么DAO方法仍然在查询数据库而不是使用缓存

给定以下Spring Boot 1.5.1应用程序

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;

@SpringBootApplication
@EnableCaching
public class Server{

    public static void main(String[] args) {
        SpringApplication.run(Server.class, args);
    }
}
控制器

@Controller
public class PasswordsController {

    @Autowired
    private PasswordService service;

    @SuppressWarnings("unchecked")
    @RequestMapping("/passwords.htm")
    public void passwords(Map model,
            HttpServletRequest request) {
        model.put("passwords", service.getPasswords(request));
    }
...
服务

@Service
@Transactional
public class PasswordService extends BaseService {

    @Autowired
    private PasswordJpaDao passwordDao;

    public Collection<Password> getPasswords(HttpServletRequest request) {
        Collection<Password> passwords = passwordDao.getPasswords(params);
        return passwords;
    }
...
@服务
@交易的
公共类PasswordService扩展了BaseService{
@自动连线
私人密码jpadao passwordDao;
公共集合getPasswords(HttpServletRequest请求){
集合密码=passwordDao.getPasswords(params);
返回密码;
}
...
接口

@Transactional
public interface PasswordJpaDaoCustom {

    public Collection<Password> getPasswords(PasswordSearchParameters params);
}
@Transactional
公共接口密码JPADAOCUSTOM{
公共集合getPasswords(PasswordSearchParameters参数);
}
和实施

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import javax.transaction.Transactional;

import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Repository;

import com.crm.entity.Password;
import com.crm.search.PasswordSearchParameters;

@Transactional
@Repository
public class PasswordJpaDaoImpl implements PasswordJpaDaoCustom {

    @PersistenceContext
    private EntityManager em;

    @Override
    @Cacheable("passwords")
    public Collection<Password> getPasswords(PasswordSearchParameters params) {
       System.err.println("got here");
       return em.createQuery(hql, Password.class);  
    }
...
import javax.persistence.EntityManager;
导入javax.persistence.PersistenceContext;
导入javax.persistence.Query;
导入javax.transaction.Transactional;
导入org.springframework.cache.annotation.Cacheable;
导入org.springframework.stereotype.Repository;
导入com.crm.entity.Password;
导入com.crm.search.PasswordSearchParameters;
@交易的
@存储库
公共类PasswordJpaDaoImpl实现了PasswordJpaDaoCustom{
@持久上下文
私人实体管理者;
@凌驾
@可缓存(“密码”)
公共集合getPasswords(PasswordSearchParameters参数){
System.err.println(“到达这里”);
返回em.createQuery(hql,Password.class);
}
...
Maven依赖项

<!-- Spring Boot start -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-jdbc</artifactId>
</dependency>

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<!-- Spring Boot end -->

<dependency>
    <groupId>mysql</groupId>
    <artifactId>mysql-connector-java</artifactId>
</dependency>

<dependency>
    <groupId>org.javassist</groupId>
    <artifactId>javassist</artifactId>
</dependency>


org.springframework.boot
弹簧启动机自由标记器
org.springframework.boot
SpringBootStarterWeb
org.springframework.boot
弹簧启动安全
org.springframework.boot
弹簧靴启动器jdbc
org.springframework.boot
spring引导启动器数据jpa
org.springframework.boot
springbootstarter缓存
mysql
mysql连接器java
org.javassist
javassist

我知道Spring Boot会隐式地使用
ConcurrentHashMap
进行缓存,而不需要任何特定的配置


但是
getPasswords()
dao方法总是被调用,而不是使用缓存。这是为什么?

是的,spring boot默认使用
ConcurrentHashMap
进行缓存,而代码的问题是您没有为
密码
缓存设置任何
键,因此它每次都调用数据库以获取da助教

因此,您需要使用
params
对象变量输入键(任何唯一标识符),如下所示:

@Cacheable(value="passwords", key="#params.id")//any unique identifier
public Collection<Password> getPasswords(PasswordSearchParameters params) {
   System.err.println("got here");
   return em.createQuery(hql, Password.class);  
}
@Cacheable(value=“passwords”,key=“#params.id”)//任何唯一标识符
公共集合getPasswords(PasswordSearchParameters参数){
System.err.println(“到达这里”);
返回em.createQuery(hql,Password.class);
}

我无法提供来自“params”、“params”的唯一密钥只是搜索表单输入字段的封装,所有字段都可以为null。如果所有字段都为null,则返回所有密码。我是否仍可以缓存方法调用?否,您将获得
java.lang.IllegalArgumentException:null key returned for cache operation
您可以设置一些默认键,例如“-1”或其他(特定于应用程序)谢谢,我将
Cacheable
注释移动到了服务层,并使用了会话id来代替
@Cacheable(value=“passwords”,key=“#request.session.id”)
。如果它们以
@RequestParam
的形式出现,您可以设置
defaultValue
,您可以查看这里: