弹簧 JPA 锁
在锁定春季jpa时,我真的很不安全。
因此,请考虑将此问题作为澄清。我真的希望我理解正确,但我的英语对于理解复杂的博客文章来说不是很好。
所以这就是我认为我从一些文章中得到的:
锁定有两种基本类型:
-
当计划较少的写入操作时,应使用乐观。读取操作不会锁定对象。
例如:您在具有乐观锁的实体中有一个“货币余额”浮动。现在,两个进程读取此值并将其用于计算和填充。其中一个现在更改了该值,并通过更新将其写入数据库。到目前为止没有错误。
但现在另一个进程也会更改该值并希望对其进行更新。现在有一个错误。这仅仅是因为第二次更新而发生的。
如果第二个进程删除了该实例,则不会发生任何事情。 -
在计划大量写入操作时,应使用悲观。读取操作将锁定对象。
例如:您在具有悲观锁的实体中有一个“货币余额”浮动。一个进程使用“findOne”读取数据/值。
在此之后,另一个进程也想要读取数据,使用乐观锁可以实现,但是使用悲观锁,他现在必须等待(没有错误,只是等待)。
当进程 1 准备就绪(更改值并更新它)时,进程 2 可以继续。
第一个问题:到目前为止,这是正确的吗?当我现在想测试这个knollage时,我可以在这个LockModeType之间进行选择:
- 乐观的
- OPTIMISTIC_FORCE_INCREMENT
- PESSIMISTIC_READ
- PESSIMISTIC_WRITE
- PESSIMISTIC_FORCE_INCREMENT
为什么现在有这么多子锁,它们有什么作用?当“乐观”是我试图理解的高层的乐观锁,那么什么是“OPTIMISTIC_FORCE_INCEMENT”?
版本更新与此有什么关系?(或 ?@version
继续:
在Spring jpa中,锁有三个基本用途:
-
在普通列上,例如:
@Entity public class PersonEntity { @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; @Lock(LockModeType.PESSIMISTIC_WRITE) private String name; }
-
在外键上转到其他表,例如:
@Entity public class PersonEntity { @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; @Lock(LockModeType.PESSIMISTIC_WRITE) @OneToOne private Group group; }
-
在存储库内的表上,例如:
interface PersonRepository extends Repository<Person, Long> { @Lock(LockModeType.PESSIMISTIC_WRITE) Person findOne(Long id); }
直接锁定实体
@Entity
@Lock(LockModeType.PESSIMISTIC_WRITE)
public class PersonEntity { }
是不可能的。因此,您可以使用 3(锁定在存储库内)。
第二个问题:这是正确的吗?我忘了使用锁定吗?
继续:
锁定背后的想法是,其他方法/进程必须等到锁定被释放(除了乐观锁,这里抛出一个错误)。
只要实例/对象处于活动状态或直到下一次提交,锁定就在那里。
解锁对象有两种主要可能性:
-
在事务中:在此完整方法中,锁处于活动状态。但是当返回时,锁将被移除。
@Transactional public void test(){ System.out.println("start, but not locked yet"); PersonEntity person1 = personRepository.findOne(1L); // locks this person or must wait, when locked System.out.println("now locked"); // do something return true; // now the lock will be deleted -> unlocked again }
-
直到对象被删除:选择对象时数据将被锁定,删除对象时数据将被解锁。
public void test(){ System.out.println("start, but not locked yet"); PersonEntity person1 = personRepository.findOne(1L); // locks this person or must wait, when locked System.out.println("now locked"); // do something person1 = null; // now the lock will be deleted -> unlocked again System.out.println("not locked anymore"); // do something more return true; }
第三个问题:到目前为止,这是正确的吗?这个函数真的可以等待数据被锁定吗?当对象设置为 ?null
最后一句话:
我真的希望我不会惹恼别人。但就像我说的:我真的很难理解英语中如此复杂的结构:(
所以非常感谢任何形式的帮助:)我真的很感激任何小小的帮助。无论你是给我链接以便更多理解还是直接回答我的问题:)