Java 调用另一个类中的方法';让我们试一下拦网
我有一些遵循这种模式的方法Java 调用另一个类中的方法';让我们试一下拦网,java,design-patterns,Java,Design Patterns,我有一些遵循这种模式的方法 try(Connection connection = MySqlConnection.getConnection()){ PreparedStatement statement = connection.prepareStatement( "Insert into db values (NULL ,?,?,?,?,?, NULL , ?)", Statement.RETURN_GENER
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);
}
我被告知将try-catch-with-connection提取到类MySqlConnection,并创建一个新方法,该方法将执行所有逻辑并封装创建连接。因此,我不太了解这种方法,也不知道如何在不编写一些难看的模板或策略的情况下解决它。还是保持原样比较好,或者可以简单地实现?使用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);
}
}
}
public void doSomeUpdate() {
ConnectionHelper.doWithConnection(connection -> {
PreparedStatement statement = connection.prepareStatement(
"Insert into db values (NULL ,?,?,?,?,?, NULL , ?)",
Statement.RETURN_GENERATED_KEYS);
statement.executeUpdate();
});
}
public boolean doSomeQuery() {
return ConnectionHelper.doWithConnection(connection -> {
PreparedStatement statement = connection.prepareStatement("SELECT * FROM table");
return statement.execute();
});
}
public类异常处理程序(){
公共R执行(函数,T参数){
试一试{
返回函数.apply(参数)
}捕获(例外e){
抛出新的运行时异常(e);
}
}
}
现在,您可以将包含逻辑的任何函数传递给上面的类,并且处理异常将是独立的
此外,通过这种方式,您可以创建许多有用的方法和类,这些方法和类的工作方式类似于代理,或者每个操作都需要这些方法和类,它们将独立于您的业务逻辑
例如,以同样的方式,您可以编写:
创建一个将处理异常的ConnectionHelper。这有点棘手,您必须定义自己的功能接口,因为标准使用者无法处理选中的SQLExceptions:
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 class ExceptionHandler() {
public R execute(Function<T,R> function, T argument) {
try {
return function.apply(argument)
} catch (Exception 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();
});
}
public boolean doSomeQuery() {
return ConnectionHelper.doWithConnection(connection -> {
PreparedStatement statement = connection.prepareStatement("SELECT * FROM table");
return statement.execute();
});
}
只要您不必从数据库中返回任何内容(这种情况很少发生),这种方法就可以很好地工作。因此,我们需要使用另一个函数接口来扩展helper,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);
}
}
}
更新
使用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);
}
}
插入连接:
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);
}
}
“有人告诉我”问告诉你的人。你问题中提供的代码看起来已经符合规范,或者你不确定如何实现
MySqlConnection.getConnection()
?@AndyTurner,我期望这个问题=)。奇怪的是,我现在不能联系这个人,但工作必须完成。@Anguium这种事情可以很容易地用intellij中的结构化搜索和替换之类的东西进行重构。始终如一地编写所有方法,然后在知道如何完成的人返回后一次性重构它们。我们提出的任何建议都可能不是他们想要的,所以无论如何你都必须重做。这看起来像是我尝试做的更好的版本,但仍然存在一些问题。当用于插入数据时,它可以为重复条目抛出SQLIntegrityConstraintVIolationException。为了简单地重新显示它,我必须将它添加到doWithConnection签名中。这就是事情变得复杂的地方。由于这个签名,我必须捕获前面提到的异常,比如当我“选择”数据时,它不可能被抛出。没有任何意义,对吗?@Anguium有两种解决方案:要么创建自己的运行时,要么创建IntegrityViolationException。或者在帮助器中创建一个insertWithConnection()
。查看我的更新。