작성
·
222
0
@Entity
@Data
public class MyEntity {
@Id
@GeneratedValue
private Long id;
private Long num;
@Version
private Long version;
}
@Repository
@RequiredArgsConstructor
public class MyRepository {
private final EntityManager em;
@Transactional
@Lock(value = LockModeType.PESSIMISTIC_FORCE_INCREMENT)
public MyEntity save(MyEntity entity) {
em.persist(entity);
return entity;
}
public MyEntity findById(Long entityId) {
return em.find(MyEntity.class, entityId);
}
}
@Service
@RequiredArgsConstructor
public class MyService {
private final MyRepository myRepository;
@Transactional
public MyEntity save(MyEntity entity) {
entity.setNum(entity.getNum() + 1);
myRepository.save(entity);
return entity;
}
@Transactional
public MyEntity saveEntity(Long entityId) {
MyEntity entity = myRepository.findById(entityId);
entity.setNum(entity.getNum() + 1);
myRepository.save(entity);
return entity;
}
}
@SpringBootTest
public class MyEntityTest {
private static final ExecutorService service =
Executors.newFixedThreadPool(3);
@Autowired
private MyRepository myRepository;
@Autowired
private MyService myService;
private long accountId;
private Long entityId;
@BeforeEach
public void setUp() {
MyEntity myEntity = new MyEntity();
myEntity.setNum(10L);
myService.save(myEntity);
entityId = myEntity.getId();
}
@Test
public void raceCond() throws InterruptedException {
CountDownLatch latch = new CountDownLatch(3);
for (int i = 0; i < 3; i++) {
service.execute(() -> {
myService.saveEntity(entityId);
latch.countDown();
});
}
latch.await();
System.out.println("myRepository.findById(entityId) = " + myRepository.findById(entityId));
}