2016-08-18 23 views
2

我有一个oracle查看我查询我的数据库。Do Jpa&Hibernate如何加载在数据库中异步变化的数据?

create or replace view my_view as 
Select cc.CCID ccid 
     sm.SMCODE smcode, 
     NVL(sm.smname, cc.ccname) sname 
    From CC cc 
Inner Join SM sm 
    On cc.id = sm.id; 

我用jpa 2.1hibernate 4.3.7我的看法映射到我的实体。 我的实体类看起来是这样的:

public class CCRequest implements Serializable { 

    private static final long serialVersionUID = 1L; 

    private String ccId; 

    private String smCode; 

    private String sName; 
} 

我的XML映射是这样的:

<?xml version="1.0" encoding="UTF-8"?> 
<entity-mappings xmlns="http://xmlns.jcp.org/xml/ns/persistence/orm" 
       version="2.1"> 
    <entity class="CCRequest" name="CCRequest001"> 
     <table name="my_view"/> 
     <attributes> 
      <id name="ccId"> 
       <column name="ccid"/> 
      </id> 
      <basic name="smCode"> 
       <column name="smcode"/> 
      </basic> 
      <basic name="sName"> 
       <column name="sname"/> 
      </basic> 
     </attributes> 
    </entity> 
</entity-mappings> 

所以我查询我的实体使用JPA得当,它返回我的所有记录。 以下是我在异步更改数据库中的数据时出现的问题,令人震惊的是,我的jpa查询返回以前的记录。 我做错了什么?

+2

1.您是直接或通过JPA/Hibernate方法更改数据库中的数据吗? - Hibernate缓存以前的结果,因此如果直接修改数据,直到清除缓存后才会看到更改。 2.如果您使用JPA/Hibernate更改数据 - 是否刷新/提交它们? 3.它也可能取决于你如何管理EntityManager或Session。 – Justas

+0

我直接更改数据。但在我的应用程序中,以不同于JPA/Hibernate方法的其他方式更改数据是可行的。这里的解决方案是什么?你说什么意思取决于我如何管理EntityManage? –

回答

0

我面临的问题是,在4之前春天,我们与JPA实体工作的人JpaTemplate,我通过EntityManagerJpaTemplate实例编程从EntityManagerFactory没有问题的一个实例。

JpaTemplate本身会做任何事情冲洗EntityManager并清除缓存。 当我迁移到春季4时,我面临着JpaTemplate已经被丢弃,所以我必须直接与EntityManager一起工作。

我通过编程从EntityManagerFactory的实例获得EntityManager的实例。

我有一个EntityManagerProvider类,它从EntityManagerFactory的实例创建EntityManager的实例。

public class EntityManagerProvider { 

    public static EntityManager createEntityManager(EntityManagerFactory entityManagerFactory) { 
     return entityManagerFactory.createEntityManager(); 
    } 
} 

我得到EntityManager实例是这样的:

<bean id="entityManager" class="com.tosan.novin.sipa.bo.da.jpa.EntityManagerFactoryProvider" factory-method="createEntityManager"> 
     <constructor-arg index="0" ref="entityManagerFactory"/> 
</bean> 

但我明白,如果我想EntityManager管理事务和冲洗的唯一途径是利用@PersistenceContext注入EntityManager到我的豆子。

@PersistenceContext 
protected EntityManager em; 

我有点困惑又用这样的方式,但这种方法解决我的问题。

0

没有那么令人震惊的JPA没有其他进程更新数据库的先知知识,它怎么可能? 你是谁知道有关,因此必须使用

em.refresh(obj) 

更新对象,如果您知道数据具有唯一的人(可能)改变。

+0

但我认为当我执行一个查询时,它应该在db上运行,并从db中获取结果。 –

+0

查询清楚地在数据库上运行,并且发出的SQL将在日志中。但它只会显示适合事务隔离的数据。只有你知道什么时候你的对象是从外部更新/添加的,以及txn隔离是否是一个因素。此外,JPA的L1/L2缓存不知道外部进程,所以如果外部改变,它们将需要驱逐对象。 –

+0

在像2应用程序与db共享机制的情况下,jpa不是解决方案,因为每次需要执行查询时都可能发生外部更改,所以应该清除chache。我对吗? –

2

Hibernate缓存以前的结果,因此您应该使用entityManager.clear()来清理关联的缓存。它将强制再次执行查询。相关线程的详细信息:

更多关于Hibernate缓存:

另一种选择是使用entityManager.refresh(obj)将数据库数据与会话数据同步。

+0

您能给我一段关于这种行为的jpa/hibernate文档吗?这对我来说似乎有点奇怪。我认为,除非出现一些特殊情况,我们经常想要我们的数据库中有什么,是不是? –

+0

更新了更多链接。 – Justas

+0

我不明白的是,如果它使用缓存数据,它如何理解新插入的数据?在我的情况下,新插入的数据,直接在db中,正在加载。但直接更新的数据没有被加载! –