【问题标题】:Best way for many classes to reference a database connection class许多类引用数据库连接类的最佳方式
【发布时间】:2009-03-12 12:34:08
【问题描述】:

我即将开始我的课程的开发阶段,目前的设计是拥有一个处理数据库连接的类和许多调用它的类;数据库类应该打开连接并盲目地传递查询,其他类负责这些查询的内容。

我想知道的是,这些参考资料了解数据库类的最佳方式是什么?我的直觉是将 Database 类中的方法设为静态并将它们称为 Database.method() 但有更好的方法吗?

附:引用这个词是正确的吗?如果不是正确的词,下次我有类似的问题时会有所帮助。

【问题讨论】:

    标签: java database oop


    【解决方案1】:

    小心点。

    单例将成为瓶颈。

    java.sql.Connection 不是线程安全的,因此您可能会遇到问题。

    我建议您在编写应用时将服务层和持久层完全分开。两者都应该基于接口。服务层是了解工作单元和事务的层,使用模型和持久性对象来实现它们。服务应该负责获取连接,使其可用于持久层,处理事务,并在创建连接的同一方法范围内关闭连接。

    范围和清理是关键。如果不这样做,您将耗尽数据库连接。

    你没有提到连接池。我会推荐一个。

    看看春天。它的 JDBC 模块很好地处理了这一切。如果你不能使用 Spring 来完成你的任务,至少它会是一个很好的模型来设计你的实现。

    【讨论】:

      【解决方案2】:

      传统方法是为每个数据类设置一个 DAO(数据访问对象)。

      即如果你有一个数据类“Person”,那么你还有一个类“PersonDAO”,它实现了 findById()、findAll()、save(Person) 等方法。基本上 DAO 类处理所有 DB 交互。

      DAO 类的构造函数可以简单地接受一个 Connection 对象,从而将创建连接的问题外部化,或者它可以在某个地方调用一个工厂方法来分配一个 Connection 对象。

      在任何一种情况下,您都可能希望拥有这样的工厂方法。

      public class Database{
         public static Connection getConnection(){
            // Create a new connection or use some connection pooling library 
         }
      }
      

      正如有人指出 java.sql.Connection 不是线程安全的,所以你不应该每次都分发同一个连接,除非你确定多个线程不会访问该方法。

      当然,如果您需要为每次通话创建新连接,您还需要在完成后关闭连接。简单的方法是向 DAO 添加 close() 方法并让它们处理它。这确实给使用 DAO 的代码带来了负担。

      即使您使用连接池,在完成连接后仍然需要关闭连接(返回池)。

      有人建议使用 Thread local 来建立每个线程的连接。这在某些情况下有效,但对于每个请求都是一个新线程(从不重用,最好不存储引用)的 Web 应用程序来说没有用。

      但是,如果您已对其进行配置,则可以在 web 应用程序中利用此功能,以便在处理每个请求后调用 Database.closeConnection(),然后如果存在 Tread 本地连接,则该连接负责关闭。

      【讨论】:

        【解决方案3】:

        避免任何静态的东西。首选"Parameterisation from Above"

        所以你想要做的是在你的'main'附近创建你的数据库包装对象。然后将其作为构造函数参数传递给需要它的对象。

        【讨论】:

          【解决方案4】:

          如果你按照你的建议去做,那么你将很难对你的类进行单元测试。一种方法可能是将您的数据库信息传递给进行查询的类,例如

          Query query = new GetPersonQuery(Database database);
          query.run(); // or whatever
          

          如果您使用的是 DAO 模式,这将特别有效,因此:

          PersonDao dao = new PersonDao(Database database);
          dao.findAll();
          

          然后数据库可以打包您需要的任何内容,例如连接池、缓存等

          【讨论】:

            【解决方案5】:

            如果你想静态存储连接,至少使用线程本地。但正如其他人所说的那样 - 最好将连接或其包装器注入需要使用它的对象中。

            【讨论】:

              【解决方案6】:

              Singleton pattern 将为您提供帮助。请在此处查看more info

              这种模式(正确地)在这里很不受欢迎,因为它本质上是使一堆方法全局化,这在面向对象的世界中是要避免的——但是对于课程作业和你想要实现的目标可能是最简单的。

              【讨论】:

              • 我会说在你的课程中避免它,因为这是一个坏习惯。在“因为它只是课程作业/简单脚本/仅在此处使用”中删除一个单例太容易了
              • 我在我的代码中使用单例和单态,并且在过去 20 年左右一直这样做,没有任何不良影响。它们只是设计师工具箱中的另一个工具。
              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2016-01-13
              • 2023-03-12
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多