Настройка спящего режима второго уровня кеша - PullRequest
5 голосов
/ 03 марта 2011

Я новичок в спящем и весеннем режимах и экспериментирую с кешем второго уровня.Но, похоже, не работает.У меня есть следующий тестовый класс:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:applicationContext.xml" })
@TransactionConfiguration
@Transactional
public class CacheTest extends AbstractTransactionalJUnit4SpringContextTests
{   
    @Test
        public void testCache1() 
        {
        System.out.println("Running testCache1");
        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
        MutableDAO<AppUser> appUserDAO = new MutableDAOImpl<AppUser>(AppUser.class, (SessionFactory) ctx.getBean("OnMediaSessionFactory"), 10);
        assertNotNull("AppUser DAO is null.", appUserDAO);

        SessionFactory sessionFactory = (SessionFactory)ctx.getBean("OnMediaSessionFactory");
        long numberOfUsers = appUserDAO.countAll();

        System.out.println("Number of rows :" + numberOfUsers);
        final String cacheRegion = AppUser.class.getCanonicalName();

        SecondLevelCacheStatistics settingsStatistics = sessionFactory.getStatistics().
            getSecondLevelCacheStatistics(cacheRegion);
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        appUserDAO.findAll();
        stopWatch.stop();
        System.out.println("Query time : " + stopWatch.getTotalTimeSeconds());
        System.out.println(settingsStatistics);
     }

    @Test
    public void testCache2() 
    {
        System.out.println("Running testCache2");
        ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
        MutableDAO<AppUser> appUserDAO = new MutableDAOImpl<AppUser>(AppUser.class, (SessionFactory) ctx.getBean("OnMediaSessionFactory"), 10);
        assertNotNull("AppUser DAO is null.", appUserDAO);

        SessionFactory sessionFactory = (SessionFactory)ctx.getBean("OnMediaSessionFactory");
        long numberOfUsers = appUserDAO.countAll();

        System.out.println("Number of rows :" + numberOfUsers);
        final String cacheRegion = AppUser.class.getCanonicalName();

        SecondLevelCacheStatistics settingsStatistics = sessionFactory.getStatistics().
            getSecondLevelCacheStatistics(cacheRegion);
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        appUserDAO.findAll();
        stopWatch.stop();
        System.out.println("Query time : " + stopWatch.getTotalTimeSeconds());
        System.out.println(settingsStatistics);
     }
}

, и у меня есть

<prop key="hibernate.show_sql">false</prop>
<prop key="hibernate.format_sql">true</prop>
<prop key="hibernate.use_sql_comments">true</prop>
<prop key="hibernate.cache.use_query_cache">true</prop>
<prop key="hibernate.cache.use_second_level_cache">true</prop>
<prop key="hibernate.generate_statistics">true</prop>
<prop key="hibernate.cache.use_structured_entries">true</prop>

, но я получаю вывод, как это:

Running testCache1
Number of rows :81
Query time : 0.129
SecondLevelCacheStatistics[hitCount=0,missCount=0,putCount=81,elementCountInMemory=81,elementCountOnDisk=0,sizeInMemory=219634]
Running testCache2
Number of rows :81
Query time : 0.063
SecondLevelCacheStatistics[hitCount=0,missCount=0,putCount=81,elementCountInMemory=81,elementCountOnDisk=0,sizeInMemory=219634]

что мне нужно сделать, чтобызаставить его работать?

Ответы [ 2 ]

3 голосов
/ 03 марта 2011

Ваш тест выглядит очень странно, вы создаете новый контекст приложения для каждого теста, поэтому Hibernate SessionFactory не выживает между тестами, как и его кэш второго уровня.

Правильный тест будет выглядеть так:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:applicationContext.xml" })
public class CacheTest extends AbstractTransactionalJUnit4SpringContextTests
{   
    @Autowired
    private MutableDAO<AppUser> appUserDAO;

    @Autowired
    private SessionFactory sessionFactory;

    private TransactionTemplate tx;

    @Autowired
    public void setPtm(PlatformTransactionManagement ptm) {
        tx = new TransactionTemplate(ptm);
    }

    @Test
    public void doTestCache() {
        // Using programmatic transaction management since we need 2 transactions
        // inside the same method

        // 1st attempt
        tx.execute(new TransactionCallbackWithoutResult() {
            public void doInTransactionWithoutResult(TransactionStatus status) {
                testCache();
            }
        });

        // 2nd attempt
        tx.execute(new TransactionCallbackWithoutResult() {
            public void doInTransactionWithoutResult(TransactionStatus status) {
                testCache();
            }
        });

    }

    public void testCache() {
        long numberOfUsers = appUserDAO.countAll();

        System.out.println("Number of rows :" + numberOfUsers);
        final String cacheRegion = AppUser.class.getCanonicalName();

        SecondLevelCacheStatistics settingsStatistics = sessionFactory.getStatistics().
            getSecondLevelCacheStatistics(cacheRegion);
        StopWatch stopWatch = new StopWatch();
        stopWatch.start();
        appUserDAO.findAll();
        stopWatch.stop();
        System.out.println("Query time : " + stopWatch.getTotalTimeSeconds());
        System.out.println(settingsStatistics);
     }      
 }
2 голосов
/ 03 марта 2011

Прежде всего, помните, что Hibernate по умолчанию не использует никакой провайдер кеша.Итак, вам понадобится «внешний» провайдер кеша для кеша Hibernate 2L.Для ответа я буду использовать ehcache и Hibernate 3.3.Обратите внимание, что конфигурация была изменена в более поздних версиях Hibernate, поэтому прочитайте документы для точной версии, которую вы используете.

В вашей конфигурации Hibernate вы пропустили одну часть, которая указывает Hibernate на фактического поставщика,Свойство hibernate.cache.provider_class делает это для Hibernate 3.3.Установите для него значение net.sf.ehcache.hibernate.SingletonEhCacheProvider

Теперь вам также понадобится файл ehcache.xml, например:

<?xml version="1.0" encoding="UTF-8"?>
<ehcache>

    <diskStore path="./cache" />

    <defaultCache   maxElementsInMemory="10000" 
                    eternal="true"
                    overflowToDisk="true"
                    diskPersistent="true" 
                    diskExpiryThreadIntervalSeconds="120"
                    memoryStoreEvictionPolicy="FIFO" />

    <cache  name="com.mycompany.jpa.MyEntity" 
            maxElementsInMemory="50" 
            overflowToDisk="true" />

    <cache  name="org.hibernate.cache.StandardQueryCache" 
            maxElementsInMemory="50" 
            overflowToDisk="true" />

    <cache  name="org.hibernate.cache.UpdateTimestampsCache" 
            maxElementsInMemory="5000"
            overflowToDisk="true" />

</ehcache>

Вы не показывали свой DAO, поэтому яне уверен, что это правильно или нет.Обратите внимание, что вы всегда должны быть откровенны с кешем, так как он предназначен для использования решения для конкретных мест, а не общего решения для всего.Это означает, что в вашем DAO вы бы добавили подсказку к запросу, указав, что ваш запрос кешируется (из вашего теста кажется, что вам нужен кеш запросов, а не только кеширование сущностей).

Если вы все еще не можете заставить его работать, см. Приложение в следующей JIRA.Он содержит проект maven с включенным кэшем, поэтому вы можете сравнить его с вашим кодом:

https://issues.jboss.org/browse/JBPAPP-4224

...