gpt4 book ai didi

hibernate - JPA merge() 最佳实践

转载 作者:行者123 更新时间:2023-12-02 11:29:38 26 4
gpt4 key购买 nike

我为实体对象实现了一个服务,它使用纯jpa,我使用spring,所以在spring xml配置hibernate 配置为 jpa impl。我正在使用 Spring 数据进行 CRUD 操作。但在我们的系统中,我们的实体对象被多次拉取/更新,并且数据存在高争用(并发)。从我们的代码中,许多只是注入(inject)服务bean并调用getEntity方法来获取实体,之后它们更改实体(根据我的理解,这是分离的,但在同一个线程中,因此 em 对象应该与我所知的相同),因此实体需要一段时间才能返回服务进行更新,它们调用 save() 服务的方法来保存实体。 Save() 方法只是调用 merge() 增删改查操作。它是带有 @Transactional 注释的事务性的。这里出现了一个问题,当有人拉取一个实体对象并且在更改它时其他人可能会拉取并更改它并将其保存回来,所以我的实体读取是脏的,如果保存它,我将覆盖已经更新的实体。问题是我们正在服务之外更改实体并调用保存。这里Spring数据存储库类是DAO层。

乐观锁是一种解决方案,但由于某些原因我们不喜欢它,所以它对我们不起作用。我正在考虑悲观锁。例如,当我通过锁定获取要更新的实体,然后将其更改到不同位置的其他位置并回调(实体已经锁定更新!)它有效吗?我不确定它是否仍然是我用于拉取实体的 EntityManager 对象。如果存在,则需要相当长的时间才能通过这些“智能”逻辑,然后才能更新并解锁它。

以下是该场景的简单示例代码:

class SomeEntity {
Long id;
String field1;
String field2;
String field3;
String field4;
String field5;
String field6;
String field7;
//getters and setters, column annotations

}


class SomeEntityServiceImple implemenet SomeEntityService{
@Transactional
save(SomeEntity se){
//call to spring data's merge() method
}

get(Long id){
//call to spring data's findOne()
}

}


//this class might be spring bean, might not be. If it is not I will get SomeEntityService bean from shared appContext
class SomeCrazyClass{
@Autowired
SomeEntityService service;
someMethod(){
SomeEntity e = service.get(1L);
//do tons of logic here, change entity object, call some another methods and again, takes 3 seond
service.save(e); //Probably detached and someone updated this object, probably overriding it.
}
}
}

在这里,我无法在服务层内移动大量逻辑,它非常具体,而且这种不同的逻辑存在于数百个地方。

那么有什么办法可以解决这种情况,至少对这种情况应用悲观锁吗?

最佳答案

对于悲观锁定,您可以尝试以下代码

  • 获取实体时锁定

    entityManager.find(Entity.class, pk, LockModeType.PESSIMISTIC_WRITE);

  • 之后应用锁定

    entityManager.lock(entity, LockModeType.PESSIMISTIC_WRITE);

  • 在查询中设置锁定模式

    query.setLockMode(LockModeType.PESSIMISTIC_WRITE);

另外,您可以尝试在 SomeEntityServiceImpl 中添加同步方法。

public synchronized void saveEntity(e){
{
Object o = get(id); //-- Fetch most recent entity
applyChanges(o, e); //-- Applying custom changes
save(o); //-- Persisting entity
}

因此,您不必将所有逻辑移至服务内,而只需委托(delegate)数据库操作。此外,它将成为在不影响应用程序逻辑的情况下进行代码更改的常见位置。

关于hibernate - JPA merge() 最佳实践,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14846508/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com