Database 设计通用DB实用程序类

Database 设计通用DB实用程序类,database,language-agnostic,oop,Database,Language Agnostic,Oop,我一次又一次地发现自己创建了一个数据库实用程序类,它有多个函数,这些函数的作用几乎相同,但对结果集的处理略有不同 例如,考虑一个java类,它有许多看起来都是这样的函数: public void doSomeDatabaseOperation() { Connection con = DriverManager.getConnection("jdbc:mydriver", "user", "pass"); try { Statement stmt = con.cr

我一次又一次地发现自己创建了一个数据库实用程序类,它有多个函数,这些函数的作用几乎相同,但对结果集的处理略有不同

例如,考虑一个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个函数的类

正如您所看到的,大量的样板文件(打开一个连接,尝试最后阻塞),唯一需要更改的是查询和处理结果集的方式。这种类型的代码出现在许多语言中(考虑到您没有使用ORM)

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

使用.net时,非常广泛地使用,以支持以下内容:

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

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

消除常见的编码错误,例如 由于未能关闭连接

使开发人员不再需要 为公共数据编写重复的代码 访问任务

减少对 自定义代码

合并最佳 数据访问实践,如 在.NET数据访问中描述 架构指南

确保 在可能的情况下,应用程序块 函数与不同类型的 数据库

确保应用程序 为一种类型的数据库编写的, 在数据访问方面,与 为其他类型编写的应用程序 数据库


还有大量的使用示例和教程:a将找到msdn.microsoft、4guysfromrolla.com、codersource.com和其他网站。

听起来你可以在这里使用a。这将允许您定义所有子类执行操作所需的公共步骤(以及它们的默认实现,如果适用)。然后子类只需要覆盖不同的步骤:SQL查询、DB字段到对象字段映射等。

我在我的一个项目中所做的方式是,我遵循Spring对JDBC模板所做的,并提出了一个查询框架。基本上创建一个公共类,它可以接受select语句或pl/sql调用和绑定参数。如果查询返回resultset,还将传递行映射器。框架将调用此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
}

您可以选择使用模板,以确保类型安全。

添加了注释以回答问题;那里有很多样品!