【问题标题】:Java Remove repeated try, catch, finally boilerplate from DAOJava 从 DAO 中移除重复的 try、catch、finally 样板
【发布时间】:2011-05-26 11:44:35
【问题描述】:

我有一个 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 放在一个地方以避免重复。我将如何做到这一点?

【问题讨论】:

    标签: java try-catch dao boilerplate


    【解决方案1】:

    为 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 {
           ...
        }
    }
    

    【讨论】:

    • 是的,如果 JdbcTemplate 不是一个选项(+1),那是我要建议的下一个模式
    【解决方案2】:

    我认为你应该使用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;
                }
            });
    

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

    【讨论】:

      【解决方案3】:

      我会在这里使用AOP 作为commong 日志记录模式。例如:-

      <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());
          }
      }
      

      【讨论】:

      • 这对我来说很有趣。你能解释更多吗?我也是这种情况
      • 您希望我详细解释哪一部分?您可以在我提供的链接上阅读有关 AOP 的信息。我还给出了 aop 配置和示例异常类的示例。
      • 这也是基于弹簧的解决方案。阅读本章:static.springsource.org/spring/docs/3.0.x/…(很难阅读,但值得努力),另请阅读 AspectJ in Action (2nd ed)manning.com/laddad2 它提供了对使用或不使用 Spring 的 AOP 的深入介绍
      【解决方案4】:

      这类似于没有匿名类的 Vladimir 解决方案,可能会从此类方法返回值。

      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
              }
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-11-27
        • 2011-10-31
        • 1970-01-01
        • 2015-09-05
        • 2011-11-17
        • 2013-02-19
        • 2016-03-28
        • 1970-01-01
        相关资源
        最近更新 更多