user2992777
user2992777

Reputation: 81

How handle db specific exceptions in spring controller

In my controller, I call multiple database methods. The rows need to store in oracle and postgres. How should I handle exceptions in this scenario; duplicates, unique constraint violation exception, etc.

In the code, I handle exceptions related to both oracle and postgres. This code all duplicate code. How can I handle this situation using common code.

What is a good way to handle exceptions in this scenario.

catch (Exception e) {
    if (e instanceof PSQLException || (e.getCause() != null && e.getCause().getMessage().contains("already exists"))) {
        String errMsg = e.getCause().getMessage();
        if (errMsg.contains("already exists")) {
            errMsg = errMsg.substring(errMsg.indexOf('"') + 1, errMsg.lastIndexOf('"'));
        }
        userResponse.setMessage("ExistedUser");
        userResponse.setValue(errMsg);
    } else if (e instanceof SQLIntegrityConstraintViolationException || e.getLocalizedMessage().contains("SQLIntegrityConstraintViolationException")) {
        userResponse.setMessage("Duplicate");
    }
}

Upvotes: 3

Views: 443

Answers (2)

Emanuele Ivaldi
Emanuele Ivaldi

Reputation: 1332

In your controllers methods you can allow your exception to bubble up as long as you have registered exception handlers to handle them properly, this is just one of the few ways spring offers you to handle exceptions, see https://spring.io/blog/2013/11/01/exception-handling-in-spring-mvc for more comprehensive examples

Upvotes: 0

eeijlar
eeijlar

Reputation: 1342

Have a look at the callback design pattern. Basically you work with an instance of an interface in your code, and its implementation handles your exceptions/db transactions. You could have something like:

public interface DatabaseQuery {
    public void execute();
}

public class OracleQuery implements DatabaseQuery {

@Override
public void execute() {
   //run query, catch exceptions etc.

}

}

public class PostgresQuery implements DatabaseQuery {

@Override
public void execute() {
   //run query, catch exceptions etc.

}

}

Then in your code where you need to do database transactions, you pass in an instance of this interface:

public class TestQuery {
    DatabaseQuery query;

    public TestQuery(DatabaseQuery query) {
          this.query = query;
    }

    public void SomeDatabaseStuff() {
        //some code
        // need to work with the db
        query.execute();
        //some more code
    }
}

You don't have to worry about whether its Oracle or Postgres, the implementation will handle that behind the scenes.

Upvotes: 1

Related Questions