2016-07-27 142 views
1

我想在我的項目中將Apache Ignite設置爲第二級Hibernate緩存提供程序,但我遇到了一個奇怪的異常。作爲Hibernate第二級緩存不啓動Apache-Ignite集成?

配置爲如下:

  1. 的pom.xml

新增

<spring.version>4.3.0.RELEASE</spring.version> 
<hibernate.version>4.3.8.Final</hibernate.version> 
<ignite.version>1.6.0</ignite.version> 

<repositories> 
<repository> 
    <id>GridGain External Repository</id> 
    <url>http://www.gridgainsystems.com/nexus/content/repositories/external</url> 
</repository> 
</repositories> 

    <dependency> 
     <groupId>org.apache.ignite</groupId> 
     <artifactId>ignite-core</artifactId> 
     <version>${ignite.version}</version> 
    </dependency> 

    <dependency> 
     <groupId>org.apache.ignite</groupId> 
     <artifactId>ignite-spring</artifactId> 
     <version>${ignite.version}</version> 
    </dependency> 

    <dependency> 
     <groupId>org.apache.ignite</groupId> 
     <artifactId>ignite-hibernate</artifactId> 
     <version>${ignite.version}</version> 
    </dependency> 
  • 彈簧Hibernate配置文件

    <!-- 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> 
    

  • 點燃-configuration.xml文件
  • <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> 
    
  • 實體類
  • 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; 
        } 
    
    } 
    
  • IgniteAlphaCachemanager
  • 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); 
    } 
    
    } 
    
    } 
    

    ,我得到它下面的Tomcat的啓動異常:

    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 
    

    回答

    1

    你必須配置所有區域的緩存。例如,對於userType您可以添加到這個配置:

    <bean parent="transactional-cache"> 
        <property name="name" value="userType"/> 
    </bean> 
    
    +0

    感謝Valetin,但我已經在userType Class中使用了註解@Cache(usage = CacheConcurrencyStrategy.READ_ONLY,region =「userType」)ignite-cache中不支持註釋。 –

    1

    截至目前,在點燃緩存註釋不支持(如對Hibernate二級緩存)。

    如果你不希望把緩存配置每個實體的配置,下面按照步驟

    步驟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的值

    2

    @Cache註釋將僅在您使用entityManager.find()時纔會執行HOD。這意味着這隻適用於主鍵。另一種方法是使用查詢緩存或點燃API。

    相關問題