【问题标题】:Hibernate or JDBC休眠或 JDBC
【发布时间】:2010-11-24 02:23:27
【问题描述】:

我有一个胖客户端,Java swing 应用程序,其架构包含 25 个表和约 15 个 JInternalFrames(表的数据输入表单)。我需要为 DBMS 交互选择直接 JDBC 或 ORM(在这种情况下使用 spring 框架休眠)的设计选择。将来会构建应用程序。

对于这种规模的项目来说,hibernate 会不会过大?非常感谢对是或否答案的解释(如果有必要,甚至可以采用不同的方法)。

TIA。

【问题讨论】:

  • 还有其他可能性。 iBATIS呢iBATIS.apache.org
  • 矫枉过正?概念矫枉过正?另一个罐子?
  • 我想在额外的处理开销中添加一个层,需要额外的开发人员技能来维护它(我有技能,但我必须考虑何时不是维护它的人) ,耦合到第 3 方而不是本地(尽管额外的 jar 不是 AFAIC 的问题)。那种东西。

标签: java hibernate jdbc


【解决方案1】:

Hibernate 可以很好,但它和其他 JPA ORM 往往会在一定程度上决定您的数据库结构。例如,复合主键可以在 Hibernate/JPA 中完成,但它们有点笨拙。还有其他例子。

如果您对 SQL 感到满意,我强烈建议您查看 Ibatis。它可以完成 Hibernate 的 90% 以上,但实现起来要简单得多。

我想不出为什么我会选择直接的 JDBC(甚至是 Spring JDBC)而不是 Ibatis。 Hibernate 是一个更复杂的选择。

看看Spring and Ibatis Tutorial

【讨论】:

    【解决方案2】:

    我认为两者都是一个不错的选择,但我个人会使用 hibernate。对于这么大的项目,我认为hibernate 并不过分。

    Hibernate 真正让我眼前一亮的地方在于处理实体/表之间的关系。如果您同时处理修改父和子(孙子、兄弟姐妹等),手动执行 JDBC 可能会占用大量代码。 Hibernate 可以让这变得轻而易举(通常一次保存父实体就足够了)。

    不过,在处理 Hibernate 时肯定有一些复杂性,例如了解 Session 刷新的工作原理以及处理延迟加载。

    【讨论】:

      【解决方案3】:

      Straight JDBC 最适合最简单的情况。

      如果您想留在 Java 和 OOD 中,那么选择 Hibernate 或 Hibernate/JPA 或 any-other-JPA-provider/JPA 应该是您的选择。

      如果您对 SQL 更熟悉,那么使用 Spring for JDBC 模板和其他面向 SQL 的框架不会有什么坏处。

      相比之下,除了事务控制之外,在使用 JPA 时使用 Spring 并没有太大帮助。

      【讨论】:

        【解决方案4】:

        毫无疑问,Hibernate 有其复杂性。

        但我真正喜欢 Hibernate 方法(也包括其他一些方法)的地方在于,您可以在 Java 中获得更好的概念模型。虽然我不认为 OO 是万灵药,也不寻求设计的理论上的纯洁性,但我多次发现 OO 实际上简化了我的代码。正如您特别询问的详细信息,这里有一些示例:

        • 增加的复杂性不在模型和实体中,而是在您用于操作所有实体的框架中。对于维护者来说,困难的部分不是几个框架类,而是您的模型,因此 Hibernate 允许您将困难的部分(模型)保持在最干净的状态。

        • 如果在您的所有实体中都使用了一个字段(如 id 或审计字段等),那么您可以使用它创建一个超类。因此:

          • 您编写的代码更少,但更重要的是...
          • 您的模型中的概念较少(唯一的概念在代码中是唯一的)
          • 免费,您可以编写更通用的代码,提供实体(未知、无类型切换或强制转换),允许您访问 id。
        • Hibernate 还有许多功能可以处理您可能需要的其他模型特征(现在或以后,仅在需要时添加它们)。将其视为您设计的可扩展性品质。

          • 您可以将继承(子类化)替换为组合(具有相同成员的多个实体,其中包含多个实体中碰巧需要的一些相关字段)。
          • 您的一些实体之间可以存在继承关系。通常情况下,您有两个具有几乎相同结构的表(但您不想将所有数据存储在一个表中,因为您会失去对不同父表的引用完整性)。
        • 通过实体之间的重用(但只有适当的继承组合),通常会有一些额外的优势。例子:

          • 通常有一些方法可以读取相似但不同的实体的数据。假设我阅读了三个实体的“标题”字段,但对于一些实体,如果结果为空,我将其替换为不同的默认值。很容易有一个签名“getActualTitle”(在超类或接口中),并在三个实现中实现默认值处理。这意味着我的实体中的代码只处理“实际标题”的概念(我明确说明了这个功能概念),并且方法继承负责执行正确的代码(不再有 switch 或 if,没有代码重复) .
          • ...
        • 随着时间的推移,需求会发生变化。您的数据库结构会出现问题。仅使用 JDBC,对数据库的任何更改都必须影响代码(即双倍成本)。使用 Hibernate,可以通过仅更改映射而不是代码来吸收许多更改。反过来也是如此:Hibernate 允许您更改代码(例如在版本之间)而不更改数据库(更改映射,尽管它并不总是足够的)。总而言之,Hibernate 让您可以独立地发展数据库和代码

        出于所有这些原因,我会选择 Hibernate :-)

        【讨论】:

          【解决方案5】:

          没有一个简单答案的好问题。

          在多年来在多个项目中使用 Hibernate 之后,我曾经是 Hibernate 的忠实粉丝。 我曾经认为任何项目都应该默认休眠。

          今天我不太确定。

          Hibernate(和 JPA)在某些方面非常有用,尤其是在开发周期的早期。 使用 Hibernate 比使用 JDBC 要快得多。 您可以免费获得许多功能 - 缓存、乐观锁定等。

          另一方面,它有一些隐性成本。 Hibernate 启动时非常简单。遵循一些教程,在你的课堂上添加一些注释——你就有了自己的坚持。但这并不简单,要能够在其中编写好的代码需要对它的内部工作和数据库设计都有很好的理解。如果您刚刚开始,您可能不知道以后可能会遇到的一些问题,所以这里是一个不完整的列表。

          性能

          运行时性能足够好,我还没有看到休眠是生产性能不佳的原因。问题在于启动性能以及它如何影响您的单元测试时间和开发性能。当休眠加载它分析所有实体并进行大量预缓存 - 对于不是很大的应用程序可能需要大约 5-10-15 秒。所以你的 1 秒单元测试现在需要 11 秒。不好玩。

          数据库独立性

          只要你不需要对数据库做一些微调就很酷了。

          内存中会话

          对于每个事务,Hibernate 都会在内存中为它“接触”的每个数据库行存储一个对象。当您进行一些简单的数据输入时,这是一个很好的优化。但是,如果您出于某种原因需要处理大量对象,则可能会严重影响性能,除非您自己明确且仔细地清理内存中的会话。

          级联

          级联可让您简化对象图的使用。例如,如果您有一个根对象和一些子对象,并且您保存了根对象,那么您也可以配置 hibernate 来保存子对象。当您的对象图变得复杂时,问题就开始了。除非你非常小心并且对内部发生的事情有很好的理解,否则很容易把事情搞砸。当你这样做时,很难调试这些问题。

          延迟加载

          延迟加载意味着每次加载对象时,hibernate 不会加载所有相关对象,而是会提供占位符,一旦您尝试访问它们就会被解析。优化不错吧?是的,除非你需要注意这种行为,否则你会得到神秘的错误。例如,谷歌“LazyInitializationException”。并注意性能。根据您加载对象和对象图的顺序,您可能会遇到“n+1 选择问题”。谷歌它以获取更多信息。

          架构升级

          Hibernate 只需重构 java 代码并重新启动即可轻松更改架构。当你开始的时候很棒。但是随后您发布了第一版。除非您想失去您的客户,否则您需要向他们提供架构升级脚本。这意味着不再需要进行简单的重构,因为所有模式更改都必须在 SQL 中完成。

          视图和存储过程

          Hibernate 需要对其使用的数据进行独占写入访问。这意味着您不能真正使用视图、存储过程和触发器,因为它们会导致数据发生更改,而 hibernate 不知道它们。您可以让一些外部进程在单独的事务中将数据写入数据库。但如果这样做,您的缓存将包含无效数据。还有一件事需要关心。

          单线程会话

          Hibernate 会话是单线程的。通过会话加载的任何对象都只能从同一个线程访问(包括读取)。这对于服务器端应用程序是可以接受的,但如果您正在执行基于 GUI 的应用程序,则可能会使不必要的事情复杂化。

          我想我的意思是没有免费的饭菜。

          Hibernate 是一个很好的工具,但它是一个复杂的工具,需要时间来正确理解它。如果您或您的团队成员不具备这些知识,那么为单个应用程序使用纯 JDBC(或 Spring JDBC)可能更简单、更快捷。另一方面,如果您愿意花时间学习它(包括边做边学和调试),那么您将能够更好地理解权衡。

          【讨论】:

          • +1 很好的答案.. 我曾经认为 Hibernate 是有史以来最好的东西,但是随着我们的应用程序变得越来越复杂(更大的对象图),我遇到了一些调试是一场噩梦的场景因为我不知道hibernate在做什么。 (幸运的是,它是开源的,所以我能够挖掘源代码来弄清楚。不好玩)无论如何,我同意.. 没有免费餐点。 Hibernate 很棒,但也有一些权衡。
          • 自从它在谷歌上的第一次点击后仍然是最新的吗?
          • @PowerFlower 对于 2018 年我觉得还是很相似的情况,hibernate 的核心特性没有改变,而且可能永远不会改变。
          【解决方案6】:

          ...内存中的会话... LazyInitializationException ...

          您可以查看Ebean ORM,它不使用会话对象......以及延迟加载的工作原理。当然是一种选择,不是矫枉过正,而且更容易理解。

          【讨论】:

            【解决方案7】:

            Hibernate 最适合中间件应用程序。假设我们在数据库之上构建了一个中间件,该中间件被大约 20 个应用程序访问,那么我们可以拥有一个满足所有 20 个应用程序要求的休眠。

            【讨论】:

            • 当涉及到测试或调试时,你知道它会是什么令人头疼的事情吗?
            【解决方案8】:
            1. 在JDBC中,如果我们打开一个数据库连接我们需要在try中写,如果发生异常catch block会接受它,最后用来关闭连接。

            2. 在jdbc中所有的异常都是checked exception,所以我们必须在try、catch和throws中写代码,但是在hibernate中我们只有Un-checked exceptions

            3. 作为程序员,我们必须关闭连接,否则我们可能有机会获得我们的连接消息……!

            4. 实际上,如果我们没有在 finally 块中关闭连接,那么 jdbc 不负责关闭该连接。

            5. 在JDBC中我们需要在各个地方编写Sql命令,程序创建后如果修改表结构则JDBC程序不起作用,需要再次修改编译重新部署,这很乏味。

            6. 如果发生异常,JDBC用来生成数据库相关的错误码,但是java程序员对这个错误码是不了解的。

            7. 当我们插入任何记录时,如果我们在数据库中没有任何特定的表,JDBC 会出现“视图不存在”之类的错误,并抛出异常,但在休眠的情况下,如果它在数据库中未找到任何表,这将为我们创建表

            8. JDBC 支持 LAZY 加载,Hibernate 支持 Eager 加载

            9. Hibernate 支持继承、关联、集合

            10. 在hibernate中,如果我们保存派生类对象,那么它的基类对象也会被存入数据库,即hibernate支持继承

            11. Hibernate 支持一对多、一对一、多对多、多对一等关系

            12. Hibernate 通过这种方式支持缓存机制,应用程序和数据库之间的往返次数将减少,通过使用这种缓存技术,应用程序性能将自动提高

            13. 在hibernate中获取分页非常简单。

            14. Hibernate 能够在我们将记录存储到数据库时自动生成主键

            【讨论】:

            • 随着 java 1.7 的发布及其特性 try-with-resources。参数 1,3 和 4 不再是问题
            【解决方案9】:

            如果数十亿用户使用应用程序或网络,那么在 jdbc 中查询将执行数十亿次,但在休眠查询中,对于任意数量的用户,休眠查询将只执行一次,这是休眠优于 jdbc 的最重要和最简单的优势。

            【讨论】:

              猜你喜欢
              • 2011-05-01
              • 2023-03-25
              • 2015-02-01
              • 2019-02-09
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2013-06-13
              • 2011-07-15
              相关资源
              最近更新 更多