我正在实现一个基于实体属性值的持久化机制。所有数据库访问都是通过Hibernate完成的。我有一个包含节点路径的表,它非常简单,只有一个id和一个路径(字符串)。路径数量很少,大约几千条。
主表有数百万行,我没有重复路径,而是将路径规范化为它们自己的表。以下是我在插入主表时想要的行为
1)检查路径表中是否存在路径(通过实体管理器查询,使用路径值作为参数)
2) 如果不存在,则插入并获取id(通过实体管理器持久化)
3) 将id作为外键值放入主表行,并将其插入主表。
对于一组域对象,这种情况将发生数千次,它们对应于主表和一些其他表中的许多行。因此,使用如下单个事务重复上述步骤:
EntityTransaction t = entityManager.getTransaction();
t.begin();
//perform steps given above, check, and then persist etc..
t.commit();
当我执行步骤2时,它会给整个操作带来巨大的性能下降。它需要缓存,因为过一段时间后,该表将最多有10-20k个条目,并且很少有新的插入。我试着用Hibernate来做这件事,结果损失了将近2天。
我使用的是Hibernate4.1,带有JPA注释和ECache。我已尝试启用查询缓存,即使在整个插入过程中使用相同的查询对象,如下所示:
Query call = entityManager.createQuery("select pt from NodePath pt " +
"where pt.path = :pathStr)");
call.setHint("org.hibernate.cacheable", true);
call.setParameter("pathStr", pPath);
List<NodePath> paths = call.getResultList();
if(paths.size() > 1)
throw new Exception("path table should have unique paths");
else if (paths.size() == 1){
NodePath path = paths.get(0);
return path.getId();
}
else {//paths null or has zero size
NodePath newPath = new NodePath();
newPath.setPath(pPath);
entityManager.persist(newPath);
return newPath.getId();
}
NodePath实体注释如下:
@Entity
@Cacheable
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
@Table(name = "node_path", schema = "public")
public class NodePath implements java.io.Serializable {
查询缓存正在被使用,据我从统计数据中看到的,但是没有使用二级缓存的报告:
queries executed to database=1
query cache puts=1
query cache hits=689
query cache misses=1
....
second level cache puts=0
second level cache hits=0
second level cache misses=0
entities loaded=1
....
一个简单的手工编写的哈希表作为缓存,可以像预期的那样工作,大大减少了总时间。我想由于我的操作性质,我未能触发Hibernate的缓存。
如何使用Hibernate的二级缓存与此设置?郑重声明,这是我的持久性xml:
http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd“version=“2.0”
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<class>...</class>
<exclude-unlisted-classes>true</exclude-unlisted-classes>
<shared-cache-mode>ENABLE_SELECTIVE</shared-cache-mode>
<properties>
<property name="hibernate.connection.driver_class" value="org.postgresql.Driver" />
<property name="hibernate.connection.password" value="zyx" />
<property name="hibernate.connection.url" value="jdbc:postgresql://192.168.0.194:5432/testdbforml" />
<property name="hibernate.connection.username" value="postgres"/>
<property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect"/>
<property name="hibernate.search.autoregister_listeners" value="false"/>
<property name="hibernate.jdbc.batch_size" value="200"/>
<property name="hibernate.connection.autocommit" value="false"/>
<property name="hibernate.generate_statistics" value="true"/>
<property name="hibernate.cache.use_structured_entries" value="true"/>
<property name="hibernate.cache.use_second_level_cache" value="true"/>
<property name="hibernate.cache.use_query_cache" value="true"/>
<property name="hibernate.cache.region.factory_class" value="org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory"/>
</properties>
好的,我找到了。我的问题是,缓存的查询只在缓存中保留查询结果的Ids,并且它(可能)返回数据库以获取实际值,而不是从二级缓存中获取它们。
当然,问题是,查询没有将这些值放入二级缓存,因为它们不是由主id选择的。因此,解决方案是使用一种将值放入二级缓存的方法,在hibernate 4.1中,我已使用natural id实现了这一点。下面是插入或从缓存返回值的函数,以防它对其他人有帮助:
private UUID persistPath(String pPath) throws Exception{
org.hibernate.Session session = (Session) entityManager.getDelegate();
NodePath np = (NodePath) session.byNaturalId(NodePath.class).using("path", pPath).load();
if(np != null)
return np.getId();
else {//no such path entry, so let's create one
NodePath newPath = new NodePath();
newPath.setPath(pPath);
entityManager.persist(newPath);
return newPath.getId();
}
}
问题内容: 使用Java Persistence API(带注释的实体)时,启用Hibernate的二级缓存需要采取哪些步骤?我如何检查它是否正常工作?我正在使用JBoss4.2.2.GA。 从Hibernate文档中,我似乎需要启用缓存并在 persistence.xml中 指定一个缓存提供程序,例如: 还需要什么?我是否需要在JPA实体中添加 @Cache 注释? 如何判断缓存是否正常工作?我
让我澄清一下我对二级缓存的理解。在我的web应用程序的基类中有一个查询。几乎每一个操作都会调用此查询(我使用的是Struts,这就是应用程序的设计方式,因此不会真正弄乱它),例如,加载我的主页会调用三个单独的Struts操作,并为每个操作执行此查询。QueryDsl形式的查询看起来像
我一个新的使用Hibernate缓存(一级,二级和查询缓存)。 我的项目是使用SpringMVC和JPA配置的。 我正在使用下面的JUnit测试用例测试一级缓存。 我的实体类定义为: 如果默认情况下启用了一级缓存,则应该执行一次本机查询。但我在执行此查询时得到以下结果: 以下是我的持久性相关配置: 有人能帮我解决一个问题或者我做错了什么吗? 提前感谢!
问题内容: 我想在hibernate项目中使用二级缓存,但是我只对hibernate二级缓存了解一点,任何人都可以解释我应该如何在代码中使用它以及需要什么配置和.jar文件吗?我将这些设置设置为我的hibernate.cfg.xml文件 并添加这些jar文件, 我想知道我是否需要更改其他配置? 我怎么知道我的项目使用二级缓存? 如果只是设置此设置,hibernate将自动使用此设置,否则我必须在我
在使用JPA时,Hazelcast是否支持Hibernate的分布式和远程二级缓存? 我有客户机/服务器体系结构,我的问题是使用JPA的数据访问操作在客户端。。。,当缓存是远程服务器时。 请给我一个代码样本,让我在两边都做?(在JPA侧和Hazelcast侧) 非常感谢!
我正在使用WildFly 8.1,所以JPA 2.1和Hibernate 4.3.5 我想在WildFly中使用JPA共享缓存/二级缓存 我遵循WildFly文档:https://docs.jboss.org/author/display/WFLY8/JPA参考指南#使用InfinispanSecondlevelCache的JPA参考指南 这是我的persitience.xml: 我将属性设置为h