0

Using :

  • spring-boot 2.3.6.RELEASE
  • spring-data-jdbc.
  • postgresql

I made a simple repository, extending CrudRepository, and it works fine. For example I am able to save data using this repository.

I created a unique index on one of the columns, and expected my repository to throw a org.springframework.dao.DuplicateKeyException when trying to insert the same object twice.

However, the repo, instead, throws a org.springframework.data.relational.core.conversion.DbActionExecutionException, which has a the DuplicateKeyException has it's cause.

My configuration is pretty basic : only configuring a datasource (spring.datasource.*)

Is this a normal behavior of spring-data-jdbc to wrap the DuplicateKeyException in a DbActionExecutionException ?
I used spring-data in the past and can't recall dealing with DbActionExecutionException.

baraber
  • 3,296
  • 27
  • 46

2 Answers2

1

In Spring-Data-Jdbc, this is expected behaviour. Spring-Data-Jdbc uses JdbcTemplate when you perform any DBAction using CrudRepository.

All the DbActions performed by CrudRepository will be translated to DbActionExecutionException if any exception thrown by JdbcTemplate.

Snippet from AggregateChangeExecutor class:

private void execute(DbAction<?> action, JdbcAggregateChangeExecutionContext executionContext) {

        try {
            if (action instanceof DbAction.InsertRoot) {
                executionContext.executeInsertRoot((DbAction.InsertRoot<?>) action);
            } else if (action instanceof DbAction.Insert) {
                executionContext.executeInsert((DbAction.Insert<?>) action);
            } else if (action instanceof DbAction.UpdateRoot) {
                executionContext.executeUpdateRoot((DbAction.UpdateRoot<?>) action);
            } else if (action instanceof DbAction.Update) {
                executionContext.executeUpdate((DbAction.Update<?>) action);
            } else if (action instanceof DbAction.Delete) {
                executionContext.executeDelete((DbAction.Delete<?>) action);
            } else if (action instanceof DbAction.DeleteAll) {
                executionContext.executeDeleteAll((DbAction.DeleteAll<?>) action);
            } else if (action instanceof DbAction.DeleteRoot) {
                executionContext.executeDeleteRoot((DbAction.DeleteRoot<?>) action);
            } else if (action instanceof DbAction.DeleteAllRoot) {
                executionContext.executeDeleteAllRoot((DbAction.DeleteAllRoot<?>) action);
            } else if (action instanceof DbAction.AcquireLockRoot) {
                executionContext.executeAcquireLock((DbAction.AcquireLockRoot<?>) action);
            } else if (action instanceof DbAction.AcquireLockAllRoot) {
                executionContext.executeAcquireLockAllRoot((DbAction.AcquireLockAllRoot<?>) action);
            } else {
                throw new RuntimeException("unexpected action");
            }
        } catch (Exception e) {
            throw new DbActionExecutionException(action, e);
        }
    }

JdbcTemplate throws DataAccessException while it performing on DBAction, and all the Spring transaction related exception classes implements DataAccessException.

Satish Varma
  • 256
  • 1
  • 8
0

That’s a wrapper class for Database Actions.

check this link (https://docs.spring.io/spring-data/jdbc/docs/1.0.0.M2/api/org/springframework/data/jdbc/core/conversion/DbActionExecutionException.html).

clifford_owino
  • 462
  • 1
  • 6
  • 24
  • Indeed, I saw this class before asking the question. I was wondering if this wrapping was specific to spring-data-jdbc because I'm pretty sure in a similar context (using spring-data), I could catch all DataAccessException directly. – baraber Nov 18 '20 at 16:06