绕过JPA / Hibernate缓存并命中数据库

时间:2014-09-18 00:59:41

标签: java database hibernate caching jpa

我一直在努力与JPA(使用Hibernate)绕过缓存并点击数据库。

我们正在构建一个接收必须保存的实体的框架,但在某些情况下,我需要检查数据库上的当前数据以确定要执行哪种更新(这是业务需求)。

因此,我有一个由用户更新的传入附加实体,但我需要验证其当前数据库信息以确定要执行的业务规则(有时在JPA merge()操作之前和之后)。

我认为它可以工作的唯一方法是使用实​​体管理器工厂创建一个全新的javax.persistence.EntityManager,并使用这个新的实体管理器执行操作,但是我遇到了并发错误。

看看(这是在DAO中的save()方法中):

EntityManager newEM = currentEntityManager.getEntityManagerFactory().createEntityManager();
newEM.find(e.getClass(), new Short("1"));

但是当我尝试执行find()操作时,我认为JPA会尝试获取当前由currentEntityManager管理的实例,而不是尝试命中数据库。

javax.persistence.PersistenceException: org.hibernate.exception.LockAcquisitionException: could not load an entity: [com.company.framework.persistence.model.TestEntity]
at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1763)
at org.hibernate.jpa.spi.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1694)
at org.hibernate.jpa.spi.AbstractEntityManagerImpl.find(AbstractEntityManagerImpl.java:1141)
at org.hibernate.jpa.spi.AbstractEntityManagerImpl.find(AbstractEntityManagerImpl.java:1068)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at org.springframework.orm.jpa.ExtendedEntityManagerCreator$ExtendedEntityManagerInvocationHandler.invoke(ExtendedEntityManagerCreator.java:334)
at com.sun.proxy.$Proxy32.find(Unknown Source)
你能帮助我吗?这是一个2周的问题。我真的没有想法。 非常感谢你。

1 个答案:

答案 0 :(得分:2)

最简单的解决方案是将DataSource注入您的DAO,就在您的实体管理器旁边并创建一个JDBCTemplate:

 @Autowired
 private final DataSource dataSource;

 private final JdbcTemplate jdbcTemplate;

@Override
public void afterPropertiesSet() {
    jdbcTemplate = new JDBCTemplate(dataSource);
}

然后使用jdbcTemplate运行查询,因为它们将使用与EntityManager不同的JDBC连接。

如果连接绑定到当前线程,则需要在提交给ExecutorService的Callable中执行语句。确保在可调用结果上调用Future.get方法,以便原始线程等待callable完成。

在Java EE中,您还可以使用@NotSupported事务传播标记Bean方法。这将暂停当前事务并在单独的事务中执行查询。