我对JPA有一些令人困惑的事情。
据我所知,JPA 具有持久性上下文(又名。L1 缓存(和 它管理所有实体的持久性。和 它使用以程管理实体。
1. 当 FIND 查询发生时,上下文中没有实体,因此实体管理器向数据库请求数据
2. 将结果另存为持久性 Contentext 中的实体。
3. 在此之后,当查询发生时,持久性查询返回内存实体(如果有(。
但是在第 3 个中,它在多个实例环境中的工作方式非常令人困惑。我认为,在多个应用程序实例中,它无法确保所有实例中的实体数据相同。
假设 JPA 应用程序有 2 个实例。(所有实例都是相同的负载均衡逻辑(。表有 2 列,一列是 ID,主键,另一列是名称 varchar。
有一行是id=1,name="foobar">
"实例 A"通过用户选择查询从数据库中生成 ID 等于 1 的实体。
此外,"实例 B"通过用户选择查询从数据库中生成 ID 等于 1 的相同实体。
然后"实例 A"更新实体,该实体为 ID=1 到 name="blahblah"通过用户更新查询。
经过足够长的时间后,没有对两个实例进行查询,如果更新查询是"从 name=blahblah 的表中更新名称设置新名称"发生在"实例 B"中,我很困惑,它已经有实体,它的名称可能不会更新为"blahblah"。 那么上次更新查询在 JPA 中是如何工作的呢?
编辑我意识到我的问题不清楚。因为 JPA 在提交事务时对 DBMS 执行数据库查询,所以通常有多少应用程序是没有问题的。
为了告诉你我为什么问这个,让我们假设有下面的代码。
void updateEntities() {
entityManager.getTransaction().begin();
List<MyEntity> entities = dao.findAll(); // point1
for (MyEntity e : entities) {
e.setValue(e.getValue() + 100); // point2
}
entityManager.getTransaction().commit();
}
List<MyEntity> findMyEntities() {
return dao.findAll(); // point3
}
两个在其代码中具有上述代码块的实例(两者都是用于负载平衡的相同代码实例(。(实体的数量足以容纳 RAM。
当客户端查询调用该方法时A instance
在内存中生成实体时findMyEntities
。然后
客户端发生下一个查询,然后请求到达instance B
,instance B
也生成了内存中的所有实体。 然后更新查询到达instance A
和实例执行的 updateEntities 和内存中的所有实体instance A
都进行了更新。
但此时,instance A
的缓存实体和instance B
缓存实体之间存在差异。但是instance B
可能无法知道数据是否已更新。
所以我想知道在上述情况之后何时发生更新查询instance B
,我相信如下
- 将发生用户查询。 因此将调用
updateEntities
方法。 - 在第 1 点中,JPA 立即对数据库执行实际查询,并将查询结果同步到实体上下文。
- Point2 代码块正常执行。
正确吗?
这是关于事务隔离和锁定的。如果要查看其他事务提交的更改,则需要刷新(实体(。JPA 不知道其他事务提交的更改。
bean 的类,通常用:
@Stateless没有状态,也就是说,即使另一个 Bean 请求相同的信息,它也不会保存状态。
您可以阅读:
https://www.tutorialspoint.com/ejb/ejb_stateless_beans.htm
@StateFul状态,将保存状态,并且在 Bean 结束事务之前不会更改。
您可以阅读:
https://www.tutorialspoint.com/ejb/ejb_stateful_beans.htm
并阅读以下内容:
https://docs.oracle.com/javaee/6/tutorial/doc/gipjg.html
除此之外,您还可以拥有以下方法(通过 EntityManager 和 EntityTransaction(:
-
反转
-
冲洗
-
刷新
-
犯
-
setFlushMode (( 可以有两个值,自动和提交
请参阅示例:
EntityManager em = ....
EntityTransaction et = em.getTransaction();
et.begin();
try{
em.persist(someObject);
et.commit();
}
et.rollback();
最后,您可以指定要在 Bean 中使用的事务类型,这些事务可以是:
命令的
必填
REQUIRES_NEW
支持
NOT_SUPPORTEED
从不
要使用此属性:
@TransactionAttribute(TransactionAtributeType.NEVER)
public float division(float a,float b){
return (a/b);
}
这个问题源于我对 JPA L1 缓存寿命的误解。
提交事务或客户端请求结束时,L1 缓存失效(在 OSIV 中(。
所以在我看来,L1缓存不与线程或进程共享。
它仅在 OSIV 中的相同事务或相同请求有效。
因此,如果实例是否多个,则没有问题。
我很感激回答愚蠢问题的人。