【发布时间】:2016-04-14 20:58:57
【问题描述】:
当我集成 Spring JPA Data 和 Spring Cache 时,出现了一个我无法解释的奇怪行为。
我正在使用 Spring Boot 来设置我的演示项目。代码如下。
我的配置 bean:
@Configuration
public class AppConfig {
@Bean
public CacheManager cacheManager() {
return new ConcurrentMapCacheManager("Person");
}
}
我的实体 bean。
@Entity
public class Person implements Serializable {
private static final long serialVersionUID = 2263555241909370718L;
@Id
@GeneratedValue
private Long id;
private String name;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
我的 JPA 界面。我覆盖了 JpaRepository 中的一些方法并添加了@cachable 注释。
public interface PersonRepository extends JpaRepository<Person, Long> {
@Override
@CacheEvict(value = "Person", allEntries = true)
public void delete(Long id);
@Cacheable("Person")
public Person findByName(String name);
@Override
@Query("select p from Person p where p.id = :id + 1L")
@Cacheable("Person")
public Person findOne(@Param("id") Long id);
}
我的单元测试类
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = SpringDataDemoApplication.class)
public class SpringDataDemoApplicationTests {
@Autowired
private PersonRepository personRepository;
@Autowired
private CacheManager cacheManager;
@Before
public void setup() {
Person p1 = new Person();
p1.setName("Chris");
personRepository.save(p1);
}
@Test
public void test2() {
JpaRepository<Person, Long> jpaRepository = personRepository;
Person p = personRepository.findOne(0L);
Assert.assertNotNull(p);
p = personRepository.findOne(0L);
Assert.assertNotNull(p);
System.err.println("---------------------------------------");
p = jpaRepository.findOne(0L);
Assert.assertNotNull(p);
p = jpaRepository.findOne(0L);
Assert.assertNotNull(p);
}
}
输出很奇怪。
Hibernate: insert into person (id, name) values (default, ?)
Hibernate: select person0_.id as id1_0_, person0_.name as name2_0_ from person person0_ where person0_.id=?+1
---------------------------------------
Hibernate: select person0_.id as id1_0_, person0_.name as name2_0_ from person person0_ where person0_.id=?+1
Hibernate: select person0_.id as id1_0_, person0_.name as name2_0_ from person person0_ where person0_.id=?+1
它应该只打印出我期望的一条 sql 语句。 jpaRepository.findOne(0L) 不使用缓存对象。
在我将 PersonRepository 接口分配给其父接口 JpaRepository 后,缓存注释不起作用。
这两个变量完全指向同一个引用,即使它是一个代理对象。为什么调用同一个引用的方法导致两个不同的结果?
我还注意到@Query 注释运行良好。 JpaRepository 和 PersonRepository 引用都使用定制的 SQL。
我想 Spring Cache 和 Spring JPA Data 如何生成代理顾问之间可能存在一些差异。这可能是一个错误吗?
【问题讨论】:
-
正在遍历实际的方法签名以确定。第一个是
PersonRepository.findOne,另一个是JpaRepository.findOne。使用 Spring Data 时已经有很多代理,并且添加缓存不会使其更清晰。您是否真的想要 Spring Caching 或者您是否真的想要由 JPA 提供程序管理的二级缓存。缓存的用途完全不同。
标签: spring spring-data-jpa spring-data spring-cache