쿼리 캐시가 필요한 이유

HQL에서 직원을 가져오는 예제를 다시 작성해 보겠습니다.

Employee director1 = session.createQuery("from Employee where id = 4").uniqueResult();
Employee director2 = session.createQuery("from Employee where id = 4").uniqueResult();

assertTrue(director1 != director2);

이러한 쿼리의 결과는 첫 번째 또는 두 번째 수준 캐시에 저장되지 않습니다 .

이것이 바로 쿼리 캐시를 사용할 수 있는 곳입니다 . 또한 기본적으로 비활성화되어 있습니다. 활성화하려면 구성 파일에 다음 행을 추가하십시오.

<property name="hibernate.cache.use_query_cache" value="true"/>

그러나 이것은 해결책의 절반에 불과합니다. 쿼리 캐시를 활성화했지만 캐시할 쿼리 결과도 지정해야 합니다. 이것은 쿼리에 작성해야 합니다.

Query query = session.createQuery("from Employee where id = 4");
query.setCacheable(true);
Employee director1 = query.uniqueResult();

쿼리 캐시는 두 번째 수준 캐시와 유사합니다. 그러나 이와는 달리 여기서 캐시 데이터의 핵심은 개체 식별자가 아니라 쿼리 매개 변수 집합입니다. 그리고 데이터 자체는 쿼리 기준과 일치하는 개체의 식별자입니다. 따라서 이 캐시를 두 번째 수준 캐시와 함께 사용하는 것이 합리적입니다.

캐시 지우기

캐시로 작업할 때 중요한 작업 중 하나는 캐시된 개체가 변경되고 캐시에서 제거(또는 업데이트)되는지 확인하는 것입니다. 최대 절전 모드는 이것을 매우 잘 수행합니다. 때때로 그는 "이해할 수없는 상황에서 캐시를 지우십시오"라는 규칙에 따라 안내되는 것처럼 보입니다.

HQL을 통해 사용자 데이터를 업데이트한다고 가정해 보겠습니다.

Query query = session.createQuery("update Employee set name=’Alex’ where id = 4")
query. executeUpdate();

Hibernate는 데이터베이스에서 무엇이 변경되었는지 정확히 알 수 없지만 Employee 객체를 변경하고 있다는 것은 알고 있습니다. 따라서 이 쿼리를 실행한 후 Hibernate는 직원 유형의 모든 객체를 캐시에서 삭제할 것입니다.

그러나 NativeQuery는 훨씬 더 흥미롭게 작동합니다.

Query nativeQuery = session.createNativeQuery("update employee set name=’Alex’ where id = 4")
nativeQuery.executeUpdate();

데이터베이스에 대한 기본 SQL 쿼리가 실행되었습니다. 이는 데이터베이스에서 무언가가 변경되었음을 의미합니다. 요청이 executeUpdate() 메서드에서 호출되었습니다 . 따라서 이 경우 Hibernate는 안전하게 플레이하고 캐시에서 모든 유형 의 모든 개체를 제거합니다 .

어때요? 당신은 무해한 요청을 호출하고 그에 대한 응답으로 Hibernate는 캐시에서 모든 데이터를 지웁니다! 이것은 베이스와 다른 물체를 보관하는 것보다 확실히 낫지만 그게 전부입니다!

따라서 Hibernate 제작자는 이 경우 Hibernate를 돕는 방법을 신속하게 파악했습니다. 캐시에서 제거할 엔터티 유형을 지정할 수 있습니다.

Query nativeQuery = session.createNativeQuery("update employee set name=’Alex’ where id = 4");
nativeQuery.unwrap(org.hibernate.SQLQuery.class).addSynchronizedEntityClass(Employee.class);
nativeQuery.executeUpdate();
비고 . 기본 선택 쿼리는 캐시를 플러시하지 않고 삽입, 업데이트, 삭제, 프로시저 호출 등만 수행합니다.

수동 캐시 지우기

특정한 이유로 캐시에서 개체를 직접 삭제해야 할 수 있습니다. 이것은 다른 방법으로 수행될 수 있습니다.

참고 . 캐시의 객체는 region 이라는 그룹에 저장됩니다 . 기본적으로 지역 이름은 클래스 이름과 동일합니다. 따라서 com.codegym.Employee 유형의 개체가 있는 경우 모든 개체가 " com.codegym.employee " 라는 이름으로 그룹(지역)에 저장됩니다 .

캐시에 액세스하여 무언가를 수행하려면 SessionFactory 객체와 getCache () 메서드를 사용하여 수행할 수 있습니다 .

session.getSessionFactory().getCache().evictQueryRegion("com.codegym.employee”);

모든 그룹(지역)에서 데이터를 삭제하려면 다음 쿼리를 실행해야 합니다.

session.getSessionFactory().getCache().evictAllRegions();

캐시에서 하나의 개체를 제거하려면 이름(유형)과 ID를 전달해야 합니다. 다음 두 가지 방법으로 이 작업을 수행할 수 있습니다.

session.getSessionFactory().getCache().evictEntityData("Employee, 4);

session.getSessionFactory().getCache().evictEntityData(com.codegym.Employee.class, 4);

특정 개체가 캐시에 있는지 확인할 수도 있습니다.

session.getSessionFactory().getCache().containsEntity("Employee, 4);
session.getSessionFactory().getCache().containsEntity(com.codegym.Employee.class, 4);