Hibernate或JDBC

jmq*_*jmq 68 java hibernate jdbc

我有一个胖客户端,java swing应用程序,具有25个表的模式和~15个JInternalFrames(表的数据输入表单).我需要在DBMS交互中进行直接JDBC或ORM(在这种情况下使用spring框架进行hibernate)的设计选择.应用程序的构建将在未来发生.

对于这么大的项目,hibernate是否会过度杀伤?对是或否答案的解释将非常感激(如果有必要,甚至是不同的方法).

TIA.

Gre*_*zky 184

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

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

今天我不太确定.

Hibernate(和JPA)对某些事情很有用,尤其是在开发周期的早期阶段.使用Hibernate比使用JDBC要快得多.您可以免费获得许多功能 - 缓存,乐观锁定等.

另一方面,它有一些隐藏的成本.当你开始时,Hibernate很简单.按照一些教程,在你的课上加上一些注释 - 你就有了自己的坚持.但它并不简单,能够在其中编写好的代码需要很好地理解它的内部工作和数据库设计.如果你刚刚开始,你可能不会意识到一些可能会在以后咬你的问题,所以这里有一个不完整的列表.

性能

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

数据库独立性

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

内存会话

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

瀑布

Cascades允许您简化对象图的使用.例如,如果您有一个根对象和一些子节点并且保存了根对象,则可以配置hibernate来保存子节点.当对象图变得复杂时,问题就开始了.除非你非常小心并且对内部发生的事情有很好的理解,否则很容易弄清楚这一点.当你这样做时,很难调试这些问题.

延迟加载

延迟加载意味着每次加载对象时,hibernate都不会加载所有相关对象,而是提供占位符,一旦您尝试访问它们就会被解析.伟大的优化对吗?它是,除了你需要知道这种行为,否则你会得到神秘的错误.Google以"LazyInitializationException"为例.并且要小心表现.根据加载对象和对象图的顺序,您可能会遇到"n + 1选择问题".谷歌它提供更多信息.

架构升级

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

视图和存储过程

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

单线程会话

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

我想我的观点是没有免费的饭菜.

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

  • +1很棒的答案..我曾经认为Hibernate是有史以来最好的东西,但是随着我们的应用程序在复杂性上越来越大(更大的对象图),我遇到了一些场景,其中debuging是一场噩梦,因为我不知道什么是hibernate这样做.(幸运的是,它是开源的,所以我能够通过源头来解决它.没有乐趣)无论如何,我同意..没有免费餐.Hibernate很棒,但有一些权衡. (5认同)

cle*_*tus 20

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

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

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

看看Spring和Ibatis教程.


KLE*_*KLE 12

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

但我真正喜欢的Hibernate方法(其他一些方法)是你可以用Java获得的概念模型更好.虽然我不认为OO是灵丹妙药,而且我没有寻找设计的理论纯度,但我发现很多次OO确实简化了我的代码.正如您专门询问的详细信息,以下是一些示例:

  • 增加的复杂性是不是在模型和实体,但在你的操纵所有实体,例如框架.对于维护者来说,困难的部分不是一些框架类,而是你的模型,因此Hibernate允许你将最难的部分(模型)保持在最干净的状态.

  • 如果在所有实体中使用了字段(如id或审计字段等),则可以使用它创建超类.因此:

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

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

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

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


Bri*_*ger 5

我认为要么是一个很好的选择,但我个人会使用hibernate.我不认为hibernate对于那么大的项目来说太过分了.

Hibernate真正让我感到惊讶的是处理实体/表之间的关系.如果您同时处理修改父项和子项(孙子,兄弟姐妹等),手工执行JDBC可能会占用大量代码.Hibernate可以使这变得轻而易举(通常单个保存父实体就足够了).

然而,在处理Hibernate时肯定存在复杂性,例如理解Session刷新的工作原理以及处理延迟加载.