我想从可扩展的微服务中将实体插入数据库。我尝试使用@Lock(LockModeType.PESSIMISTIC_WRITE)
来防止条目增加一倍。问题是,我对实体有依赖性。
一个基本的例子是:
TestEntity.java
public class TestEntity {
@GeneratedValue()
@Id
private Long id;
private String string;
@ManyToOne
private TestEntityParent testEntityParent;
}
TestEntityParent.java
public class TestEntityParent {
@GeneratedValue()
@Id
private Long id;
private String stringTwo;
@OneToMany(mappedBy = "testEntityParent")
private List<TestEntity> testEntities;
}
TestEnityRepository.java
public interface TestEnityRepository extends JpaRepository<TestEntity,Long> {
@Lock(LockModeType.PESSIMISTIC_WRITE)
TestEntity saveAndFlush(TestEntity testEntity);
Optional<TestEntity> findByStringAndTestEntityParentStringTwo(String string, String stringTwo);
}
TestEntityParentRepository.java
public interface TestEntityParentRepository extends JpaRepository<TestEntityParent, Long> {
@Lock(LockModeType.PESSIMISTIC_WRITE)
TestEntityParent save(TestEntityParent testEntityParent);
Optional<TestEntityParent> findByStringTwo(String stringTwo);
}
AtomicDbService.java
@Service
public class AtomicDbService {
@Autowired
TestEnityRepository testEnityRepository;
@Autowired
TestEntityParentRepository testEntityParentRepository;
@Transactional
public TestEntity atomicInsert(TestEntity testEntity) {
TestEntityParent testEntityParent = testEntityParentRepository.findByStringTwo(testEntity.getTestEntityParent().getStringTwo())
.orElse(testEntityParentRepository.save(testEntity.getTestEntityParent()));
return testEnityRepository.findByStringAndTestEntityParentStringTwo(
testEntity.getString(), testEntity.getTestEntityParent().getStringTwo()
).orElse(testEnityRepository
.save(
TestEntity.builder()
.string(testEntity.getString())
.testEntityParent(testEntityParent)
.build()
)
);
}
}
我的测试用例:
@Test
@Transactional
public void testAtomicInsert(){
TestEntityParent testEntityParent = TestEntityParent.builder().stringTwo("testTwo").build();
TestEntity testEntity = TestEntity.builder().string("test").testEntityParent(testEntityParent).build();
atomicDbService.atomicInsert(testEntity);
System.out.println(testEnityRepository.findAll());
atomicDbService.atomicInsert(testEntity);
System.out.println(testEnityRepository.findAll());
atomicDbService.atomicInsert(testEntity);
System.out.println(testEnityRepository.findAll());
System.out.println(testEnityRepository.findAll());
}
我得到以下答案:
[TestEntity(id=2, string=test, testEntityParent=TestEntityParent(id=1, stringTwo=testTwo, testEntities=null))]
[TestEntity(id=2, string=test, testEntityParent=TestEntityParent(id=1, stringTwo=testTwo, testEntities=null)), TestEntity(id=3, string=test, testEntityParent=TestEntityParent(id=1, stringTwo=testTwo, testEntities=null))]
和一个错误:
query did not return a unique result: 2;
没有依赖项,一切正常。
更新:
将@Lock(LockModeType.PESSIMISTIC_WRITE)
添加到find方法会导致
Feature not supported: "MVCC=TRUE && FOR UPDATE && JOIN"; SQL statement:
...同样适用于
@Lock(LockModeType.PESSIMISTIC_WRITE)
@Query("SELECT e from TestEntity e join e.testEntityParent p where e.string = :string and p.stringTwo = :stringTwo ")
Optional<TestEntity> findWhatever(@Param("string") String string, @Param("stringTwo") String stringTwo);
...因为总是生成for update
。
答案 0 :(得分:0)
显然,这是一个愚蠢的错误,我需要用orElse
和一个lambda替换orElseGet
,并且即使没有所有这些@Lock
,所有的东西都可以工作,等等。
我仍然不明白交易到底出了什么问题以及原因。