`

从一个实体类对应多个表的困难来看Hibernate的实体表,以及我对Hibernate、ORM设计理念的认识

阅读更多

 


     这几天在工作中,需要设计一个业务中需要的类,想把这个类从数据库里取出来的时候发现使用Hibernate并不容易实现。工作代码不好直接拿出来,举个差不多的例子吧。
 
     例如用户在系统中,保存的信息包括简要信息(用户名、联系电话、Email、性别)和一些图像信息(照片)。
 
     但是在系统设计时,我的设计方式都是遵循业务的需要,设计一个“用户”类,包含用户名、联系电话、Email、性别和照片信息。这个时候我是不会考虑数据库设计的,这是一个设计原则:“不因为实现妨碍设计”。
 
     在后面的数据库设计中因为照片比较大,所以保存的时候,会设计成两个表:用户简要信息表和用户照片表,两个表通过“用户ID”字段关联。
 
     如果使用JDBC实现比较简单,直接使用SQL,使用联合查询查到用户所有信息,返回成为对象,比较简单。但是因为项目早期的设计开发人员选择了Hibernate,只有沿着这个方向做了,我发现比较困难,因为Hibernate的机制就是一个表对应一个“实体对象”。
 
     没有办法,我只能建立两个实体对象,业务对象User中,改成这样:
 
 
    class User{
          UserSimpleInfo sinfo;
          UserPhotoIfo   pinfo;
     }
 
 
     感觉真够滑稽的。也许还有好的解决方案,只是我没有找到而已,我也会继续去寻找。就现在看来,没有找到这方面好的资料。
 
     我现在觉得这是不可思议的一个做法。对象的设计,应该是从业务的分析和业务逻辑中来,和设计没有那么紧密的关系。应该是由设计觉得实现,不应该由实现决定设计。一种实现或是一种框架,不管功能是否强大,都不能“绑架”设计,要设计“屈从”,这是框架设计的一个基本原则。
 
     实际上,一个表对应一个实体对象是很多情况下一个很自然的选择,但并不是必须的做法,如果限制了一定要这么设计实现,那就是非常荒谬的。我经常面向的领域和客户,经常面对的场景里,一个对象拆成几个表是非常有可能的事情。所以,ORM应该支持这种场景。
 
     从另外一个方面看,一个表对应一个实体类是一个有欠考虑的理念。当然,ORM如果支持一个类映射多个表,复杂度增大了很多,用起来也更困难了。没办法,想做通用的东西,肯定比转做一个领域和业务要困难啊。
 
     我本来就不喜欢ORM这东西,这让我更加讨厌Hibernate这类ORM框架,为此特意找了一些网上的资料,觉得这东西还是很不错的,尤其是一些需求简单的场景里,但是支持它的一些说法和理由却站不住脚:
 
     有人说:Hibernate出现的目的,是为了可以让我们这些写代码的,可以更集中精力处理业务代码,而不是把心思放在怎么构建SQL语句。
 
     我的意见:SQL本身也就是体现业务逻辑的。一个产品,本身包含的不仅有功能需求,还有效率、存储方面等等需求。
 
     有人说:在还没有O/R MAPPING之前,我们在团队开发的时候,实现一个业务逻辑前的事情,就是跑去问DBA或者找系统的数据库 字典,要先把这个逻辑所用到的字段类型、大小、约束都搞清楚,才能开始做编码工作,因为我们需要构建特定的SQL语句、在代码放入各种的逻辑判断……
     在有了O/R MAPPING之后,这种现象才得到基本解脱,因为我们要操作表里的数据,只需要直接对映射类操作即可,O/R MAPPING会自动生成所需要的SQL语句……
 
     我的意见:类型、大小、约束和需要在代码里放入的逻辑判断本身也是业务逻辑的一个部分。不管你用何种理念和工具,都要考虑和面对的。
 
     有人说:不使用ORM,那么多的get/set多烦人啊,写那些SQL多烦人啊。而且不容易维护。
 
     我的意见:即便不使用现有的ORM,也肯定会采用面向对象的方式,把数据库的对象和业务对象封装起来给上层使用。业务层面看到的,也是非常清晰的存、取功能调用而已。不会到处都是JDBC的调用和ResultSet的set和get,更不会SQL满天飞。这在一定程度上其实和Hibernate、MyBatis差不多,但是因为不用考虑通用性,所以设计实现起来比较容易,且都是根据自己产品需要来设计,量体裁衣,最最适合自己的产品使用。
     另外说到写SQL,我认为,写好SQL是设计和实现人员的基本功,不能在这里偷懒。我觉得有个人说的(忘了是谁了):“SQL是丑陋的,难以理解的。”这句话是站不住脚的。如果SQL是邪恶的,那么JNI是什么样的呢?SQL是一门非常精炼和优雅的语言,更是一门艺术。SQL中蕴藏了非常简练干净、清晰的概念,非常稳定的架构。
 
     我不会只是从效率方面考虑问题,我更多的考虑是:
     对象应该从业务的分析中来,对象和数据库表毫无关系,对象应该能够从数据存储层取出来,应该能通过存储层保存起来------至于什么表格式等等,都不影响这些上层设计。从数据库表产生实体对象很糟糕;从实体对象产生表结构也一样不好。如上一条所说,对象从业务中来;表的设计,是要根据对象的设计和数据库自身的特点、产品或项目的需求(例如效率需求和不同数据库自身的不同特性)而来的。
     一个项目和产品,很多时候就是应该设计师、实现者和DBA共同努力来做好的,或者另外一种情况,一个团队里,本身就应该有一个或几个精通数据库或SQL的人,来一起做,不能因为说“SQL我不熟悉”或者“写好SQL太困难”为理由,对效率和存储方面的需求视而不见。或者简单的说“OO和关系数据库直接由天然阻抗”。做好数据持久层,一定是需要熟悉或精通数据库和SQL的人。
 
     或者,你做一个对效率、存储、持续性都没有什么要求的项目或产品,那另当别论。又或者经过一段时间的学习和体验,我会改变自己现在的看法。
 
 
 
 
 
 
 

 

2
3
分享到:
评论
4 楼 windshome 2013-06-27  
嗯,jinnianshilongnian 的回复也告诉我这个问题了,我也专门发文章,一则致谢,二是说明自己了解太少。

我觉得分开实体类是一种设计选择,有时候挺好,有时候不好,业务场景不同。但是原则应该是,不从实现角度考虑设计,二是从业务需要考虑设计。这里也感谢楼上的建议。
3 楼 jilo88 2013-06-27  
hibernate 是支持你说的这种一个实体映射多个表的,你可以看看如下这个网友写的内容,:http://huihai.iteye.com/blog/1285638,他这里用的是contact标签,这样分开实体类也有好处,当你只加载用户信息,不加载图片信息时,就可以利用hibernate的load lazy特性来装载数据,这样只会查询得到用户信息,而不会将图片信息也查询到。
2 楼 windshome 2013-06-26  
感谢  jinnianshilongnian ,是我接触的时间太短,还没有看到这个。

相关推荐

    Hibernate ORM - 一对多双向关联关系

    标题“Hibernate ORM - 一对多双向关联关系”指的是在数据库建模中,Hibernate ORM(对象关系映射)框架如何处理一个实体类(如User)与多个实体类(如Article)之间的关系。在这种关系中,一个用户可以拥有多个文章...

    Hibernate实体层设计

    总的来说,Hibernate实体层设计是一个综合性的任务,它涉及到对象模型、数据库映射、关系处理、性能优化、事务管理等多个方面。理解和熟练掌握这些知识,能够帮助我们构建出高效、稳定的Java企业应用。

    Myeclipse自动生成Hibernate配置文件及实体类映射ORM

    Myeclipse 自动生成 Hibernate 配置文件及实体类映射 ORM 配置文件 Myeclipse 是一个功能强大的集成开发环境(IDE),它提供了许多实用的功能来简化软件开发过程。在这个示例中,我们将展示如何使用 Myeclipse 自动...

    hibernate实体生成工具

    在Hibernate中,实体类代表数据库中的表,每个实体类对应一个表,类的属性对应表的列。实体类通常会使用`@Entity`注解来标记,并通过`@Table`注解指定对应的数据库表名。实体类的属性使用`@Column`注解来映射表的列...

    hibernate 映射关系学习入门 多对多实体映射

    Hibernate是一个对象关系映射(ORM)框架,它允许我们将Java对象(实体)与数据库表进行映射,从而实现了面向对象编程和关系数据库之间的桥梁。Hibernate提供了强大的查询语言HQL(Hibernate Query Language)以及 ...

    Hibernate ORM - 一对一连接表关联关系

    2. **一对一关联(One-to-One)**: 在数据库设计中,一对一关联意味着两个实体之间存在唯一的关系,即每个实体实例仅对应另一个实体的一个实例。例如,一个用户可能有一个唯一的身份证信息。 3. **注解配置**: ...

    Hibernate ORM - 多对多双向连接表关联关系

    在数据库设计中,多对多关系意味着一个实体可以对应多个其他实体,反之亦然。例如,一个学生可以选修多门课程,一门课程也可以被多个学生选修。为了在数据库层面实现这种关系,通常需要创建一个中间表(连接表),...

    生成hibernate实体类

    2. **引入Hibernate工具**:Hibernate提供了一个名为`hibernatetool`的命令行工具,或者可以通过IDE插件(如Eclipse或IntelliJ IDEA的Hibernate插件)来实现实体类的自动生成。你需要在项目中添加Hibernate的相关...

    hibernate学习入门一对多实体映射源码

    在数据库设计中,一对多关系是一种常见的关联类型,意味着一个父实体可以有多个子实体,而每个子实体只能属于一个父实体。例如,一个学生可以对应多门课程,而一门课程只能被一个学生选修。 三、配置一对多映射 在...

    Hibernate实体映射

    综上所述,"Hibernate实体映射"的学习资源涵盖了从基本概念到实际操作的多个方面,对于想深入了解Hibernate ORM框架的开发者来说,无疑是一份宝贵的资料。通过实践这些实例代码,可以加深对Hibernate实体映射的理解...

    Hibernate ORM - 一对多双向连接表关联关系

    2. **一对多关联**:在数据库设计中,一对多关联表示一个表(父表)的记录可以与另一个表(子表)的多个记录相关联。在Hibernate中,这通常通过`@OneToMany`注解来实现。 3. **双向关联**:双向关联意味着两个实体...

    hibernate生成实体类

    - 在生成实体类之前,建议先对数据库表进行一定的规范化处理,如合理设计字段、添加注释等,这样生成的实体类会更加规范易读。 - 生成的实体类默认可能包含所有字段的getter和setter方法,对于不需要持久化的字段...

    根据数据库表生成实体、hibernate配置文件和实体映射文件

    在IT行业中,数据库是存储和管理数据的核心工具,而Hibernate是一个流行的关系型对象-关系映射(ORM)框架,它简化了Java应用与数据库之间的交互。本教程将深入讲解如何根据数据库表自动生成实体类、Hibernate配置...

    Hibernate ORM - 一对多双向组合关联关系

    在关系型数据库中,一对多关联意味着一个父实体可以与多个子实体相对应,而双向则表示这种关系是相互的,即父实体可以找到其所有子实体,同时每个子实体也能追溯到其父实体。 **描述:** 由于描述为空,我们无法从...

    Hibernate_ORM步骤详解

    完成逆向工程后,Hibernate会自动生成与数据库表对应的实体类和`hbm.xml`映射文件。这些实体类代表了数据库中的表,而`hbm.xml`文件定义了类与表之间的映射规则。这样,我们就可以通过操作实体类来间接操作数据库。 ...

    hibernate-orm-3.3源码

    本文将针对《hibernate-orm-3.3源码》进行深度解析,帮助读者理解其核心设计理念与实现机制。 一、Hibernate概述 Hibernate 是一款开源的 Java 库,它简化了数据库操作,通过将 Java 对象与数据库表之间的映射关系...

Global site tag (gtag.js) - Google Analytics