'Only allow updating JPA entity when @version attribute matches
I have two classes, a file and an attachment. There is a version attribute on the file and it has a onetomany relationship. I have written code to upload/add attachments to the file. The code works.
However, It doesn't look at the version attribute of 'File' and updates the entity anyway. I would like to add versioning to be checked when calling the addAttachment method. I've tried providing the current value as a requestparam and set it on the File, however, this is not being checked. Any advice on how to setup the controller to make versioning work?
Classes:
....
@Data
public class File {
@Id
private Long fileId;
@Version
private Long tstamp;
@OneToMany(cascase = CascadeType.All)
@JoinColumn(name = "fileId", referencedColumnName = "fileId")
private List<Attachment> attachments = new ArrayList<>();
....
public void addAttachment(Attachment attachment) {
attachments.add(attachment);
}
}
@Data
public class Attachment {
@Id
private Long attachmentId;
private String ....;
......
}
FileService to add attachment to file:
@Transactional
public File addAttachmentToFile(Long id, Long tstamp, Long attachmentId) {
File fileCurrent = getFileById(id);
fileCurrent.setTstamp(tstamp);
Attachment attachment = attachmentService.getAttachmentById(attachmentId);
fileCurrent.addAttachment(attachment);
File file = saveFile(fileCurrent);
return file;
}
File controller:
@PostMapping("/{fileId}/attachments")
public ResponseEntity<File> addAttachmentToFile(@PathVariable final Long fileId, @RequestParam("version") Long tstamp, @RequestParam("attachments") MultipartFile attachment) {
Attachment createdAttachment = attachmentService.saveAttachment(attachment);
Long attachmentId = createdAttachment.getAttachmentId();
fileService.addAttachmentToFile(finDocId, tstamp, attachmentId);
File file = fileService.getFileById(fileId);
return new ResponseEntity<>(file, HttpStatus.OK);
}
Solution 1:[1]
I learned that:
By default, the child or to-many relationship site owns the one-to-many association. Therefore, Hibernate doesn’t increment the version number of the parent entity when you add or remove a child entity.
But you can use the LockModeType.OPTIMISTIC_FORCE_INCREMENT to trigger the version update programmatically.
You can choose between 2 options to set the LockModeType for a specific entity. You either call the lock method on the EntityManager or perform a JPQL query and provide the LockModeType.OPTIMISTIC_FORCE_INCREMENT to the setLockMode method.
You could refer to Hibernate Tips: How to Increase the Version of the Parent Entity When Updating a Child Entity for the in-detail tutorial.
There's one more way you could try to achieve version update i.e. using Event Listeners. It also intercepts any child entity modification and acquires an OPTIMISTIC_FORCE_INCREMENT event on the associated root entity.
I think this method might be an optimal solution. You can follow How to increment the parent entity version whenever a child entity gets modified with JPA and Hibernate for the in-detail tutorial.
One more comment: I notice that you've set tstamp as version but I don't think the version is actually set as timestamps. They're usually like auto-increment that just increment by 1.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Keshavram Kuduwa |
