我有相同的模块,连接数据库运行在两个服务器(后面和前面)。它与同一个数据库的连接。
我使用JPA (Hibernate实现)和Spring事务管理。
我有以下问题:
我必须用两个不同字段的最大值+1从fieldA更新tableA (fieldA来自tableA,fieldB来自tableB)
Case1:
更新前
tableA fA = 100
tableB fB = 102
更新后
tableA fA = 103
tableB fB = 102
Case2:
更新前
tableA fA = 102
tableB fB = 100
更新后
tableA fA = 103
tableB fB = 100
使用此代码的方法是事务性的,并在此之前(如创建实体)和之后进行操作。因此,在提交事务之前,如果其他应用程序试图获取该值,它将过时,并将在fieldA中保存相同的值。Hibernate会话是不同的,因为分布式系统。
我不能在数据库中使用序列(因为这是关于发票的法律问题)或Hibernate的分布式缓存(系统问题)。
我怎么能做到??
谢谢
发布于 2014-04-30 07:28:31
你可以用锁。适当的锁定类型取决于您的用例。
如果并发更新的概率较低,则使用乐观锁定。在发生更新冲突时,捕获Exception
、刷新实体、重新应用更改并重试提交。
如果使用乐观锁定,建议将@Version
字段添加到实体中。没有版本字段的乐观锁定不一定会被支持。
如果并发修改的概率很高,则使用悲观锁定。因此,可以序列化行上的写入。请注意,这种类型的锁定会造成瓶颈,因为事务队列用于更新,而其他事务则在获取锁之前超时。
为了减少lokc的时间,您可以对单个查询应用锁:
query.setLockMode(LockMode.WRITE)
编辑:这些锁可能可以安全地在分布式环境中使用。
乐观锁定是在提交时(或等效)对DB中的@Version
字段进行检查的方式实现的--如果使用读-预隔离(默认),则没有丢失对实体的提交更改的风险。
悲观锁定是在DB级别上实现的,通常使用SELECT FOR UPDATE
或类似的。所以你不用担心。
发布于 2014-04-30 07:24:46
你需要止痛药锁。使用Hibernate,您可以在JDBC或事务级别上执行此操作。
阅读hibernate手册中的关于锁定的章节。
发布于 2014-04-30 07:34:13
我不知道我是否正确地理解了你的问题,但也许在你的道上,你可以准备一种方法,这样你就可以做一些事情
DetachedCriteria dc = DetachedCriteria.forClass(ClassA);
dc.setProjection(Projections.max("id"));
logger.info(svc.getMax(dc));
一旦得到最大值,就可以更新另一个表。
安杰洛
https://stackoverflow.com/questions/23381799
复制相似问题