I an new to use hibernate caching (first level, 2nd level and query cache).
My project is configured using Spring MVC and JPA.
I am testing first level cache using JUnit test case below.
public class FirstLevelCacheTest { private static final Logger logger = LoggerFactory.getLogger(FirstLevelCacheTest.class); @PersistenceContext private EntityManager entityManager; @Test public void testFirstLevelCacheTest() { Long clientId = 1L; // fetch the client entity from database first time Client client1 = entityManager.find(Client.class, clientId); logger.debug("Client Name : {}", client1.getName()); // fetch the client entity again client1 = entityManager.find(Client.class, clientId); logger.debug("Client Name : {}", client1.getName()); } }
And my entity class is defined as :
@Entity @JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL) @Table(name = "client") public class Client extends BaseModel { // instance variable declaration // getter and setter methods for instance variables }
This should execute native query once in case first level cache is by default enabled. But I am getting result below while executing this query:
Hibernate: select client0_.id as id0_0_, client0_.created as created0_0_, client0_.createdBy as createdBy0_0_, client0_.updated as updated0_0_, client0_.updatedBy as updatedBy0_0_, client0_.contactNo as contactNo0_0_, client0_.contactPerson as contactP7_0_0_, client0_.contactPersonEmail as contactP8_0_0_, client0_.contactPersonNo as contactP9_0_0_, client0_.email as email0_0_, client0_.name as name0_0_ from client client0_ where client0_.id=? [main] DEBUG Client Name : Client1 Hibernate: select client0_.id as id0_0_, client0_.created as created0_0_, client0_.createdBy as createdBy0_0_, client0_.updated as updated0_0_, client0_.updatedBy as updatedBy0_0_, client0_.contactNo as contactNo0_0_, client0_.contactPerson as contactP7_0_0_, client0_.contactPersonEmail as contactP8_0_0_, client0_.contactPersonNo as contactP9_0_0_, client0_.email as email0_0_, client0_.name as name0_0_ from client client0_ where client0_.id=? [main] DEBUG Client Name : Client1
Below is my persistence related configurations:
@Configuration @EnableTransactionManagement public class PersistanceConfig { // injection private String[] PACKAGES_TO_SCAN = new String[] { "com.mypackage1", "com.mypackage2" }; @Bean public DataSource dataSource() { // dataSource setting 'com.mysql.jdbc.Driver' as a jdbc driver } private Properties jpaProperties() { Properties properties = new Properties(); properties.put(AvailableSettings.DIALECT, hibernateDialect); properties.put(AvailableSettings.SHOW_SQL, hibernateShowSql); // 2nd level cache properties.put("hibernate.cache.use_second_level_cache", true); properties.put("hibernate.cache.region.factory_class", "org.hibernate.cache.ehcache.EhCacheRegionFactory"); return properties; } @Bean public LocalContainerEntityManagerFactoryBean entityManagerFactory() { // entity manager settings using dataSource and jpaProperties } @Bean public JpaTransactionManager transactionManager() { // transaction manager settings using entityManagerFactory } }
Can anybody help me to sort out an issue or anything I am doing wrong ?
Thanks in advance !
Advertisement
Answer
You need to annotate the test method with @Transactional
or use the Spring TransactionTemplate
.
Even if retrieving an entity doesn’t require a transaction, grouping multiple calls inside one would clearly specify the Persistence Context boundaries (where it is meant to start and where it should end).
To replicate the 1st Level Cache you need the same Unit Of Work throughout your test method, and annotating the test with @Transactional
would start a transaction (a Spring logical transaction that’s bound to the current executing Persistence Context transaction which correlates to the actual physical database transaction).
When the test method ends the Transaction is usually roll-back so no changes will be propagated to any successive test, but within the currently executing test method you get to see your own changes, which is the Isolation property in ACID.