Java Remove repeated try, catch, finally boilerplate from DAO

前端 未结 4 1004
心在旅途
心在旅途 2021-01-06 08:06

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 {
             


        
相关标签:
4条回答
  • 2021-01-06 08:22

    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
            }
        }
    }
    
    0 讨论(0)
  • 2021-01-06 08:23

    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.

    0 讨论(0)
  • 2021-01-06 08:30

    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 {
           ...
        }
    }
    
    0 讨论(0)
  • 2021-01-06 08:41

    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());
        }
    }
    
    0 讨论(0)
提交回复
热议问题