我有一些遵循这种模式的方法
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并创建一个新方法,该方法将执行所有逻辑并封装创建连接。因此,我不太了解这种方法,也不知道如何在不编写一些难看的模板或策略的情况下解决它。保持现状还是更好,还是可以通过简单的方式实现?
答案 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);
}
}
}
现在,您可以将任何包含逻辑的函数传递给该类,并且处理异常将是独立的。
此外,通过这种方式,您可以创建许多有用的方法和类,它们的工作方式类似于代理,或者是每个操作所需要的,并且帽子将与您的业务逻辑无关。
例如,以相同的方式,您可以编写: