Когда я интегрирую Spring JPA Data и Spring Cache, возникает странное поведение, которое я не могу объяснить.Странное поведение при интеграции Spring JPA Data и Spring Cache
Я использую Spring Boot для настройки моего демонстрационного проекта. Код ниже.
Мой конфиг боб:
@Configuration
public class AppConfig {
@Bean
public CacheManager cacheManager() {
return new ConcurrentMapCacheManager("Person");
}
}
Моя сущность боб.
@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;
}
}
My 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.
Эти 2 переменные точно указывают на одну и ту же ссылку, даже если это прокси-объект. Зачем вызывать метод той же ссылки, вызывающий 2 результата разности?
Я также замечаю, что аннотация @Query работает хорошо. В ссылках JpaRepository и PersonRepository используется настроенный SQL.
Возможно, некоторые различия между тем, как Spring Cache и Spring JPA Data генерируют прокси-советник. Возможно ли это здесь?
Подпись фактического метода настраивается для определения. В первом это 'PersonRepository.findOne', в другом -' JpaRepository.findOne'. При использовании Spring Data уже много проксирования, и добавление кеширования не станет более ясным. Также вам действительно нужно Spring Caching или вы действительно хотите иметь кеш второго уровня, управляемый провайдером JPA. Кэши служат совершенно другой цели. –