关于JPA,我有些困惑。
据我所知,JPA具有持久性上下文(也称为L1缓存),并且它管理所有实体以实现持久性。并通过以下过程管理实体。
1.发生查找查询时,上下文中没有实体,因此实体管理器向数据库请求数据
2.将结果另存为持久性目录中的实体。
3.之后,当查询发生时,持久性查询将返回内存实体(如果有)。
但是在第三篇中,它在多个实例环境中的工作方式非常令人困惑。我认为,在多个应用程序实例中,它不能确保所有实例中的实体数据相同。
我们假设有两个JPA应用程序实例(所有实例都是相同的负载均衡逻辑)。该表有2列,一个是id,主键,另一个是名称varchar。
有一行ID = 1,名称为“ foobar”
“实例A”通过用户选择查询从数据库中生成ID等于1的实体。
同样,“实例B”通过用户选择查询从数据库中生成ID等于1的相同实体。
然后通过用户更新查询将ID = 1的“实例A”更新实体命名为“ blahblah”。
经过足够的时间后,没有对两个实例进行查询,如果在“实例B”中发生了更新查询,即“从名称= blahblah的表更新名称设置新名称”,我很困惑,它已经具有该实体及其实体名称可能未更新为“ blahblah”。那么最后更新查询在JPA中如何工作?
编辑 我意识到我的问题不清楚。因为提交事务时JPA对DBMS执行DB查询,所以通常没有多少应用程序的问题。
要告诉您为什么要问这个,让我们假设下面是代码。
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
方法将被调用。 对吗?
答案 0 :(得分:0)
这是关于事务隔离和锁定的。如果要查看其他事务提交的更改,则需要refresh(entity)。 JPA不知道其他事务提交的更改。
答案 1 :(得分:0)
bean的类通常标记为:
@无状态的无状态,也就是说,即使另一个bean请求相同的信息,它也不会保存状态。
您可以阅读:
具有状态的@StateFul将保存状态,并且在bean结束事务之前不会更改。
您可以阅读:
https://www.tutorialspoint.com/ejb/ejb_stateless_beans.htm
阅读:
https://www.tutorialspoint.com/ejb/ejb_stateful_beans.htm
除此之外,您还可以使用方法(通过EntityManager和EntityTransaction):
回滚
冲洗
刷新
提交
setFlushMode()可以具有两个值:AUTO和COMMIT
查看示例:
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);
}
答案 2 :(得分:0)
这个问题源于我对JPA L1缓存寿命的误解。
在事务提交或客户端请求结束时(在OSIV中),L1缓存无效。
因此,就我而言,L1缓存未与线程或进程共享。
它仅对OSIV中的同一事务或相同请求有效。
因此,实例是否多个都没有问题。
我感谢回答愚蠢问题的人。