So there is some table that can only have unique values. I want to read or create new value. I though this would be fairly simple, but for some reason synchronized is not working for me… Maybe it’s just the hot summer day and I’m missing something simple 😉
The error thrown when two threads try to create the same signature:
Caused by: org.postgresql.util.PSQLException: ERROR: duplicate key value violates unique
I’m working with JDK17, Hibernate5, Spring5 (not migrating to Jakarta yet).
// update that needs to be isolated or it throws constraint violation upon creating duplicate signature
private void updateSignature(HoldingEntity holding, String signature) {
var signatureInDb = signatureDAO.getByText(signature);
SignatureEntity newSignature = null;
if (signatureInDb != null) {
newSignature = signatureInDb;
} else {
newSignature = new signatureEntity();
newSignature.setText(signature);
signatureDAO.create(newSignature);
}
holding.setSignature(newSignature);
}
As you can imagine updateSignature
is a part of a larger service that creates holdings.
@Transactional(rollbackFor = {Throwable.class})
public HoldingEntity create(HoldingParams params)
throws HoldingServiceException {
// ...
updateSignature(holding, signature);
// ...
}
Simplified import thread creation:
public void executeImport(Long jobId, String importType, ImportHelperThread importHelperThread) {
// setup sub-threads
ExecutorService executor = Executors.newFixedThreadPool(splitThreadCount);
CompletionService<Void> completionService = new ExecutorCompletionService<>(executor);
// run sub-threads
for (int i = 0; i < splitThreadCount; i++) {
final int threadIndex = i;
completionService.submit(() -> {
try {
initImportThread(jobId);
importHelperThread.run(threadIndex);
} finally {
ThreadContextHolder.clear();
}
return null;
});
}
// stop accepting new subtasks
executor.shutdown();
executor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS);
}