mardi 29 juin 2021

How to perform another DB query in the same transaction in case of unique constraint violation in Java Spring @Transactional method?

I am struggling with handling exceptions during transactional methods with Spring @Transactional annotations. Currently, when my Dao insert method throws a unique contraint violation, I want to perform a read instead to get the existing item. However, this fails because the UniqueIdViolation causes the transaction to fail. How can I refactor this to work as intended whilst not doing a dodgy boolean return on the insert?

I have a DAO with an insert method, e.g.:

public class ItemDao {
  
  public void insertItem(Item item) {
    // insert into db via jooq
  }

  public Item fetch(String id) {
    // fetch from db
  }
  ...
}

If it violates a unique constraint I have an aspect that handles the DataAccessException and rethrows it as a UniqueIdException.

I have a service method that takes in some information and creates an Item, before returning that item.

If the dao throws a UniqueIdException, I want the service to catch this error and then call itemDao.find() to get the existing Item and return it.

public class MyServiceImpl implements MyService {
  
  @Transactional(isolation = SERIALIZABLE)
  public Item createItem(...) {
    Item item = new Item(...);
    try {
      itemDao.insert(item);
      return item;
    } catch (UniqueIdException ex) {
      return itemDao.find(item.getId());
    }
  }
}

The issue here is when itemDao.insert(item) throws an exception this causes the transaction to fail and therefore itemDao.find() doesn't run.

Aucun commentaire:

Enregistrer un commentaire