我有一个胖客户端,带有25个表和约15个JInternalFrames(表的数据输入表单)的架构的java swing应用程序。我需要为DBMS交互选择直接的JDBC或ORM(在这种情况下为Spring框架休眠)的设计选择。应用程序的构建将在将来发生。
对于这样规模的项目,冬眠会显得过大吗?对于肯定或否定答案的解释将不胜感激(如果需要,甚至可以采用其他方法)。
TIA。
我有一个胖客户端,带有25个表和约15个JInternalFrames(表的数据输入表单)的架构的java swing应用程序。我需要为DBMS交互选择直接的JDBC或ORM(在这种情况下为Spring框架休眠)的设计选择。应用程序的构建将在将来发生。
对于这样规模的项目,冬眠会显得过大吗?对于肯定或否定答案的解释将不胜感激(如果需要,甚至可以采用其他方法)。
TIA。
Answers:
好问题,没有一个简单的答案。
在多年使用多个项目后,我曾经是Hibernate的忠实拥护者。我曾经相信任何项目都应默认为休眠状态。
今天我不太确定。
Hibernate(和JPA)在某些方面非常有用,尤其是在开发周期的早期。使用Hibernate进行操作要比使用JDBC快得多。您可以免费获得许多功能-缓存,乐观锁定等。
另一方面,它有一些隐性成本。开始时,Hibernate非常简单。遵循一些教程,在您的课程上添加一些注释-您便会拥有持久性。但这并不简单,并且要能够编写出色的代码,需要对它的内部工作原理和数据库设计有充分的了解。如果您只是刚开始,您可能不知道以后可能会遇到的某些问题,因此这里是不完整的列表。
性能
运行时性能足够好,我还没有看到冬眠是生产性能不佳的原因。问题在于启动性能以及它如何影响您的单元测试时间和开发性能。当休眠加载时,它会分析所有实体并进行大量预缓存-对于不太大的应用程序,可能需要5-10-15秒。因此,您的1秒钟单元测试现在将花费11秒。不好玩。
数据库独立性
只要您不需要对数据库进行一些微调,它就会非常酷。
内存会议
对于每个事务,Hibernate都会为它“接触”的每个数据库行在内存中存储一个对象。当您进行一些简单的数据输入时,这是一个很好的优化。但是,如果由于某种原因需要处理大量对象,除非您自己明确且仔细地清理内存中的会话,否则它可能会严重影响性能。
级联
级联使您可以简化对象图的使用。例如,如果您有一个根对象和一些子对象,并且保存了根对象,则可以将休眠配置为也保存子对象。当您的对象图变得复杂时,问题就开始了。除非您非常谨慎并且对内部发生的事情有充分的了解,否则很容易将其弄乱。而且当您这样做时,很难调试这些问题。
延迟加载
延迟加载意味着每次加载对象时,休眠将不会加载其所有相关对象,而是会提供占位符,当您尝试访问它们时将对其进行解析。优化效果好吗?是的,除非您需要了解此行为,否则您将得到隐秘的错误。以Google“ LazyInitializationException”为例。并注意性能。根据加载对象和对象图的顺序,您可能会遇到“ n + 1选择问题”。谷歌它的更多信息。
架构升级
Hibernate只需重构Java代码并重新启动,即可轻松更改架构。一开始就很棒。但是随后您发布了版本1。并且,除非您想失去客户,否则需要向他们提供架构升级脚本。这意味着不再需要简单的重构,因为所有模式更改都必须在SQL中完成。
视图和存储过程
Hibernate需要对其使用的数据具有独占写入权限。这意味着您不能真正使用视图,存储过程和触发器,因为那些视图,存储过程和触发器会导致休眠状态下的数据更改(不知道)。您可以让一些外部进程在单独的事务中将数据写入数据库。但是,如果这样做,缓存将包含无效数据。还有另一件事要注意。
单线程会话
休眠会话是单线程的。通过会话加载的任何对象只能从同一线程访问(包括读取)。这对于服务器端应用程序是可接受的,但是如果您正在基于GUI的应用程序,则可能会使不必要的事情变得复杂。
我想我的意思是没有免费的饭菜。
Hibernate是一个很好的工具,但它是一个复杂的工具,需要时间来正确理解它。如果您或您的团队成员不了解这些知识,则对于单个应用程序使用纯JDBC(或Spring JDBC)可能会更简单,更快。另一方面,如果您愿意花更多的时间来学习它(包括边做边学和调试),那么将来您将能够更好地了解这些取舍。
Hibernate可能很好,但是它和其他JPA ORM往往会在一定程度上决定您的数据库结构。例如,复合主键可以在Hibernate / JPA中完成,但是有点尴尬。还有其他例子。
如果您熟悉SQL,我强烈建议您看一下Ibatis。它可以完成Hibernate的90%以上的工作,但是实现起来要简单得多。
我想不出为什么要选择Ibatis的直接JDBC(甚至是Spring JDBC)的单一原因。休眠是一个更复杂的选择。
毫无疑问,Hibernate具有其复杂性。
但是,我真正喜欢Hibernate方法(还有其他一些方法)的是,您可以在Java中获得更好的概念模型。尽管我不认为OO是万能的灵丹妙药,而且我也不追求设计的理论纯度,但是我发现了很多次,OO确实简化了我的代码。如您特别要求的详细信息,以下是一些示例:
例如,增加的复杂性不在模型和实体中,而在您用于操作所有实体的框架中。对于维护者来说,困难的部分不是几个框架类,而是您的模型,因此Hibernate允许您将困难的部分(模型)保持在最干净的状态。
如果在您的所有实体中都使用了字段(例如ID或审核字段等),则可以使用该字段创建超类。因此:
Hibernate还具有许多功能来处理您可能需要的其他模型特征(现在或以后,仅根据需要添加它们)。将其视为设计的可扩展性。
随着实体之间的重用(但只有适当的继承和composition),通常会有一些其他优点。例子 :
随着时间的流逝,需求不断变化。在某种程度上您的数据库结构有问题。仅使用JDBC,对数据库的任何更改都必须影响代码(即,双倍成本)。使用Hibernate,仅更改映射而不更改代码可以吸收许多更改。反之亦然:Hibernate允许您更改代码(例如,在版本之间),而无需更改数据库(更改映射,尽管并不总是足够的)。总而言之,Hibernate让您独立地开发数据库和代码。
由于所有这些原因,我会选择Hibernate :-)
在JDBC中,如果我们打开数据库连接,则需要在try中编写代码,并且如果发生任何异常,catch块将接受它,最后用于关闭连接。
在jdbc中,所有异常都是经过检查的异常,因此我们必须在try,catch和throws中编写代码,但是在休眠状态下,我们只有未检查的异常
在这里,作为程序员,我们必须关闭连接,否则我们将有机会获得连接消息……!
实际上,如果我们没有在finally块中关闭连接,则jdbc不负责关闭该连接。
在JDBC中,我们需要在各个位置编写Sql命令,在程序创建后,如果表结构被修改,则JDBC程序将无法正常工作,同样,我们需要修改,编译和重新部署,这很繁琐。
如果发生异常,JDBC用来生成与数据库相关的错误代码,但是Java程序员对此错误代码一无所知。
当我们插入任何记录时,如果我们在数据库中没有任何特定的表,则JDBC将引发诸如“视图不存在”之类的错误,并引发异常,但在休眠的情况下,如果未在数据库中找到任何表数据库将为我们创建表
JDBC支持LAZY加载,而Hibernate支持Eager加载
Hibernate支持继承,关联,集合
在hibernate中,如果我们保存派生的类对象,则其基类对象也将存储到数据库中,这意味着hibernate支持继承
Hibernate支持诸如一对多,一对一,多对多对多,多对一的关系
通过这种方式,Hibernate支持缓存机制,将减少应用程序与数据库之间的往返次数,通过使用这种缓存技术,应用程序性能将自动提高。
在休眠状态下进行分页非常简单。
当我们将记录存储到数据库中时,Hibernate具有自动生成主键的功能
如果数十亿用户使用了应用程序或Web,则在jdbc查询中将执行数十亿次时间,但在休眠查询中,对于任何数量的用户而言,与jdbc相比,最重要和最简单的休眠优势将仅执行一次。