admin管理员组文章数量:1399347
Could someone please explain how to get Optimistic Locking in JPA to work? My initial idea was, that once I'm passing an entity with Version number other than it is stored in the database the commit is rejected and OptimisticLockException is thrown. My Database in the backend is Oracle 21C
as shown in the code below I'm explicitly setting fixed version number for each HTTP PUT(update) request. But every request is successful.
The updateDateTime
property is correctly managed by JPA and it is updated with every request. The same for version
property. Its value is being incremented on every commit.
Here is my test entity, with property annotated with @Version:
@Entity
@Table(name = "docs", uniqueConstraints = @UniqueConstraint(columnNames = "doc_id"))
public class Doc {
@Id
@Column(name = "doc_id")
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "doc_generator")
@SequenceGenerator(name = "doc_generator", sequenceName = "doc_seq", allocationSize = 1)
private Long id;
@Column(name = "param_1", nullable = false)
private String param1;
@Column(name="param_2")
private String param2;
@CreationTimestamp
@Column(name = "created", nullable = false, updatable = false)
private LocalDateTime createDateTime;
@UpdateTimestamp
@Column(name = "updated", nullable = false, updatable = true)
private LocalDateTime updateDateTime;
@Version
@Column(name = "version")
private Integer version;
// ...
}
simple repository:
public interface DocRepository extends JpaRepository<Doc, Long> {
@Query(value = "SELECT d FROM Doc d WHERE d.id = ?1")
@Lock(LockModeType.OPTIMISTIC)
Optional<Doc> findByIdWithLock(Long id);
}
a service:
@Service
public class DocService {
private final DocRepository docRepository;
private final EntityManager entityManager;
private final DocMapper docMapper;
public DocService(DocRepository docRepository, EntityManager entityManager, DocMapper docMapper) {
this.docRepository = docRepository;
this.entityManager = entityManager;
this.docMapper = docMapper;
}
public DocDto save(DocDto dto) {
var entity = docMapper.toEntity(dto);
var saved = docRepository.save(entity);
return docMapper.toDto(saved);
}
@Transactional
public DocDto update(Long id, DocDto dto) {
var updated = docRepository.findByIdWithLock(id)
.map(entity -> docMapper.updateWith(entity, dto))
.orElseThrow(() -> new EntityNotFoundException("Document not found"));
var saved = docRepository.save(updated);
return docMapper.toDto(saved);
}
@Transactional
public List<DocDto> findAll() {
return docRepository.findAll().stream()
.map(docMapper::toDto)
.collect(Collectors.toList());
}
public void delete(Long id) {
var saved = docRepository.findById(id)
.orElseThrow(() -> new EntityNotFoundException("Document not found"));
docRepository.delete(saved);
}
public Long getCount() {
return docRepository.count();
}
}
controller:
@RestController
@RequestMapping(path = "/api/doc")
public class DocController {
private final DocService docService;
public DocController(DocService docService) {
this.docService = docService;
}
@PostMapping(path = {"", "/"})
public ResponseEntity<DocDto> save(@RequestBody DocDto dto) {
var response = docService.save(dto);
return ResponseEntity.ok(response);
}
@GetMapping(path = {"", "/"})
public ResponseEntity<List<DocDto>> findAll() {
var response = docService.findAll();
return ResponseEntity.ok(response);
}
@PutMapping(path = "/{id}")
public ResponseEntity<DocDto> update(@PathVariable(value = "id") Long id, @RequestBody DocDto dto) {
var response = docService.update(id, dto);
return ResponseEntity.ok(response);
}
@DeleteMapping(path = "/{id}")
public ResponseEntity<Void> delete(@PathVariable(value = "id") Long id) {
docService.delete(id);
return ResponseEntity.noContent().build();
}
@ExceptionHandler(value = {EntityNotFoundException.class})
@ResponseStatus(HttpStatus.NOT_FOUND)
public ResponseEntity<ErrorResponse> handleException(EntityNotFoundException exc) {
// ...
}
}
and DTO / Entity mapper:
@Component
public class DocMapper {
public Doc toEntity(DocDto dto) {
var entity = new Doc()
.setParam1(dto.getParam1())
.setParam2(dto.getParam2());
return entity;
}
public Doc updateWith(Doc entity, DocDto dto) {
entity.setParam1(dto.getParam1())
.setParam2(dto.getParam2())
.setVersion(1);
return entity;
}
public DocDto toDto(Doc entity) {
var dto = new DocDto()
.setId(entity.getId())
.setParam1(entity.getParam1())
.setParam2(entity.getParam2())
.setVersion(entity.getVersion());
return dto;
}
}
本文标签: javaJPA Version and optimistic locking problemStack Overflow
版权声明:本文标题:java - JPA @Version and optimistic locking problem - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1744204615a2595127.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论