Java 从 DAO 中移除重复的 try、catch、finally 样板
Posted
技术标签:
【中文标题】Java 从 DAO 中移除重复的 try、catch、finally 样板【英文标题】:Java Remove repeated try, catch, finally boilerplate from DAO 【发布时间】: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 放在一个地方以避免重复。我将如何做到这一点?
【问题讨论】:
【参考方案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-JDBC的JdbcTemplate
即使您不使用 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
【讨论】:
以上是关于Java 从 DAO 中移除重复的 try、catch、finally 样板的主要内容,如果未能解决你的问题,请参考以下文章