Весенняя миграция с 4.1.X на 4.2.x Проблема кеширования 2-го уровня для метода LocalSessionFactoryBean.setCacheRegionFactory (RegionFactory cacheRegionFactory)

Я обновляю проект с Spring-4.1.6.RELEASE до Spring-4.2.1.RELEASE и Hibernate (core и Ehcache) с 4.3.9.Final до 5.0.1.Final.

В Spring-4.1.6.RELEASE есть метод

org.springframework.orm.hibernate4.LocalSessionFactoryBean.setCacheRegionFactory(RegionFactory cacheRegionFactory)

Но в Spring 4.2.1.RELEASE такого метода в классе нет

org.springframework.orm.hibernate5.LocalSessionFactoryBean

Поэтому, когда я устанавливаю свойство в bean-компоненте сеанса спящего режима, чтобы включить кеширование второго уровня, используя

<prop key="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</prop>

Выдается следующая ошибка:

WARN : org.springframework.beans.factory.support.DefaultListableBeanFactory - Bean creation exception on FactoryBean type check: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userDao' defined in class path resource [application-context.xml]: Cannot resolve reference to bean 'transactionManager' while setting bean property 'transactionManager'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'transactionManager' defined in class path resource [application-context.xml]: Cannot resolve reference to bean 'sessionFactory' while setting bean property 'sessionFactory'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory' defined in class path resource [application-context.xml]: Error setting property values; nested exception is org.springframework.beans.NotWritablePropertyException: Invalid property 'cacheRegionFactory' of bean class [org.springframework.orm.hibernate5.LocalSessionFactoryBean]: Bean property 'cacheRegionFactory' is not writable or has an invalid setter method. Does the parameter type of the setter match the return type of the getter?
WARN : org.springframework.web.context.support.XmlWebApplicationContext - Exception encountered during context initialization - cancelling refresh attempt
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'homeController': Injection of autowired dependencies failed; nested exception is org.springframework.beans.factory.BeanCreationException: Could not autowire field: private com.envers.spring.dao.UserDAO com.envers.spring.HomeController.userDao; nested exception is org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [com.envers.spring.dao.UserDAO] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
Related cause: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userDao' defined in class path resource [application-context.xml]: Cannot resolve reference to bean 'transactionManager' while setting bean property 'transactionManager'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'transactionManager' defined in class path resource [application-context.xml]: Cannot resolve reference to bean 'sessionFactory' while setting bean property 'sessionFactory'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory' defined in class path resource [application-context.xml]: Error setting property values; nested exception is org.springframework.beans.NotWritablePropertyException: Invalid property 'cacheRegionFactory' of bean class [org.springframework.orm.hibernate5.LocalSessionFactoryBean]: Bean property 'cacheRegionFactory' is not writable or has an invalid setter method. Does the parameter type of the setter match the return type of the getter?
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:334)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1214)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:543)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:305)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:301)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:196)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:772)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:834)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:537)
    at org.springframework.web.servlet.FrameworkServlet.configureAndRefreshWebApplicationContext(FrameworkServlet.java:667)
    at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:633)
    at org.springframework.web.servlet.FrameworkServlet.createWebApplicationContext(FrameworkServlet.java:681)
    at org.springframework.web.servlet.FrameworkServlet.initWebApplicationContext(FrameworkServlet.java:552)
    at org.springframework.web.servlet.FrameworkServlet.initServletBean(FrameworkServlet.java:493)
    at org.springframework.web.servlet.HttpServletBean.init(HttpServletBean.java:136)
    at javax.servlet.GenericServlet.init(GenericServlet.java:158)
    at org.apache.catalina.core.StandardWrapper.initServlet(StandardWrapper.java:1231)
    at org.apache.catalina.core.StandardWrapper.loadServlet(StandardWrapper.java:1144)
    at org.apache.catalina.core.StandardWrapper.load(StandardWrapper.java:1031)

Как настроить кеширование второго уровня в Spring-4.2.1.RELEASE и Hibernate-5.0.1.FINAL? Какой будет замена кода в Hibernate-5, чтобы включить кеширование второго уровня?

Пожалуйста, помогите с этим вопросом миграции. Заранее спасибо.


person Nirav Patel    schedule 30.09.2015    source источник


Ответы (1)


tl; dr version: измените пакет класса HibernateTransactionManager с org.springframework.orm.hibernate4 на org.springframework.orm.hibernate5.

Я смог заставить это работать, изменив это:

<!-- Set up default hibernate properties. -->
<bean id="hibernateProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
    <property name="properties">
        <props>
            <prop key="hibernate.dialect">org.hibernate.dialect.H2Dialect</prop>
            <prop key="hibernate.hbm2ddl.auto">create</prop>
            <prop key="hibernate.show_sql">true</prop>
            <prop key="hibernate.cache.use_second_level_cache">true</prop>
            <prop key="hibernate.cache.use_query_cache">true</prop>
        </props>
    </property>
</bean>

<bean id="cacheRegionFactory" class="org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory">
    <constructor-arg index="0" ref="hibernateProperties" />
</bean>

<bean id="sessionFactory" class="org.nrg.framework.orm.hibernate.AggregatedAnnotationSessionFactoryBean"
      p:cacheRegionFactory-ref="cacheRegionFactory" p:dataSource-ref="dataSource"
      p:hibernateProperties-ref="hibernateProperties" p:namingStrategy-ref="namingStrategy" />

<bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager" p:sessionFactory-ref="sessionFactory" />

К этому:

<!-- Set up default hibernate properties. -->
<bean id="hibernateProperties" class="org.springframework.beans.factory.config.PropertiesFactoryBean">
    <property name="properties">
        <props>
            <prop key="hibernate.dialect">org.hibernate.dialect.H2Dialect</prop>
            <prop key="hibernate.hbm2ddl.auto">create</prop>
            <prop key="hibernate.show_sql">true</prop>
            <prop key="hibernate.cache.use_second_level_cache">true</prop>
            <prop key="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory</prop>
            <prop key="hibernate.cache.use_query_cache">true</prop>
        </props>
    </property>
</bean>

<bean id="sessionFactory" class="org.nrg.framework.orm.hibernate.AggregatedAnnotationSessionFactoryBean"
      p:dataSource-ref="dataSource" p:hibernateProperties-ref="hibernateProperties" p:physicalNamingStrategy-ref="namingStrategy" />

<bean id="transactionManager" class="org.springframework.orm.hibernate5.HibernateTransactionManager" p:sessionFactory-ref="sessionFactory" />

Вот большие изменения:

<prop key="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory</prop>

Вы уже сделали эту часть.

Другие изменения:

  • Изменение p: namingStrategy-ref на p: physicalNamingStrategy-ref (это потребовало изменения в моей реализации пользовательского именования, но довольно легко)
  • Удаление объявления bean-компонента SingletonEhCacheRegionFactory
  • Удаление параметра свойства p: cacheRegionFactory-ref
  • Изменение пакета класса HibernateTransactionManager с org.springframework.orm.hibernate4 на org.springframework.orm.hibernate5

Я думаю, что последнее, вероятно, самое важное, что вам нужно изменить.

В целом, я бы предпочел иметь типобезопасную возможность устанавливать диспетчер кеш-области через bean-компонент, а не установку значения свойства произвольной формы, но это исправит нас, пока я не найду другой способ сделать это.

person Spanky Quigman    schedule 17.11.2015
comment
Я изменил версию hibernate TransactionManager с 4 на 5, но проблема связана с классом org.hibernate.cache.ehcache.EhCacheRegionFactory. Если я использую org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory, тогда он работает правильно. Я не знаю, какие изменения необходимы для использования EhCacheRegionFactory. - person Nirav Patel; 17.11.2015