Apache-Ignite 集成作为 Hibernate 二级缓存未启动?
Apache-Ignite integration as Hibernate 2nd level cache not starting?
我正在尝试将 Apache Ignite 设置为我项目中的二级 Hibernate 缓存提供程序,但出现了一个奇怪的异常。
配置如下:
- 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>
Spring 休眠配置文件
<!-- 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>
- 实体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;
}
}
- 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.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.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
您必须为所有区域配置缓存。例如,对于 userType
,您可以将其添加到配置中:
<bean parent="transactional-cache">
<property name="name" value="userType"/>
</bean>
到目前为止,ignite-cache 不支持注释(作为休眠的 l2 缓存)。
如果您不想将每个实体的配置放入缓存配置中,请按照以下步骤操作
第 1 步。创建一个新的 class 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 步。使用 class HibernateRegionFactoryForIgnite 作为 hibernate 配置属性
中键 hibernate.cache.region.factory_class 的值
@Cache
注解只有在使用entityManager.find()
方法时才会执行。这意味着这仅适用于主键。另一种方法是使用查询缓存或点燃 API.
我正在尝试将 Apache Ignite 设置为我项目中的二级 Hibernate 缓存提供程序,但出现了一个奇怪的异常。
配置如下:
- 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>
Spring 休眠配置文件
<!-- 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>
- 实体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; } }
- 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.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.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
您必须为所有区域配置缓存。例如,对于 userType
,您可以将其添加到配置中:
<bean parent="transactional-cache">
<property name="name" value="userType"/>
</bean>
到目前为止,ignite-cache 不支持注释(作为休眠的 l2 缓存)。
如果您不想将每个实体的配置放入缓存配置中,请按照以下步骤操作
第 1 步。创建一个新的 class 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 步。使用 class HibernateRegionFactoryForIgnite 作为 hibernate 配置属性
中键 hibernate.cache.region.factory_class 的值@Cache
注解只有在使用entityManager.find()
方法时才会执行。这意味着这仅适用于主键。另一种方法是使用查询缓存或点燃 API.