Apache-Ignite integration as Hibernate 2nd level cache not starting?

夙愿已清 提交于 2019-12-02 13:41:38

问题


I am trying to set Apache Ignite as the second level Hibernate cache provider in my project but i am getting a strange exception.

Configurations are as below:

  1. POM.xml

Added

<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>
  1. Spring Hibernate Configuration file

    <!-- 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. ignite-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>
  1. Entity Class
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. 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);
}

}

}

The exception that i get it below on tomcat startup:

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:


You have to configure caches for all your regions. For example, for userType you can add this to the configuration:

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



回答2:


@Cache annotation will be executed only if you use the entityManager.find() method. That mean this will work only with primary keys. Another approach is to use query cache or ignite API.




回答3:


Till now, annotations not supported in ignite-cache (as l2 cache for hibernate).

If you don't want to put configuration of each entity in cache configuration, follow below steps

Step 1. Create a new class HibernateRegionFactoryForIgnite as below

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;
    }
}

Step 2. Use class HibernateRegionFactoryForIgnite as value for key hibernate.cache.region.factory_class in hibernate configuration properties



来源:https://stackoverflow.com/questions/38624139/apache-ignite-integration-as-hibernate-2nd-level-cache-not-starting

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!