我在我的应用程序中使用Hibernate二级缓存,由于某些商业原因我不能再更改实体注释.
在我的项目中,除了从Hibernate更改数据库之外,还存在其他未通过Hibernate的本机SQL.因此,从本机SQL更新数据库后,Hibernate二级缓存数据可能会过时.这就是为什么我想为某些实体禁用二级缓存(以编程方式或以其他方式更改注释).
提前致谢!
我经历了以下明显无证问题,我想了解是否
行为是这个假设以下映射
<class name="org.sample.Foo" table="foo">
...
<many-to-one name="bar" class="org.sample.Bar"/>
</class>
<class name="org.sample.Bar" table="bar" lazy="false">
...
</class>
Run Code Online (Sandbox Code Playgroud)
首先,作为背景,多对一关系上的fetch属性的Hibernate默认值应该是" select ",这至少是记录的内容(当我找到它时,我会在这里添加链接)
但是,如果引用的类是lazy ="true",这显然是正确的!
所以显然上面的映射被翻译成了这个(因为Bar是lazy ="false"):
<class name="org.sample.Foo" table="foo">
...
<many-to-one name="bar" class="org.sample.Bar" *fetch="join" />
</class>
<class name="org.sample.Bar" table="bar" lazy="false">
...
</class>
Run Code Online (Sandbox Code Playgroud)
现在为什么会出现这个问题?而不是2个选择,Hibernate将使用其"父"在单个选择中加载非延迟引用(在单个选择中加载Foo和Bar)
这实际上是有道理的,因为对象不是懒惰,为什么不加载呢?
答案是:如果Bar在二级缓存中会发生什么?
<class name="org.sample.Foo" table="foo">
...
<many-to-one name="bar" class="org.sample.Bar" *fetch="join" />
</class>
<class name="org.sample.Bar" table="bar" lazy="false">
<cache usage="transactional" />
...
</class>
Run Code Online (Sandbox Code Playgroud)
答案就是 - 没有任何改变!
显然人们会认为Hibernate足够聪明,无法理解不应该加载这种类型的对象,但是由于默认的fetch从select更改为join,所以Hibernate没有选择(你无法加入真正的表)还有二级缓存)
所以Hibernate做了它所说的,并使用一个连接从数据库中获取一个对象,它已经在二级缓存中
我发现的解决方案是将映射更改为fetch ="select"
现在当Bar的第二个选择即将发布时,Hibernate知道它不应该进入数据库,并从缓存中获取它.只执行一次查询(预热后)
我目前正在尝试使用hibernate附带的缓存提供程序来运行hibernate.
net.sf.ehcache.hibernate.SingletonEhCacheProvider
Run Code Online (Sandbox Code Playgroud)
我在ecache.xml中启用了默认缓存和类特定缓存,该缓存在我的hibernate.cfg.xml文件中引用.定义类/映射文件特定高速缓存以处理多达20000个对象.
但是,我发现自从我在其中一个映射文件上打开缓存映射后,我没有看到这个问题.
我的测试如下.
加载我测试的特定映射文件的10000个对象(这应该击中DB并成为瓶颈).接下来我将加载相同的10000个对象,因为我希望缓存被击中并看到显着的性能提升.尝试过使用hibernate映射xml文件中的"只读"和"读写"缓存映射.
我想知道他们需要做些什么来确保缓存在加载对象时在数据库之前被击中?
注意作为测试im pagin的一部分通过这些10000记录使用类似于下面的东西(在时间分页1000条记录).
Criteria crit = HibernateUtil.getSession() .createCriteria( persistentClass );
crit.setFirstResult(startIndex);
crit.setFetchSize(fetchSize);
return crit.list();
Run Code Online (Sandbox Code Playgroud)
已经看到标准有一个缓存模式setter(setCacheMode())所以我应该做些什么?
我注意到在内存中使用了以下的统计代码,即10000个对象(好的hiberante脱水onjects,我想象??)但是由于某种原因我得到0次点击而且更令人担忧的是0次因此看起来它根本不会进入缓存当它查看时,即使统计代码似乎告诉我在内存中有10000个对象.
关于我在做什么的任何想法?我认为我得失的事实很好,因为它意味着正在使用缓存,但我无法弄清楚为什么我没有得到任何缓存命中.是否使用setFirstResult()和setFetchSize()使用标准的事实.
System.out.println("Cache Misses = " + stats.getSecondLevelCacheMissCount());
System.out.println("Cache Hits Count = " + stats.getSecondLevelCacheHitCount());
System.out.println("2nd level elements in mem "+ stats.getSecondLevelCacheStatistics("com.SomeTestEntity").getElementCountInMemory());
Run Code Online (Sandbox Code Playgroud) Hibernate 3.3.x,ehcache 2.2.x
当我尝试一次发布大量用户时,会发生以下错误.知道为什么会发生这种情况以及如何纠正这个问题?有没有办法在批量加载用户之前禁用此缓存,如果是这样,我应该怎么做?
17:17:50,140 WARN [AbstractReadWriteEhcacheAccessStrategy] Cache
persistence.unit:unitName=my.ear/my-ejb-1.0.0.jar#my.com.mycompany.User.phones Key com.mycompany.User.phones#9915 Lockable : null
A soft-locked cache entry was expired by the underlying Ehcache.
If this happens regularly you should consider increasing the cache timeouts and/or capacity limits
Run Code Online (Sandbox Code Playgroud)
EDIT1:
当我尝试通过JPA调用将大量用户批量加载到数据库中时,会发生此错误.我没有通过拆卸钩子关闭缓存管理器.
我有以下问题:我有一个查询,它返回35我的结果,我想保持在二级缓存:
public List<Product> getAllProducts() {
Session session = this.sessionfactory.getCurrentSession();
String queryString = "from com.ewave.upromotions.objects.Product product where product.active=:active";
Query query = session.createQuery(queryString);
query.setBoolean("active", true);
query.setCacheable(true);
query.setCacheRegion("productCache");
List<Product> products =query.list();
return products;
}
Run Code Online (Sandbox Code Playgroud)
我的目标如下:
@Entity
@Table(name="products",schema="test11")
@Cacheable
@Cache( usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class Product implements Serializable {
//all setters and getters ommited:
}
Run Code Online (Sandbox Code Playgroud)
我的ehcache.xml文件位于/ src /目录中:
<ehcache>
<diskStore path="java.io.tmpdir"/>
<defaultCache maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
overflowToDisk="false"/>
<cache name="hibernate.test.org.hibernate.cache.UpdateTimestampsCache"
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
overflowToDisk="true"/>
<cache name="hibernate.test.org.hibernate.cache.StandardQueryCache"
maxElementsInMemory="10000"
eternal="false"
timeToIdleSeconds="120"
timeToLiveSeconds="120"
overflowToDisk="true"/>
<cache name="com.vanilla.objects.Product"
maxElementsInMemory="300" …Run Code Online (Sandbox Code Playgroud) 我已经在这里阅读了关于这个主题的其他主题,但没有一个解决方案适合我.
我尝试将它放在我的hibernate.cfg.xml中:
<property name="hibernate.cache.region.factory_class">org.hibernate.cache.spi.EntityRegion</property>
Run Code Online (Sandbox Code Playgroud)
我总是得到这个错误: 无法实例化RegionFactory [org.hibernate.cache.spi.EntityRegion]
我也从Hibernate网站上的线程尝试了大多数建议,但没有运气.
那我该怎么配置呢?
我正在使用WildFly 8.1,所以JPA 2.1和Hibernate 4.3.5
我想在WildFly中使用JPA共享缓存/二级缓存
我遵循WildFly文档:https://docs.jboss.org/author/display/WFLY8/JPA+Reference+Guide#JPAReferenceGuide-UsingtheInfinispansecondlevelcache
这是我的persitience.xml:
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
<persistence-unit name="myAppPU" transaction-type="JTA">
<jta-data-source>java:/jdbc/myAppDS</jta-data-source>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<shared-cache-mode>ENABLE_SELECTIVE</shared-cache-mode>
<properties>
<property name="hibernate.show_sql" value="true"/>
<property name="hibernate.format_sql" value="true"/>
<property name="org.hibernate.flushMode" value="MANUAL"/>
<property name="hibernate.cache.use_second_level_cache" value="true"/>
</properties>
</persistence-unit>
</persistence>
Run Code Online (Sandbox Code Playgroud)
我将属性hibernate.cache.use_second_level_cache设置为true并将shared-cache-mode设置为ENABLE_SELECTIVE
我希望缓存的实体(@Entity)使用@Cacheable(true)进行注释,如下所示:
@Entity
@Cacheable(true)
public class Tooltip implements Serializable {
@Id
private String path ;
private String description ;
private Boolean rendered ;
//...
}
Run Code Online (Sandbox Code Playgroud)
但每次我访问一个网页时,hibernate都会生成大量的select来获取我指示为@Cacheable(true)的所有实体,即使我已经访问过该页面(在同一个会话中).
所以似乎共享缓存/二级缓存不起作用
我错过了什么?
谢谢hwellmann
我试图在persitence.xml中将hibernate.cache.use_query_cache设置为true
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1" xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
<persistence-unit …Run Code Online (Sandbox Code Playgroud) 我有一个简单的单元测试,我使用相同的参数执行相同的 NHibernate 命名查询 2 次(每次不同的会话)。这是一个简单的 int 参数,由于我的查询是一个命名查询,我假设这两个调用是相同的,并且结果应该被缓存。
事实上,我可以在日志中看到结果正在被缓存,但使用不同的键。因此,我的第二次查询结果在缓存中从未找到。
这是我的日志中的一个片段(请注意密钥有何不同):
(第一个查询)
DEBUG NHibernate.Caches.SysCache2.SysCacheRegion [(null)] <(null)> - 添加新数据:key= [snipped]...参数:['809']; 命名参数:{}@ 743460424 & value=System.Collections.Generic.List`1[System.Object]
(第二次查询)
DEBUG NHibernate.Caches.SysCache2.SysCacheRegion [(null)] <(null)> - 添加新数据:key=[snipped]...参数:['809']; 命名参数:{}@ 704749285 & value=System.Collections.Generic.List`1[System.Object]
我已将 NHibernate 设置为使用查询缓存。我将这些查询设置为可缓存=true。不知道还能去哪里看。有人有什么建议吗?
谢谢
-迈克
我使用 Spring Boot 配置作为我的主表的二级缓存。我没有在 Spring Boot 中配置二级缓存。需要了解缓存是如何完成的以及检索是如何完成的。
这是我的 Application.java 类(SpringBootServletinitializer)。我添加了一个测试方法 allCodeValues() 只是为了验证我是否只触发一次休眠查询。但我看到查询被触发了两次,因此表明存储库调用未缓存在休眠中。请帮助我为 EhCaching 进行 SpringBoot 的准确配置...
public class Application extends SpringBootServletInitializer {
public static void main(String[] args) throws Exception{
SpringApplication.run(Application.class, args);
}
@Autowired
WorkflowListRepository wflListRepo;
@Bean(name="getAllCodeValue")
public List<WorkFlowList> allcodeValues(){
List<WorkFlowList> wflList= wflListRepo.getAllDocuments();
wflList= wflListRepo.getAllDocuments();
return wflList;
}
Run Code Online (Sandbox Code Playgroud)
}
下面是JPA持久化的配置
@Bean(name = "entityManagerFactory")
@Primary
public LocalContainerEntityManagerFactoryBean entityManagerFactoryBean() {
LocalContainerEntityManagerFactoryBean entityManagerFactoryBean = new LocalContainerEntityManagerFactoryBean();
entityManagerFactoryBean.setJpaVendorAdapter(vendorAdaptor());
entityManagerFactoryBean.setDataSource(dataSource());
entityManagerFactoryBean.setPersistenceProviderClass(HibernatePersistenceProvider.class);
entityManagerFactoryBean.setJpaProperties(jpaHibernateProperties());
return entityManagerFactoryBean;
}
private Properties jpaHibernateProperties() {
Properties properties = new Properties();
properties.put(PROPERTY_NAME_HIBERNATE_SHOW_SQL, env.getProperty(PROPERTY_NAME_HIBERNATE_SHOW_SQL)); …Run Code Online (Sandbox Code Playgroud) hibernate ×8
java ×4
caching ×3
jpa ×3
ehcache ×2
annotations ×1
nhibernate ×1
orm ×1
shared-cache ×1
spring ×1
spring-boot ×1
wildfly ×1