设计通用DB实用程序类

时间:2010-10-11 13:01:34

标签: database language-agnostic oop

我一次又一次地发现自己正在创建一个数据库实用程序类,它具有多个函数,这些函数几乎都做同样的事情,但对结果集的处理略有不同。

例如,考虑一个具有许多函数的Java类,它们都是这样的:

public void doSomeDatabaseOperation() {
    Connection con = DriverManager.getConnection("jdbc:mydriver", "user", "pass");
    try {
        Statement stmt = con.createStatement();
        ResultSet rs = stmt.executeQuery("SELECT whatever FROM table"); // query will be different each time
        while (rs.next()) {
            // handle result set - differently each time
        }
    } catch (Exception e) {
        // handle
    } finally {
        con.close();
    }
}

现在设想一个包含20个这些函数的类。

正如您所看到的,大量的样板(打开连接,try-finally块),唯一改变的是查询和处理结果集的方式。这种类型的代码以多种语言出现(考虑到你没有使用ORM)。

如何管理数据库实用程序类以减少代码重复?典型的DB实用程序类在您的语言/框架中是什么样的?

3 个答案:

答案 0 :(得分:1)

听起来你可以在这里使用Template Method pattern。这将允许您定义所有子类将执行操作所采用的公共步骤(以及它们的默认实现,如果适用)。那么子类只需要覆盖不同的步骤:SQL查询,DB-field-to-object-field映射等。

答案 1 :(得分:1)

我在我的一个项目中所做的就是我遵循Spring对JDBC模板所做的工作,并提出了一个Query框架。基本上创建一个公共类,它可以接受select语句或pl / sql调用和绑定参数。如果查询返回结果集,也传递Rowmapper。框架将调用此rowmapper对象,以将每行转换为任何类型的对象。

示例 -

Query execute = new Query("{any select or pl/sql}",
                          // Inputs and Outputs are for bind variables.
                          new SQL.Inputs(Integer.class, ...),
                          // Outputs is only meaningful for PL/SQL since the
                          // ResultSetMetaData should be used to obtain queried columns.
                          new SQL.Outputs(String.class));

如果你想要rowmapper -

Query execute = new Query("{any select or pl/sql}",
                          // Inputs and Outputs are for bind variables.
                          new SQL.Inputs(Integer.class, ...),
                          // Outputs is only meaningful for PL/SQL since the
                          // ResultSetMetaData should be used to obtain queried columns.
                          new SQL.Outputs(String.class), new RowMapper() {

        public Object mapRow(ResultSet rs, int rowNum) throws SQLException {
            Actor actor = new Actor();
            actor.setFirstName(rs.getString("first_name"));
            actor.setSurname(rs.getString("surname"));
            return actor;
        });

最后一个Row类是输出,如果你已经传递了RowMapper -

,它将包含对象列表
for (Row r : execute.query(conn, id)) {
  // Handle the rows
}

您可以使用模板并使用模板以确保类型安全。

答案 2 :(得分:0)

使用.net时,Data Access Application Block广泛用于为以下内容提供支持:

  

[数据访问]应用程序块   旨在实现以下目标   目标:

     

封装用于执行的逻辑   最常见的数据访问任务。

     

消除常见的编码错误,例如   因为没有关闭连接。

     

解除开发人员的需求   为常见数据编写重复的代码   访问任务。

     

减少对的需求   自定义代码。

     

融入最佳   数据访问实践,如   在.NET数据访问中描述   建筑指南。

     

确保如此   应用程序块尽可能远   函数适用于不同类型的   数据库。

     

确保申请   为一种类型的数据库编写的是,   在数据访问方面,同样如此   为其他类型编写的应用程序   数据库。

还有很多使用示例和教程:google search会找到msdn.microsoft,4guysfromrolla.com,codersource.com等。