Hibernate或JDBC

我有一个厚实的客户端,java swing应用程序,包含25个表格和〜15个JInternalFrames(表格的数据input表格)。 我需要为DBMS交互做直接的JDBC或ORM(在这种情况下用spring框架的hibernate)的deviseselect。 将来会发生出应用程序。

冬眠会为这个大小的项目矫枉过正吗? 对“是”或“否”的解释的解释将是非常赞赏的(甚至如果需要,甚至是不同的方法)。

TIA。

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

过去多年来,在多个项目中使用Hibernate之后,我一直是Hibernate的忠实粉丝。 我曾经相信,任何项目应该默认冬眠。

今天我不太确定。

Hibernate(和JPA)对于某些事情来说非常棒,特别是在开发周期的早期。 与使用Hibernate相比,使用Hibernate更快。 你有很多免费的function – caching,乐观locking等等。

另一方面它有一些隐藏的成本。 当你开始时,Hibernate是非常简单的 。 按照一些教程,在你的课堂上加上一些注释 – 而且你已经有了坚持。 但是这并不简单,能够编写好的代码需要对内部工作和数据库devise有很好的理解。 如果你刚刚开始,你可能不会意识到一些问题,可能会咬你以后,所以这里是一个不完整的列表。

性能

运行时性能足够好,我还没有看到一个情况,hibernate是生产性能差的原因。 问题是启动性能以及它如何影响你的unit testing时间和开发性能。 当hibernate加载它分析所有的实体,并做了大量的预caching – 它可能需要大约5-10-15秒,一个不是很大的应用程序。 所以你的1秒unit testing现在要花费11秒。 不好玩。

数据库独立性

只要您不需要对数据库进行一些微调,就非常酷。

内存中的会话

对于每一个事务,Hibernate都会将一个对象存储在内存中,用于“触及”每一个数据库行。 当你做一些简单的数据input时,这是一个很好的优化。 如果由于某种原因需要处理大量对象,除非明确地仔细清理内存中的会话,否则会严重影响性能。

瀑布

级联允许您简化对象图的工作。 例如,如果你有一个根对象和一些孩子,你保存根对象,你也可以configurationhibernate以保存孩子。 当对象图变得复杂时,问题就开始了。 除非你非常小心,并且很好地理解内部发生的事情,否则很容易搞砸了。 而当你这样做时,很难debugging这些问题。

懒加载

延迟加载意味着每次加载对象时,hibernate都不会加载所有相关的对象,而是提供占位符,只要您尝试访问它们,它们就会被parsing。 大优化的权利? 它是,除了你需要知道这种行为,否则你会得到神秘的错误。 Google以“LazyInitializationException”为例。 并注意性能。 根据你如何加载你的对象和你的对象图的顺序,你可能会打“n + 1select问题”。 谷歌它的更多信息。

架构升级

Hibernate通过重构Java代码并重新启动,允许轻松进行模式更改。 你开始的时候很棒。 但是,然后你释放版本一。 除非你想失去你的客户,否则你需要为他们提供架构升级脚本。 这意味着不需要更简单的重构,因为所有模式更改都必须在SQL中完成。

意见和stored procedures

Hibernate需要独占的写入权限来处理数据。 这意味着你不能真正使用视图,存储过程和触发器,因为那些可能会导致数据的变化,hibernate不知道他们。 您可以有一些外部进程在单独的事务中将数据写入数据库。 但是,如果你这样做,你的caching将有无效的数据。 还有一件事值得关注。

单线程会话

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

我想我的观点是没有免费餐。

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

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

如果你对SQL很熟悉,我强烈build议你看看Ibatis 。 它可以做Hibernate的90%以上,但实现起来要简单得多。

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

看看Spring和Ibatis教程 。

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

但是我真正喜欢Hibernate的方法(也有一些)是可以用Java获得的概念模型。 虽然我不认为面向对象是万能的,但我并没有去寻求devise的理论纯度,但是我发现很多时候OO事实上简化了我的代码。 正如你问的细节,这里是一些例子:

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

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

    • 你写更less的代码,但更重要的是…
    • 在你的模型中有更less的概念(这个独特的概念在代码中是独一无二的)
    • 免费的,你可以编写更通用的代码,提供一个实体(未知的,没有types切换或转换),允许你访问id。
  • Hibernate还有许多function可以处理你可能需要的其他模型特性(现在或以后,只需要添加它们)。 把它作为你的devise的可扩展性质量。

    • 你可以用组合来代替inheritance(子类化)(几个实体具有相同的成员,包含几个实体中恰好需要的相关字段)。
    • 在你的几个实体之间可以有inheritance关系。 通常情况下,您有两个表具有几乎相同的结构(但您不希望将所有数据存储在一个表中,因为您将失去对不同父表的参照完整性)。
  • 通过你的实体之间的重用(但只有适当的inheritance组合 ),通常还有一些额外的好处来。 例子 :

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

由于所有这些原因,我会selecthibernate:-)

我认为要么是一个很好的select,但个人我会使用hibernate。 我不认为冬眠对于这个规模的项目是过分的。

Hibernate真正为我着想的是处理实体/表之间的关系。 如果您同时处理修改父项和子项(孙辈,兄弟姐妹等),手动执行JDBC可能需要很多代码。 Hibernate可以使这个变得轻而易举(通常单个的父实体保存就足够了)。

处理Hibernate的时候肯定有复杂性,比如理解Session flush是如何工作的,以及如何处理延迟加载。

hibernate最适合中间件应用程序。 假设我们在数据库的基础上构build了一个中间件,在这种情况下,我们可以使用大约20个应用程序来访问middelware,我们可以使用一个hibernate来满足所有20个应用程序的需求。

直接的JDBC最适合最简单的情况。

如果你想留在Java和OOD,那么去Hibernate或Hibernate / JPA或任何其他JPA提供程序/ JPA应该是你的select。

如果你更熟悉SQL,那么Spring for JDBC模板和其他面向SQL的框架不会受到影响。

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

…内存中的会话… LazyInitializationException …

你可以看看不使用会话对象的Ebean ORM ,以及懒加载正常工作的地方。 当然是一个选项,而不是矫枉过正,而且会更容易理解。

  1. 在JDBC中,如果我们打开一个数据库连接,我们需要在try中写入,如果发生任何exception,catch块会把它拿走,最后用来closures连接。

  2. 在jdbc中,所有exception都是检查exception,所以我们必须在try,catch和throws中编写代码,但是在hibernate中我们只有Un-checkedexception

  3. 在这里作为程序员,我们必须closures连接,否则我们可能有机会获得我们的连接信息…!

  4. 实际上,如果我们没有closuresfinally块中的连接,那么jdbc不负责closures连接。

  5. 在JDBC中,我们需要在不同的地方编写Sql命令,在程序创build之后,如果表结构被修改了,那么JDBC程序就不能工作,我们需要再次修改,编译和重新部署,这很枯燥。

  6. 如果发生exception,JDBC用于生成与数据库相关的错误代码,但是java程序员对这个错误代码是不知道的。

  7. 当我们插入任何logging的时候,如果我们在数据库中没有任何特定的表,JDBC会产生像“View not exist”这样的错误,并抛出exception,但是在hibernate的情况下,如果没有在表中find任何表数据库这将为我们创build表

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

  9. Hibernate支持inheritance,关联,集合

  10. 在hibernate中,如果我们保存了派生类对象,那么它的基类对象也会被存储到数据库中,这意味着hibernate支持inheritance

  11. Hibernate支持一对多,一对一,多对多,多对一的关系

  12. Hibernate支持这种caching机制,应用程序和数据库之间的往返次数将减less,通过使用这种caching技术,应用程序性能将会自动增加

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

  14. 当我们将logging存储到数据库时,Hibernate能够自动生成主键