嗨,我遇到了一些hibernate二级缓存的问题.作为缓存提供程序,我使用ehcache.
来自persistence.xml的配置的一部分
<property name="hibernate.cache.use_second_level_cache" value="true"/>
<property name="hibernate.cache.provider_class" value="net.sf.ehcache.hibernate.EhCacheProvider" />
<property name="hibernate.cache.provider_configuration_file_resource_path" value="/ehcache.xml" />
Run Code Online (Sandbox Code Playgroud)
我使用注释配置我的实体,所以:
@Cache(region = "Kierunek", usage = CacheConcurrencyStrategy.READ_WRITE)
public class Kierunek implements Serializable {
这些注释的导入是:
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
我的ehcache.xml
<diskStore path="java.io.tmpdir" />
<defaultCache maxElementsInMemory="10000" eternal="false"
timeToIdleSeconds="120" timeToLiveSeconds="120" overflowToDisk="true"
diskSpoolBufferSizeMB="30" maxElementsOnDisk="10000000"
diskPersistent="false" diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="LRU" />
<cache name="Kierunek" maxElementsInMemory="1000"
eternal="true" overflowToDisk="false" memoryStoreEvictionPolicy="LRU" />
Run Code Online (Sandbox Code Playgroud)
谁知道为什么我会得到以下错误?
WARNING: Could not find a specific ehcache configuration for cache named [persistence.unit:unitName=pz2EAR.ear/pz2EJB.jar#pz2EJB.Kierunek]; using defaults.
19:52:57,313 ERROR [AbstractKernelController] Error installing to Start: name=persistence.unit:unitName=pz2EAR.ear/pz2EJB.jar#pz2EJB state=Create
java.lang.IllegalArgumentException: Cache …Run Code Online (Sandbox Code Playgroud) 我有一个使用JPA,Hibernate和ehcache的应用程序,以及Spring的声明式事务.DB上的负载相当高,因此所有内容都被缓存以加快速度,包括集合.现在,将集合与拥有它们的实体分开缓存并不是秘密,因此如果我删除作为此类缓存集合的元素的实体,则保留应该是其中一个元素的实体,或更新实体以使其成为从一个集合旅行到另一个集合,我必须手工执行驱逐.
所以我使用一个hibernate事件监听器来跟踪插入,删除或更新的实体,并保存该信息,以便在Spring的事务管理器上注册的事务同步.然后,一旦提交事务,同步就执行驱逐.
现在的问题是,很多时候,其他一些并发事务设法在缓存中找到刚刚被驱逐的集合(这些事件通常根据日志分开十分之一秒),并且自然会导致发生EntityNotFoundException.
如何正确同步这些东西?
我尝试在TransactionSynchronization的4个方法中进行逐出(在相对于事务完成的不同时间点调用),它没有帮助.
任何人都可以发布一个示例来配置Ehcache独立的Java应用程序吗?
我有以下简单的要求:
我正在使用jdbctemplate.Query,它正在快速执行,但从列表中检索需要相当长的时间.List持有大量数据(结果集).
任何人都可以建议如何克服这个问题?
我们有一个高性能的Java(J2SE)中间件应用程序,其中延迟是最重要的.它使用遗留数据库中保存的一些常设数据,其中遗留应用程序可以对数据进行临时修改.由于延迟要求,我们计划使用JPA和Hibernate以及可能的缓存提供程序(如Ehcache)来缓存常备数据.
但是,当站点数据更新(由旧版应用程序)时,我们需要尽快通知此情况.我想在缓存上设置一个到期时间,但是在应用程序发出下一个数据请求之前,缓存不会刷新 - 此时由于数据库重新读取,延迟将会生效.
理想情况下,我们需要缓存来返回过时的值,并在后台使用数据库中的最新值定期更新/刷新缓存.
这可能与Ehcache有关吗?我见过SelfPopulatingCache和CacheLoader,但这似乎我做了很多工作(我必须为每个实体编写代码).另外,有没有人有CacheLoader实现的例子?我希望查询缓存上有一个异步刷新选项.
还有其他技术可以提供解决方案吗?我们不受JPA提供程序或缓存提供程序的约束.
Spring @Cacheable可以提供解决方案吗?我看过spring ehcache cachable提到自填充缓存范围,但我不清楚这意味着什么.
提前致谢.
标题显然表明它:我无法使二级缓存适用于JPA2/Hibernate 3.6.3.
我一直在尝试很多黑客工作.但我只是成功地使查询缓存工作.虽然Hibernate创建了缓存(实例的名称),但它们被忽略了.即使未命中也未注册.也许这是版本不兼容.我尝试了其他一些没有结果的人.而且我不再能够完成所有排列的任务了.:-P
我在这里问这个问题,因为有些人似乎让它工作(我也尝试过它的例子).也许他们可以发现我正在犯的明显错误.
在此先感谢任何帮助我的人!:-)
persistence.xml中
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"
version="2.0">
<persistence-unit name="foo" transaction-type="RESOURCE_LOCAL">
<shared-cache-mode>ENABLE_SELECTIVE</shared-cache-mode>
<properties>
<property name="javax.persistence.jdbc.driver" value="org.apache.derby.jdbc.EmbeddedDriver"/>
<property name="javax.persistence.jdbc.url" value="jdbc:derby:/opt/db/foo;create=true"/>
<property name="javax.persistence.jdbc.user" value="foo"/>
<property name="javax.persistence.jdbc.password" value="bar"/>
<property name="hibernate.dialect" value="org.hibernate.dialect.DerbyDialect"/>
<property name="hibernate.hbm2ddl.auto" value="create"/>
<property name="hibernate.cache.region.factory_class" value="net.sf.ehcache.hibernate.SingletonEhCacheRegionFactory"/>
<property name="hibernate.cache.use_second_level_cache" value="true"/>
<property name="hibernate.cache.use_query_cache" value="true"/>
</properties>
</persistence-unit>
Run Code Online (Sandbox Code Playgroud)
的pom.xml
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>3.6.3.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate.javax.persistence</groupId>
<artifactId>hibernate-jpa-2.0-api</artifactId>
<version>1.0.0.Final</version>
</dependency>
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache-core</artifactId>
<version>2.4.2</version>
Run Code Online (Sandbox Code Playgroud)
JMX设置
这样我就可以检查缓存的用法.创建缓存(每个实体一个),两个查询缓存也在那里.后者填补速度非常快.但是没有一个缓存显示任何未命中或命中.甚至不是查询缓存.
ManagementService.registerMBeans( CacheManager.getInstance(), ManagementFactory.getPlatformMBeanServer(), true, true, true, true, true )
Run Code Online (Sandbox Code Playgroud)
实体缓存被忽略.它们应至少包含保存到数据库中的实体.或者通过查询检索.什么都没有动.
示例Java代码
EntityManager entityManager = Persistence.createEntityManagerFactory("foo").createEntityManager();
entityManager.getTransaction.begin();
entityManager.merge(bar); …Run Code Online (Sandbox Code Playgroud) 我试图在Hibernate的二级缓存中缓存一个对象,该缓存在我的持久性映射文件中映射了一个复合id.日志说我第一次运行查询时,映射为composite-id的类被放入缓存中.但是,当我第二次运行查询时,不会从缓存中提取对象.而是再次运行查询.
Hibernate是否存在二级缓存复合ID的问题?
相关信息:
这就是我构建我的ID并执行我的查询的方式:
CompositeId id = new CompositeId(date, sessionId);
UserDetails user = (UserDetails) hibernateTemplate.load(UserDetails.class, id);
Run Code Online (Sandbox Code Playgroud)
这就是我的持久性映射文件定义上述内容的方式:
<class name="com.entities.UserDetails"
table="USER_DETAILS"
lazy="false">
<cache usage="read-write"/>
<composite-id name="userId" class="com.entities.CompositeId" unsaved-value="undefined">
<key-property name="userSessionId" column="SESSION_ID" />
<key-property name="dateCreated" column="DATE_CREATED" type="date" />
</composite-id>
Run Code Online (Sandbox Code Playgroud)
编辑:情节变厚....
当我将其更改为只读缓存策略时,它工作正常.事务性缓存行为似乎极不可预测.任何人都可以解释为什么上述情况发生在读写缓存中,但在只读时运行良好吗?此表未更新,因此不确定为什么事务语义会改变该实例中的内容.
目前我们有2个应用程序服务器,每个都有应用程序级缓存,并具有集中式数据库服 为了使两个服务器应用程序缓存保持同步,我们在其间设置了JMS代理.在一个服务器上清除缓存,该服务器向JMS发送消息,因为其他服务器已注册,因此它将获取消息并根据消息内容清除相关条目.
由于此消息传递系统在清除缓存条目时增加了延迟,因此在一段时间内应用程序级缓存之间将存在不一致.
因此,我们考虑使用集中式缓存服务器来避免所有这些额外的工作,以保持所有缓存同步.
我们正在考虑使用Ehcache/Terracotta或Hazelcast,这些缓存保存结果集,锁信息和一些系统特定的变量.
请为我们推荐最佳缓存解决方案.
Spring手册中的以下示例混淆了我.
<bean id="cacheManager"
class="org.springframework.cache.ehcache.EhCacheCacheManager"
p:cache-manager-ref="ehcache"/>
<!-- Ehcache library setup -->
<bean id="ehcache"
class="org.springframework.cache.ehcache.EhCacheManagerFactoryBean"
p:config-location="ehcache.xml"/>
Run Code Online (Sandbox Code Playgroud)
命名约定要求EhCacheManagerFactoryBean生成缓存管理器,更确切地说,它是一个net.sf.ehcache.CacheManager实例.然而,豆ehcache不被称为ehcachemanager.cacheManager但是,实际引用了这个bean.
在散文中你可以说一个是Ehcache缓存管理器,而另一个是Spring缓存管理器(由前者支持).
如果您使用以下情况会变得更糟EhCacheFactoryBean:
<bean
id="myCache"
class="org.springframework.cache.ehcache.EhCacheFactoryBean">
<property name="cacheManager">
<ref local="ehcache" />
</property>
Run Code Online (Sandbox Code Playgroud)
有一个叫做cacheManager引用bean 的属性ehcache.
我误解了什么,或者它真的令人困惑吗?设计中的设计不好或命名错误?
我们有一个包含100多个实体类的广泛实体模型.所有实体类都是单个实体超类的子类.共享缓存模式已设置为ALL.
@Entity
@Inheritance(strategy = InheritanceType.JOINED)
@Table(name = "entities")
public abstract class LongIdEntity {
@Id
@GeneratedValue(strategy = GenerationType.TABLE)
private Long id;
@Version
@Column(name = "OPT_LOCK_VERSION")
private Long lockVersion;
etc...
}
Run Code Online (Sandbox Code Playgroud)
一个示例子类:
@Entity
@Table(name = "cars")
public class Car extends LongIdEntity { ... }
Run Code Online (Sandbox Code Playgroud)
我们想要缓存二级缓存中的所有实体.问题是只为所有实体制作了1个缓存区域; 名为LongIdEntity.
调试显示Hibernate 确实找到了所有实体类,但无论如何都要为它们分配相同的区域.因为在SessionFactoryImpl:339:
String cacheRegionName = cacheRegionPrefix + model.getRootClass().getCacheRegionName();
Run Code Online (Sandbox Code Playgroud)
在我们的例子中,对model.getRootClass()的调用将始终产生" LongIdEntity ".
我认为这确实会缓存所有实体,但没有任何驱逐控制.有些课程非常频繁且只读.所以我们希望将它们固定在内存中.有些通常在某个时间跨度内使用,等等......将它们全部塞入同一个缓存会使一切无效.
在注释中指定区域无效.例如:
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE,region = "cars")
@Entity
@Table(name = "cars")
public class Car extends LongIdEntity …Run Code Online (Sandbox Code Playgroud) 我在webapp中使用ehcache,其版本在 Tomcat实例上并行部署.这是在不停止应用程序的情况下部署新版本的便捷方法.
但是我有这样一个问题要继续:即使我给缓存和磁盘存储不同的名称,取决于webapp的版本,所有缓存在停止一个实例时停止.
我的配置是:
<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="ehcache.xsd" name="mywebapp-${project.version}_build_${buildNumber}">
<defaultCache
maxElementsInMemory="1000"
maxElementsOnDisk="10000"
eternal="false"
timeToLiveSeconds="300"
timeToIdleSeconds="300"
overflowToDisk="true"
diskPersistent="false"
memoryStoreEvictionPolicy="LRU"
statistics="true"
/>
<cache
maxElementsInMemory="1000"
maxElementsOnDisk="10000"
name="org.hibernate.cache.internal.StandardQueryCache"
eternal="false"
timeToLiveSeconds="300"
timeToIdleSeconds="300"
overflowToDisk="true"
diskPersistent="false"
statistics="true"/>
<cache
name="org.hibernate.cache.spi.UpdateTimestampsCache"
maxElementsInMemory="10000"
maxElementsOnDisk="100000"
timeToLiveSeconds="300"
timeToIdleSeconds="300"
eternal="false"
overflowToDisk="true"
diskPersistent="false"
statistics="true"/>
<cache
name="query.Presences"
maxElementsInMemory="100"
maxElementsOnDisk="1000"
eternal="false"
timeToLiveSeconds="300"
timeToIdleSeconds="300"
overflowToDisk="true"
diskPersistent="false"
statistics="true"/>
<diskStore path="java.io.tmpdir/mywebapp-${project.version}_build_${buildNumber}"/>
</ehcache>
Run Code Online (Sandbox Code Playgroud)
${project.version} 和 ${buildNumber}
在构建过程中被maven取代.
有人知道如何避免这种不受欢迎的行为吗?
我使用的是ehcache-core-2.4.3和hibernate-ehcache-4.3.8.
ehcache ×10
java ×6
hibernate ×5
caching ×2
jpa-2.0 ×2
spring ×2
annotations ×1
centralized ×1
collections ×1
hazelcast ×1
jpa ×1
tomcat ×1
transactions ×1