Apache-Ignite集成为Hibernate二级缓存无法启动?

时间:2016-07-27 22:19:59

标签: hibernate spring-mvc caching gridgain ignite

我正在尝试将Apache Ignite设置为我项目中的二级Hibernate缓存提供程序,但我遇到了一个奇怪的例外。

配置如下:

  1. 的pom.xml
  2. <!-- Hibernate SessionFactory -->
    <bean id="sessionFactoryHibernate" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
    <property name="dataSource" ref="dataSource"></property>
    <property name="hibernateProperties">
        <props>
            <prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
            <prop key="hibernate.hbm2ddl.auto">true</prop>
            <prop key="hibernate.format_sql">true</prop>
            <prop key="hibernate.show_sql">true</prop>
            <prop key="hibernate.cache.use_query_cache">true</prop>
            <prop key="hibernate.generate_statistics">true</prop>
            <prop key="hibernate.cache.use_second_level_cache">true</prop>
            <prop key="hibernate.cache.region.factory_class">org.apache.ignite.cache.hibernate.HibernateRegionFactory</prop>
            <prop key="org.apache.ignite.hibernate.grid_name">hibernate-grid</prop>
            <prop key="org.apache.ignite.hibernate.default_access_type">READ_ONLY</prop>
        </props>
    </property>
    <property name="packagesToScan" value="com.entity"></property>
    
    1. Spring Hibernate配置文件

          <beans xmlns="http://www.springframework.org/schema/beans"
             xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
             xsi:schemaLocation="
              http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
      
          <!-- Basic configuration for atomic cache. -->
          <bean id="atomic-cache" class="org.apache.ignite.configuration.CacheConfiguration" abstract="true">
          <property name="cacheMode" value="PARTITIONED"/>
          <property name="atomicityMode" value="ATOMIC"/>
          <property name="writeSynchronizationMode" value="FULL_SYNC"/>
          </bean>
      
          <!-- Basic configuration for transactional cache. -->
          <bean id="transactional-cache" class="org.apache.ignite.configuration.CacheConfiguration" abstract="true">
          <property name="cacheMode" value="PARTITIONED"/>
          <property name="atomicityMode" value="TRANSACTIONAL"/>
          <property name="writeSynchronizationMode" value="FULL_SYNC"/>
          </bean>
      
          <bean id="ignite.cfg" class="org.apache.ignite.configuration.IgniteConfiguration">
          <!-- 
              Specify the name of the caching grid (should correspond to the 
              one in Hibernate configuration).
          -->
          <property name="gridName" value="hibernate-grid"/>
      
          <!-- 
              Specify cache configuration for each L2 cache region (which corresponds 
              to a full class name or a full association name).
          -->
          <property name="cacheConfiguration">
              <list>
                  <!--
                      Configurations for entity caches.
                  -->
      <!--             <bean parent="transactional-cache">
                      <property name="name" value="com.mycompany.MyEntity1"/>
                  </bean>
                  <bean parent="transactional-cache">
                      <property name="name" value="com.mycompany.MyEntity2"/>
                  </bean>
                  <bean parent="transactional-cache">
                      <property name="name" value="com.mycompany.MyEntity1.children"/>
                  </bean>
        -->
                  <!-- Configuration for update timestamps cache. -->
                  <bean parent="atomic-cache">
                      <property name="name" value="org.hibernate.cache.spi.UpdateTimestampsCache"/>
                  </bean>
      
                  <!-- Configuration for query result cache. -->
                  <bean parent="atomic-cache">
                      <property name="name" value="org.hibernate.cache.internal.StandardQueryCache"/>
                  </bean>
              </list>
          </property>
      
          </bean>
      
          </beans>
      

      1. 点燃-configuration.xml文件
    2. import java.io.Serializable;
      
      import javax.persistence.Column;
      import javax.persistence.Entity;
      import javax.persistence.GeneratedValue;
      import javax.persistence.GenerationType;
      import javax.persistence.Id;
      import javax.persistence.Index;
      import javax.persistence.Table;
      
      import org.hibernate.annotations.Cache;
      import org.hibernate.annotations.CacheConcurrencyStrategy;
      
      @Entity
      @Table(name = "USER_TYPE", indexes = {
            @Index(columnList = "TYPE_SHORT_NAME", name = "TYPE_SHORT_NAME_UNIQUE_idx", unique = true), })
      @Cache(usage = CacheConcurrencyStrategy.READ_ONLY, region = "userType")
      
      public class UserType implements Serializable {
      
        private static final long serialVersionUID = -628308304752474026L;
      
        @Id
        @GeneratedValue(strategy = GenerationType.AUTO)
        @Column(name = "USER_TYPE_ID")
        private int userTypeId;
      
        @Column(name = "TYPE_SHORT_NAME", length = 20, nullable = false)
        private String typeShortName;
      
        @Column(name = "TYPE_LONG_NAME", length = 255)
        private String typeLongName;
      
        public UserType() {
        }
      
        public UserType(int userTypeId, String typeShortName, String typeLongName) {
            this.userTypeId = userTypeId;
            this.typeShortName = typeShortName;
            this.typeLongName = typeLongName;
        }
      
        @Override
        public int hashCode() {
            final int prime = 31;
            int result = 1;
            result = prime * result + ((typeLongName == null) ? 0 : typeLongName.hashCode());
            result = prime * result + ((typeShortName == null) ? 0 : typeShortName.hashCode());
            result = prime * result + userTypeId;
            return result;
        }
      
        @Override
        public boolean equals(Object obj) {
            if (this == obj)
                return true;
            if (obj == null)
                return false;
            if (!(obj instanceof UserType))
                return false;
            UserType other = (UserType) obj;
            if (typeLongName == null) {
                if (other.typeLongName != null)
                    return false;
            } else if (!typeLongName.equals(other.typeLongName))
                return false;
            if (typeShortName == null) {
                if (other.typeShortName != null)
                    return false;
            } else if (!typeShortName.equals(other.typeShortName))
                return false;
            if (userTypeId != other.userTypeId)
                return false;
            return true;
        }
      
        @Override
        public String toString() {
            return "UserType [userTypeId=" + userTypeId + ", typeShortName=" + typeShortName + ", typeLongName="
                    + typeLongName + "]";
        }
      
        public int getUserTypeId() {
            return userTypeId;
        }
      
        public void setUserTypeId(int userTypeId) {
            this.userTypeId = userTypeId;
        }
      
        public String getTypeShortName() {
            return typeShortName;
        }
      
        public void setTypeShortName(String typeShortName) {
            this.typeShortName = typeShortName;
        }
      
        public String getTypeLongName() {
            return typeLongName;
        }
      
        public void setTypeLongName(String typeLongName) {
            this.typeLongName = typeLongName;
        }
      
      }
      
      1. 实体类
      2. public interface AlphaCacheManager {
        AlphaCache<?, ?> getCache(Class<?> cacheClass);
        }
        
        
        
        
        
        
        import java.util.Map;
        import java.util.concurrent.ConcurrentHashMap;
        
        import org.apache.ignite.Ignite;
        import org.apache.ignite.IgniteCache;
        import org.apache.ignite.Ignition;
        import org.springframework.stereotype.Repository;
        
        
        @Repository
        public class IgniteAlphaCacheManager implements AlphaCacheManager {
        
        private final Ignite ignite;
        private final Map<Class<?>, AlphaCache<?, ?>> caches;
        
        public IgniteAlphaCacheManager() {
          System.out.println("Init cache...");
            ignite = Ignition.start("classpath:/spring/ignite-configuration.xml");
            //ignite = Ignition.start();
            caches = new ConcurrentHashMap<>();
            initCaches();
        }
        
        private void initCaches() {
          IgniteCache<Integer, BaseIdea> igniteCache = ignite.getOrCreateCache(BaseIdea.class.getName());
          AlphaCache<Integer, BaseIdea> ideaCache = new IgniteAlphaCache<>(igniteCache);
          caches.put(BaseIdea.class, ideaCache);
        }
        
        @Override
        public AlphaCache<?, ?> getCache(Class<?> cacheClass) {
          return caches.get(cacheClass);
        }
        
        }
        
        }
        
        1. IgniteAlphaCachemanager
        2. Jul 27, 2016 1:46:43 PM org.apache.catalina.core.StandardContext listenerStart
          SEVERE: Exception sending context initialized event to listener instance of class org.springframework.web.context.ContextLoaderListener
          org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'hibernateStatisticsFactoryBean': Unsatisfied dependency expressed through field 'sessionFactoryHibernate': Error creating bean with name 'sessionFactoryHibernate' defined in class path resource [spring/databaseContext.xml]: Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Cache is not started: userType; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactoryHibernate' defined in class path resource [spring/databaseContext.xml]: Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Cache is not started: userType
              at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:573)
              at org.springframework.beans.factory.annotation.InjectionMetadata.inject(InjectionMetadata.java:88)
              at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor.postProcessPropertyValues(AutowiredAnnotationBeanPostProcessor.java:350)
              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:306)
              at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
              at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
              at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
              at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:756)
              at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:861)
              at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:541)
              at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:444)
              at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:326)
              at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:107)
              at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:4811)
              at org.apache.catalina.core.StandardContext.startInternal(StandardContext.java:5272)
              at org.apache.catalina.util.LifecycleBase.start(LifecycleBase.java:147)
              at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1407)
              at org.apache.catalina.core.ContainerBase$StartChild.call(ContainerBase.java:1397)
              at java.util.concurrent.FutureTask.run(FutureTask.java:266)
              at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
              at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
              at java.lang.Thread.run(Thread.java:745)
          Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactoryHibernate' defined in class path resource [spring/databaseContext.xml]: Invocation of init method failed; nested exception is java.lang.IllegalArgumentException: Cache is not started: userType
              at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1578)
              at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:545)
              at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:482)
              at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:306)
              at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:230)
              at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:302)
              at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:197)
              at org.springframework.beans.factory.config.DependencyDescriptor.resolveCandidate(DependencyDescriptor.java:187)
              at org.springframework.beans.factory.support.DefaultListableBeanFactory.findAutowireCandidates(DefaultListableBeanFactory.java:1208)
              at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1048)
              at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1018)
              at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:570)
              ... 24 more
          Caused by: java.lang.IllegalArgumentException: Cache is not started: userType
              at org.apache.ignite.internal.processors.cache.GridCacheProcessor.publicCache(GridCacheProcessor.java:3143)
              at org.apache.ignite.internal.IgniteKernal.getCache(IgniteKernal.java:2427)
              at org.apache.ignite.cache.hibernate.HibernateRegionFactory.regionCache(HibernateRegionFactory.java:226)
              at org.apache.ignite.cache.hibernate.HibernateRegionFactory.buildEntityRegion(HibernateRegionFactory.java:175)
              at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:364)
              at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1859)
              at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1930)
              at org.springframework.orm.hibernate4.LocalSessionFactoryBuilder.buildSessionFactory(LocalSessionFactoryBuilder.java:372)
              at org.springframework.orm.hibernate4.LocalSessionFactoryBean.buildSessionFactory(LocalSessionFactoryBean.java:454)
              at org.springframework.orm.hibernate4.LocalSessionFactoryBean.afterPropertiesSet(LocalSessionFactoryBean.java:439)
              at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1637)
              at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1574)
              ... 35 more
          

          我在tomcat启动时得到它的例外:

          {{1}}

3 个答案:

答案 0 :(得分:2)

仅当您使用@Cache方法时,才会执行

entityManager.find()注释。这意味着这只适用于主键。另一种方法是使用查询缓存或点燃API。

答案 1 :(得分:1)

您必须为所有区域配置缓存。例如,对于{{1}},您可以将其添加到配置中:

{{1}}

答案 2 :(得分:1)

到目前为止,ignite-cache中不支持注释(作为hibernate的l2缓存)。

如果您不想将每个实体的配置放在缓存配置中,请按照以下步骤进行操作

步骤1.创建一个新类HibernateRegionFactoryForIgnite,如下所示

import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import javax.cache.CacheException;
import org.apache.ignite.Ignition;
import org.apache.ignite.cache.CacheAtomicityMode;
import org.apache.ignite.cache.CacheMode;
import org.apache.ignite.cache.CacheWriteSynchronizationMode;
import org.apache.ignite.cache.hibernate.HibernateCollectionRegionForIgnite;
import org.apache.ignite.cache.hibernate.HibernateEntityRegionForIgnite;
import org.apache.ignite.cache.hibernate.HibernateRegionFactory;
import org.apache.ignite.configuration.CacheConfiguration;
import org.apache.ignite.internal.IgniteKernal;
import org.apache.ignite.internal.processors.cache.IgniteInternalCache;
import org.apache.log4j.Logger;
import org.hibernate.boot.spi.SessionFactoryOptions;
import org.hibernate.cache.spi.CacheDataDescription;
import org.hibernate.cache.spi.CollectionRegion;
import org.hibernate.cache.spi.EntityRegion;
import org.hibernate.cache.spi.TimestampsRegion;
import org.hibernate.cfg.Settings;

@SuppressWarnings("deprecation")
public class HibernateRegionFactoryForIgnite extends HibernateRegionFactory {

    private static final long serialVersionUID = 530290669748711933L;

    public static Logger logger =     Logger.getLogger(HibernateRegionFactoryForIgnite.class);

    private IgniteKernal ignite;
    private IgniteInternalCache<Object, Object> dfltCache;
    private final Map<String, String> regionCaches = new HashMap<>();

    @Override
    public void start(SessionFactoryOptions settings, Properties properties) throws CacheException {
        start(new Settings(settings), properties);
        initializeVariables(properties);
    }

    public void initializeVariables(Properties props) {
        ignite = (IgniteKernal) Ignition.ignite("hibernate-grid");
        String dfltCacheName = props.getProperty(DFLT_CACHE_NAME_PROPERTY);

        for (Map.Entry<Object, Object> prop : props.entrySet()) {
            String key = prop.getKey().toString();
            if (key.startsWith(REGION_CACHE_PROPERTY)) {
                String regionName = key.substring(REGION_CACHE_PROPERTY.length());
                String cacheName = prop.getValue().toString();
                regionCaches.put(regionName, cacheName);
            }
        }

        if (dfltCacheName != null) {
            dfltCache = ((IgniteKernal) ignite).getCache(dfltCacheName);
        }
    }

    private IgniteInternalCache<Object, Object> regionCache(String regionName) throws CacheException {
        String cacheName = regionCaches.get(regionName);
        if (cacheName == null) {
            if (dfltCache != null)
                return dfltCache;
            cacheName = regionName;
        }
        IgniteInternalCache<Object, Object> cache = ((IgniteKernal) ignite).getCache(cacheName);
        if (cache == null)
            throw new CacheException("Cache '" + cacheName + "' for region '" + regionName + "' is not configured.");
        return cache;
    }

    @Override
    public EntityRegion buildEntityRegion(String regionName, Properties props, CacheDataDescription metadata)
            throws CacheException {
        EntityRegion entityRegion = null;
        try {
            entityRegion = new HibernateEntityRegion(this, regionName, ignite, regionCache(regionName),
                metadata);
        } catch (Exception e) {
        }
        if (entityRegion == null) {
            ignite.createCache(cacheConfiguration(regionName));
            try {
                entityRegion = new HibernateEntityRegion(this, regionName, ignite, regionCache(regionName),
                    metadata);
            } catch (Exception e) {
                logger.debug("exception occurred");
            }
        }
        return entityRegion;
    }

    @Override
    public CollectionRegion buildCollectionRegion(String regionName, Properties props, CacheDataDescription metadata)
        throws CacheException {
        CollectionRegion collectionRegion = null;
        try {
            collectionRegion = new HibernateCollectionRegion(this, regionName, ignite, regionCache(regionName),
                metadata);
        } catch (Exception e) {
        }
        if (collectionRegion == null) {
            ignite.createCache(cacheConfiguration(regionName));
            try {
                collectionRegion = new HibernateCollectionRegion(this, regionName, ignite,
                    regionCache(regionName), metadata);
            } catch (Exception e) {
                logger.debug("exception occurred");
            }
        }
        return collectionRegion;
    }

    private CacheConfiguration<Object, Object> cacheConfiguration(String cacheName) {
        CacheConfiguration<Object, Object> cfg = new CacheConfiguration<Object, Object>();
        cfg.setName(cacheName);
        cfg.setCacheMode(CacheMode.PARTITIONED);
        cfg.setAtomicityMode(CacheAtomicityMode.TRANSACTIONAL);
        cfg.setWriteSynchronizationMode(CacheWriteSynchronizationMode.FULL_SYNC);

        return cfg;
    }
}

步骤2.使用HibernateRegionFactoryForIgnite类作为hibernate配置属性中关键hibernate.cache.region.factory_class的值