我正在实现基于实体属性值的持久性机制。所有数据库访问都通过Hibernate完成。 我有一个包含节点路径的表,它非常简单,只是一个id和一个路径(字符串)路径数量很少,大约有几千个。如何在JPA中使用Hibernate的二级缓存?
主表具有数百万行,而不是重复路径,我已将路径标准化为自己的表。以下是我想,在插入时进入主表
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天。
我使用Hibernate 4.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
....
一个简单的,手写的哈希表高速缓存,按预期工作,切割d自己的总时间很大。我想我由于操作的本质而无法触发Hibernate的缓存。
如何在此设置中使用hibernate的二级缓存?根据记录,这是我的坚持XML:
http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd” 版本= “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>
非常有趣!感谢您的问题和答案;)+1 – MychaL