I encountered an 'org.hibernate.AssertionFailure' error in my test for a specific logic.
ERROR 56862 --- [pool-3-thread-9] org.hibernate.AssertionFailure : HHH000099: an assertion failure occurred (this may indicate a bug in Hibernate, but is more likely due to unsafe use of the session): org.hibernate.AssertionFailure: null id in ... entry (don't flush the Session after an exception occurs)
The issue arises when a data race condition leads to a Constraint Violation Exception due to the 'longUrl' being a unique column. In this scenario
- the first committed transaction context returns its 'shortUrl'
- while the other failing contexts should find and return the committed entity.
@Transactional
public String
getShortUrl(String longUrl) {
UrlEntity url;
try {
// Create Entity For Id
url = this.db.findUrlEntityByLongUrl(longUrl).orElseGet(
() -> this.db.save(new UrlEntity(longUrl)));
String shortUrl = this.generator.encode(url.getId());
url.setShortUrl(shortUrl);
this.db.save(url);
} catch (DataIntegrityViolationException e) {
// if Conflict return after find
url = this.db.findUrlEntityByLongUrl(longUrl).get();
if (url.getShortUrl() != null) return url.getShortUrl();
url.setShortUrl(this.generator.encode(url.getId()));
}
return url.getShortUrl();
}
Based on my understanding, exceptions occurring within the scope of a transaction trigger a rollback, rendering the session unstable. In this context, I am attempting to perform entity retrieval using this unstable session :(
How should I approach the design? I am concerned that managing try-catch blocks at the controller level might shift part of the business logic to the controller, which seems inappropriate.
Is there a suitable design pattern for this situation?
Aucun commentaire:
Enregistrer un commentaire