Java 从 DAO 中删除重复的 try、catch、finally 样板

发布于 2024-10-08 02:13:21 字数 981 浏览 9 评论 0原文

我有一个 DAO 类,其中有许多方法,这些方法有很多重复的代码,大致如下: -

public void method1(...) {
  Connection conn = null;
  try {
      //custom code here
  } catch (SQLException e) {
     LOG.error("Error accessing the database.", e);
     throw new DatabaseException();
  } catch (QueryNotFoundException e) {
     LOG.error("Error accessing the database.", e);
     throw new DatabaseException();
  } finally {
     if (conn != null)
        connectionPool.returnConnection(conn);
  } 

public void method2(...) {
  Connection conn = null;
  try {
      //different custom code here
  } catch (SQLException e) {
     LOG.error("Error accessing the database.", e);
     throw new DatabaseException();
  } catch (QueryNotFoundException e) {
     LOG.error("Error accessing the database.", e);
     throw new DatabaseException();
  } finally {
     if (conn != null)
        connectionPool.returnConnection(conn);
  } 

我想重构这个类,将 try、catch、finally 放在一个地方以避免重复。我将如何实现这个目标?

I have a DAO class with many methods that have a lot of repeated code along the lines of: -

public void method1(...) {
  Connection conn = null;
  try {
      //custom code here
  } catch (SQLException e) {
     LOG.error("Error accessing the database.", e);
     throw new DatabaseException();
  } catch (QueryNotFoundException e) {
     LOG.error("Error accessing the database.", e);
     throw new DatabaseException();
  } finally {
     if (conn != null)
        connectionPool.returnConnection(conn);
  } 

public void method2(...) {
  Connection conn = null;
  try {
      //different custom code here
  } catch (SQLException e) {
     LOG.error("Error accessing the database.", e);
     throw new DatabaseException();
  } catch (QueryNotFoundException e) {
     LOG.error("Error accessing the database.", e);
     throw new DatabaseException();
  } finally {
     if (conn != null)
        connectionPool.returnConnection(conn);
  } 

I would like to restructure this class to put the try, catch, finally in one place to avoid repetation. How would I accomplish this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

冧九 2024-10-15 02:13:21

为 ex 创建一个接口。可执行文件:

 public interface Executable() {

   void exec() throws SqlException();

 }

将每个 dao 方法重构为:

public void method1() {
   execute(new Executable() {

     @Override
     public void exec() throws SqlException() {
          // your code here
     }
  });
  } 

在 DAO 中创建以下执行方法:

private void execute(Executor ex) {
    try {
      ex.exec();
    } catch(...) {
      ...
    } finally {
       ...
    }
}

Create an interface for ex. Executable:

 public interface Executable() {

   void exec() throws SqlException();

 }

Refactor each of your dao method to :

public void method1() {
   execute(new Executable() {

     @Override
     public void exec() throws SqlException() {
          // your code here
     }
  });
  } 

Create the following method execute in your DAO:

private void execute(Executor ex) {
    try {
      ex.exec();
    } catch(...) {
      ...
    } finally {
       ...
    }
}
转身以后 2024-10-15 02:13:21

我认为你应该使用的是 Spring- JDBCJdbcTemplate

即使您不使用 spring 来管理您的应用程序,您也可以以编程方式使用 JdbcTemplate 来抽象所有连接管理和错误处理。

示例代码:

List<Actor> actors = this.jdbcTemplate.query(
        "select first_name, last_name from t_actor",
        new RowMapper<Actor>() {
            public Actor mapRow(ResultSet rs, int rowNum)
            throws SQLException {
                Actor actor = new Actor();
                actor.setFirstName(rs.getString("first_name"));
                actor.setLastName(rs.getString("last_name"));
                return actor;
            }
        });

如您所见,您仅处理实际查询,而不处理其周围的基础设施。

I think what you should use is Spring-JDBC's JdbcTemplate

Even if you don't use spring to manage your application, you could programmatically use JdbcTemplate to abstract away all the connection management and error handling.

Example code:

List<Actor> actors = this.jdbcTemplate.query(
        "select first_name, last_name from t_actor",
        new RowMapper<Actor>() {
            public Actor mapRow(ResultSet rs, int rowNum)
            throws SQLException {
                Actor actor = new Actor();
                actor.setFirstName(rs.getString("first_name"));
                actor.setLastName(rs.getString("last_name"));
                return actor;
            }
        });

As you can see, you deal with the actual query only, not with the infrastructure stuff around it.

他不在意 2024-10-15 02:13:21

我会使用 AOP 用于此处的通用日志记录模式。例如:-

<bean id="exceptionLogger" class="my.good.ExceptionLogger" />  
    <aop:config>
            <aop:pointcut id="allDaoMethods" expression="execution(* my.dao.*(..))" />
            <aop:aspect id="daoLogger" ref="exceptionLogger">
                <aop:after-throwing pointcut-ref="allDaoMethods"
                                    method="logIt"
                                    throwing="e"/>
            </aop:aspect>  
    </aop:config>

ExceptionLogger 类可能如下所示:-

public class ExceptionLogger {
    private static Logger logger = Logger.getLogger(ExceptionLogger.class);
    public void logIt(JoinPoint jp, Exception e) {
        StringBuilder msg = new StringBuilder();
        msg.append("<whatever makes sense>");
        logger.error(msg.toString());
    }
}

I would use AOP for a commong logging pattern here. For example:-

<bean id="exceptionLogger" class="my.good.ExceptionLogger" />  
    <aop:config>
            <aop:pointcut id="allDaoMethods" expression="execution(* my.dao.*(..))" />
            <aop:aspect id="daoLogger" ref="exceptionLogger">
                <aop:after-throwing pointcut-ref="allDaoMethods"
                                    method="logIt"
                                    throwing="e"/>
            </aop:aspect>  
    </aop:config>

And the ExceptionLogger class could be something like below:-

public class ExceptionLogger {
    private static Logger logger = Logger.getLogger(ExceptionLogger.class);
    public void logIt(JoinPoint jp, Exception e) {
        StringBuilder msg = new StringBuilder();
        msg.append("<whatever makes sense>");
        logger.error(msg.toString());
    }
}
花辞树 2024-10-15 02:13:21

这类似于没有匿名类的弗拉基米尔解决方案,可以从此类方法返回值。

interface DaoOperation {
    void execute() throws SQLException;
}

class Operation1 implements DaoOperation {

    public void execute() {
        // former method1
    }
}

// in case you'd ever like to return value
interface TypedDaoOperation<T> {
    T execute() throws SQLException;
}

class Operation2 implements TypedDaoOperation<String> {
    public String execute() {
        return "something";
    }
}

class DaoOperationExecutor {
    public void execute(DaoOperation o) {
        try {
            o.execute();
        } catch (SQLException e) {
            // handle it as you want
        }
    }

    public <T>T execute(TypedDaoOperation<T> o) {
        try {
            return o.execute();
        } catch (SQLException e) {
            // handle it as you want
        }
    }
}

This is similiar to Vladimirs solution without anonymous classes with possibility to return value from such methods.

interface DaoOperation {
    void execute() throws SQLException;
}

class Operation1 implements DaoOperation {

    public void execute() {
        // former method1
    }
}

// in case you'd ever like to return value
interface TypedDaoOperation<T> {
    T execute() throws SQLException;
}

class Operation2 implements TypedDaoOperation<String> {
    public String execute() {
        return "something";
    }
}

class DaoOperationExecutor {
    public void execute(DaoOperation o) {
        try {
            o.execute();
        } catch (SQLException e) {
            // handle it as you want
        }
    }

    public <T>T execute(TypedDaoOperation<T> o) {
        try {
            return o.execute();
        } catch (SQLException e) {
            // handle it as you want
        }
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文