我的Spring组件从客户端获取请求,向Web服务询问某些数据并将接收到的对象保存到数据库 . 我 identify 所有对象和 save only new 个 .
The issue occurs 当客户端同时发出两个或多个相同的请求时(或者由于甚至不同的用户请求,我从Web服务接收相同的对象) .
在这里用 persistence 描述一些细节问题 . 对于每个客户端请求,我的组件在一个单独的线程中开始执行,我得到一个新的entityManager,开始一个事务,从web-service接收数据,然后我在当前事务中使用给定的entityManager识别对象并保留新的对象 .
如果在单独的事务中,我从Web服务接收相同的对象,如果它们是尚未在数据库中的新对象,则在未提交的事务中是 not able to identify them ,因此它们将保留在 all 事务中 . Then all duplicate objects will be commited and saved to database.
在这种情况下,什么是好的解决方案?即使在不同的交易中,有没有办法正确地使用 identify 新对象?或者可以应用哪些方法?
可能 Spring 提供了一些管理事务或entityManagers的方法,以便它可以帮助解决这个问题......
Note . 当然,我可以使用数据库工具来避免保存重复的对象,但在这种情况下,它不是一个非常好的解决方案 .
2 回答
所以我的案例中的解决方案如下:
使事务非常小并分别提交每个对象 .
在数据库中创建唯一约束以防止重复对象 . 这一点对我们来说不会有太多帮助,但需要第3点 .
我们在try-catch块中插入的每个commit()方法 . 如果我们尝试在并行事务中提交重复对象,那么我们将收到一个异常,并且在catch块中我们可以检查数据库,选择已经存在的对象并进一步使用它 .
这个例子:
在保存之前检查数据库中是否存在对象 .
使用@UniqueConstraint or @Column(unique = true)来防止重复行,适当地处理异常 .
使用
@Version
管理现有实体的并发修改 . 更多关于乐观和悲观锁定的信息:Chapter 5. Locking . 相关讨论:Hibernate Automatic Versioning和When to use @Version and @Audited in Hibernate?您可以使用线程锁/同步机制来确保对同一用户的请求将按顺序发生 . 但是,如果您的服务在多个节点上运行,则无法使用此功能 .