2016-08-18 53 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中,正在加載。但直接更新的數據沒有被加載! –