在另一个类的try catch块中调用方法

时间:2018-12-05 14:22:01

标签: java design-patterns

我有一些遵循这种模式的方法

try(Connection connection = MySqlConnection.getConnection()){
        PreparedStatement statement = connection.prepareStatement(
                "Insert into db values (NULL ,?,?,?,?,?, NULL , ?)",
                Statement.RETURN_GENERATED_KEYS);
        ...
        statement.executeUpdate();
        ...
    }
    catch(SQLException e) {
        throw new RuntimeException(e);
    }

有人告诉我提取与类MySqlConnection的连接的try-catch并创建一个新方法,该方法将执行所有逻辑并封装创建连接。因此,我不太了解这种方法,也不知道如何在不编写一些难看的模板或策略的情况下解决它。保持现状还是更好,还是可以通过简单的方式实现?

2 个答案:

答案 0 :(得分:2)

创建一个用于处理异常的 ConnectionHelper 。这有点棘手,您必须定义自己的功能接口,因为标准的Consumer不适用于已检查的SQLException:

public class ConnectionHelper {

    @FunctionalInterface
    public interface ConnectionConsumer {
        void accept(Connection connection) throws SQLException;
    }

    public static void doWithConnection(ConnectionConsumer connectionConsumer) {
        try (Connection connection = MySqlConnection.getConnection()) {
            connectionConsumer.accept(connection);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }
}

然后像这样使用它:

public void doSomeUpdate() {
    ConnectionHelper.doWithConnection(connection -> {
        PreparedStatement statement = connection.prepareStatement(
                "Insert into db values (NULL ,?,?,?,?,?, NULL , ?)",
                Statement.RETURN_GENERATED_KEYS);
        statement.executeUpdate();
    });
}

只要您不必从数据库中返回任何内容,这种方法就很好用,这种情况很少发生。因此,我们需要使用另一个功能接口ConnectionFunction扩展帮助程序,以便在需要返回对象时使用它:

public class ConnectionHelper {

    @FunctionalInterface
    public interface ConnectionConsumer {
        void accept(Connection connection) throws SQLException;
    }

    public static void doWithConnection(ConnectionConsumer connectionConsumer) {
    ...
    }

    @FunctionalInterface
    public interface ConnectionFunction<T> {
        T apply(Connection connection) throws SQLException;
    }

    public static <T> T doWithConnection(ConnectionFunction<T> connectionFunction) {
        try (Connection connection = MySqlConnection.getConnection()) {
            return connectionFunction.apply(connection);
        } catch (SQLException e) {
            throw new RuntimeException(e);
        }
    }
}

然后像这样使用它:

public boolean doSomeQuery() {
    return ConnectionHelper.doWithConnection(connection -> {
        PreparedStatement statement = connection.prepareStatement("SELECT * FROM table");
        return statement.execute();
    });
}

更新SQLIntegrityConstraintViolationException一起使用的2种解决方案:

自己的运行时异常: 由于这是运行时异常,因此只需在需要的地方添加try-catch。

public static class MySQLIntegrityConstraintViolationException extends RuntimeException {
    public MySQLIntegrityConstraintViolationException(Throwable cause) {
        super(cause);
    }
}

public static void doWithConnection(ConnectionConsumer connectionConsumer)       {
    try (Connection connection = MySqlConnection.getConnection()) {
        connectionConsumer.accept(connection);
    } catch (SQLIntegrityConstraintViolationException e) {
        throw new MySQLIntegrityConstraintViolationException(e);
    } catch (SQLException e) {
        throw new RuntimeException(e);
    }
}

insertWithConnection doWithConnection()的专用版本。同样,仅在适用的地方/地方使用它。

public static void insertWithConnection(ConnectionConsumer connectionConsumer) throws SQLIntegrityConstraintViolationException {
    try (Connection connection = MySqlConnection.getConnection()) {
        connectionConsumer.accept(connection);
    } catch (SQLIntegrityConstraintViolationException e) {
        throw e;
    } catch (SQLException e) {
        throw new RuntimeException(e);
    }
}

答案 1 :(得分:1)

使用Java功能接口将异常处理与业务逻辑分开,如下所示:

public class ExceptionHandler() {

    public R execute(Function<T,R> function, T argument) {
        try {
           return function.apply(argument)
        } catch (Exception e) {
           throw new RuntimeException(e);
        }
    }
}

现在,您可以将任何包含逻辑的函数传递给该类,并且处理异常将是独立的。

此外,通过这种方式,您可以创建许多有用的方法和类,它们的工作方式类似于代理,或者是每个操作所需要的,并且帽子将与您的业务逻辑无关。

例如,以相同的方式,您可以编写:

  1. 您自己的交易管理,
  2. 记录输入和输出
  3. 检查用户和权限
  4. 和任何其他拦截器