Jpa&Hibernate是否加载数据库中异步变化的数据?
Do Jpa& Hibernate load data which changes asynchronously in DB?
我有一个 oracle 视图,我在其中查询我的数据库。
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.1
和 hibernate 4.3.7
将我的视图映射到我的实体。
我的实体 class 看起来像这样:
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 正确查询了我的实体,它 returns 我所有的记录。
这是问题所在,当我异步更改数据库中的数据时,令人震惊的是我的 jpa 查询 returns 以前的记录。
我是不是做错了什么?
令人震惊的是,JPA 对更新您的数据库的其他进程没有先见之明,怎么可能呢?
您是唯一知道这一点的人,因此必须使用
em.refresh(obj)
如果您知道数据(可能)已更改,则更新对象。
Hibernate 会缓存以前的结果,因此您应该使用 entityManager.clear()
来清理关联的缓存。它将强制再次执行查询。有关详细信息的相关主题:
- When to Use EntityManager.clear()?
- Am I supposed to call EntityManager.clear() often to avoid memory leaks?
关于 Hibernate 缓存的更多信息:
- What are First and Second Level caching in Hibernate?
- How to disable hibernate caching
另一种选择是使用 entityManager.refresh(obj)
将数据库数据与会话数据同步。
我面临的问题是,在 4 之前的 spring 中,我们有 JpaTemplate
用于处理 jpa 实体,我将 EntityManager
传递给 [=13= 的实例] 以编程方式从 EntityManagerFactory
的实例中毫无问题。
JpaTemplate
本身会做任何事情来刷新 EntityManager
和清除缓存。
当我迁移到 spring 4 时,我发现 JpaTemplate
已被删除,所以我必须直接使用 EntityManager
。
我从 EntityManagerFactory
.
的实例以编程方式获取 EntityManager
的实例
我有一个 EntityManagerProvider
class 从 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
注入我的 bean。
@PersistenceContext
protected EntityManager em;
我对这种方式有点困惑,但我的问题用这种方法解决了。
我有一个 oracle 视图,我在其中查询我的数据库。
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.1
和 hibernate 4.3.7
将我的视图映射到我的实体。
我的实体 class 看起来像这样:
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 正确查询了我的实体,它 returns 我所有的记录。 这是问题所在,当我异步更改数据库中的数据时,令人震惊的是我的 jpa 查询 returns 以前的记录。 我是不是做错了什么?
令人震惊的是,JPA 对更新您的数据库的其他进程没有先见之明,怎么可能呢? 您是唯一知道这一点的人,因此必须使用
em.refresh(obj)
如果您知道数据(可能)已更改,则更新对象。
Hibernate 会缓存以前的结果,因此您应该使用 entityManager.clear()
来清理关联的缓存。它将强制再次执行查询。有关详细信息的相关主题:
- When to Use EntityManager.clear()?
- Am I supposed to call EntityManager.clear() often to avoid memory leaks?
关于 Hibernate 缓存的更多信息:
- What are First and Second Level caching in Hibernate?
- How to disable hibernate caching
另一种选择是使用 entityManager.refresh(obj)
将数据库数据与会话数据同步。
我面临的问题是,在 4 之前的 spring 中,我们有 JpaTemplate
用于处理 jpa 实体,我将 EntityManager
传递给 [=13= 的实例] 以编程方式从 EntityManagerFactory
的实例中毫无问题。
JpaTemplate
本身会做任何事情来刷新 EntityManager
和清除缓存。
当我迁移到 spring 4 时,我发现 JpaTemplate
已被删除,所以我必须直接使用 EntityManager
。
我从 EntityManagerFactory
.
的实例以编程方式获取 EntityManager
的实例
我有一个 EntityManagerProvider
class 从 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
注入我的 bean。
@PersistenceContext
protected EntityManager em;
我对这种方式有点困惑,但我的问题用这种方法解决了。