Search code examples
javamysqljdbcdaoservice-layer

Should I catch exceptions in DAO layer or can I do it on service layer?


I have a DAO with different methods. An example of one of them:

@Override
public boolean insertUser(Connection connection,User user) {
    int rowNum = 0;
    String query = "INSERT INTO user_info(login,userPassword,userType,userEmail)values(?,?,?,?);";
    ResultSet keys = null;
    Connection con;
    PreparedStatement statement = null;
    try {
        con = connection;
        statement = con.prepareStatement(query,Statement.RETURN_GENERATED_KEYS);
        statement.setString(1, user.getLogin());
        statement.setString(2, PasswordUtil.generateStrongPasswordHash(user.getPassword()));
        statement.setString(3, user.getUserType());
        statement.setString(4, user.getUserEmail());
        rowNum = statement.executeUpdate();
        keys = statement.getGeneratedKeys();
        if (keys.next()) {
            user.setUserId(keys.getInt(1));
        }

    } catch (SQLException e) {
        LOGGER.error(e);
    } finally {
        ConnectionUtil.oneMethodToCloseThemAll(keys,statement,null);
        }
    return rowNum > 0;
}

And in the service Iayer I have:

public boolean insertUser(User user)  {
    Connection connection = MySQLDAOFactory.getConnection();
    boolean result =  userDao.insertUser(connection,user);
    ConnectionUtil.commit(connection);
    ConnectionUtil.oneMethodToCloseThemAll(null,null,connection);
    return result;
}

Should I catch exceptions in DAO Layer or can I throw them and catch at service layer?


Solution

  • Usually I catch and translate the exceptions at the DAO layer and catch the translated exceptions in the Service Layer to decide what to do.

    Why catch and translate? Because a simple SQLException is hard for the Service Layer to understand what happened, so you catch the SQLException in the DAO, translate it to a more 'friendly' corresponding exception and then throw it, so the Service Layer can easily decide what to do.

    A simple example:

    DAO:

    try {
      // your logic to insert
    } catch (SQLException e) {
      // translate the exception
      if (e.getErrorCode() == 123) // imagine 123 is a constraint violation code from the database
        throw new ConstraintViolationException("message", e);
    } finally {
      // ...
    }
    

    Service Layer:

    try {
        callMethodFromDAO();
    } catch (ConstraintViolationException ex) {
        // what to do ...
    } catch (AnotherDatabaseException ex) {
        // what to do ...
    }