`
javaso
  • 浏览: 53230 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

高效使用JavaEE ORM框架(轉)

    博客分类:
  • java
阅读更多

     偶然看到一遍好文, 特別轉載過來。原來地址:這裡    原來作者:廖雪峰

 

     虽然Java领域有无数的ORM框架,如HibernateiBatis ,TopLink,JDO,JPA…… 但是这些ORM框架基本上大同小异。很多初学者对JDBC的复杂性望而却步,就简单认为使用ORM就会省时省力,结果恰恰相反,任何好的框架都是给专家准 备的,任何急功近利试图偷懒的方法往往适得其反。要正确使用ORM还真不是一件简单的事情。本文仅简单整理一下ORM的原理,基本用法,以及如何避免各种 陷阱的基本编程原则。

ORM的原理

先说ORM的实现原理。其实,要实现JavaBean的属性到数据库表的字段的映射,任何ORM框架不外乎是读某个配置文件把JavaBean的属 性和数据库表的字段自动关联起来,当从数据库Query时,自动把字段的值塞进JavaBean的对应属性里,当做INSERT或UPDATE时,自动把 JavaBean的属性值绑定到SQL语句中。但是,几乎所有的ORM都提供“按需读取”的功能,比如一个User有id,name,email和 address这4个字段,但是address字段很少用,于是ORM只读取前3个字段,直到调用User的getAddress()方法时,才去数据库 中读取address的值。这个功能显然不能通过User的get/set完成,因此,ORM需要采用某种方式生成一个User类的子类,并且覆写get /set方法,这样,才能在调用get方法时有机会从数据库中读取。类似的对User的修改检测也是这样实现的。

两种增强的方式

ORM为我们自己的JavaBean实现子类的方法很多,这个过程简单称之为“增强”,基本上有两种方法:Hibernate使用CGLIB在加载 我们的User类时动态创建了一个子类,而JDO则要求编译完User类后再利用它提供的工具对User类进行改造,以便实现JDO需要的各种接口。请注意 :就是这种极其变态的设计导致了使用JDO的极大困难,在我们编译完源码后,还需要额外执行一个增强命令,或者额外编写Ant任务,极大地影响了快速开发和单元测试,所以,凡是采用静态生成持久类的ORM,要在第一时间直接排除,切记!

理解持久和非持久状态

所有的ORM框架都有持久和非持久的概念。简单地说,当我们new一个User实例时,它是非持久对象,当我们调用ORM的save()之类的方法 后,这个实例就变成持久对象了。当我们通过ORM从数据库读取到一个User对象时,这个对象是持久对象,当关闭当前的事务后,这个对象变成非持久对象。

虽然这个过程很容易理解,但是,难点在于当我们设计一个方法时,我们必须准确地知道当前操作的对象是持久对象还是非持久对象,否则,各种灵异事件会 接踵而来,比如插入了重复记录等等。举例说明,当我们需要创建一个User对象时,save(User)方法必须传入非持久对象,当我们需要更新一个 User对象时,update(User)方法必须传入一个持久对象,有些ORM比如Hibernate,为了方便用户,提供了 saveOrUpdate()方法,自动判断是否是持久对象,是则更新,否则创建。我的建议是永远不要使用这些看上去很简单的方法,否则将很难判断ORM 到底做了什么操作,也就很难追踪到逻辑错误。

正确使用CRUD

正因为我们需要时刻区分一个对象的持久化状态,所以,编写CRUD(Create,Retrieve,Update,Delete的缩写)要严格遵循以下原则:

Create :对于Create操作,传入的永远是非持久化对象,一旦调用了create方法,就变成持久化对象;

Retrieve :所有通过ORM从数据库读取的对象都是持久化对象,直到当前会话结束;

Update :对于Update操作,传入的必须是持久化对象,而通常需要更新的对象是从页面获得的,因此,编写Update方法要按照以下步骤:

从Web页面中获得了一个User对象(包含ID),这个对象肯定是非持久化对象;

当得到该User对象时,千万不可直接做Update操作,因为从Web页面得到的数据都是不可信任的,修改HTTP请求非常简单,有经验的开发人 员利用一个FireFox插件就能完成。正确的做法是根据该User对象的ID从数据库中查询到持久化的User对象,然后把待修改的属性复制到持久化的 User对象中,最后Update该持久化的User对象,简单的代码如下:

void update(User u) {
   // 从数据库读取User:
    User p = load(User.class, u.getId());
   // 检查当前用户有无权限修改:
    // TODO: ...
   // 复制属性:
    p.setName(u.getName());
    p.setAddress(u.getAddress());
    // 不允许修改的属性例如email就不要复制了,然后更新:
    update(p);
}
 

Delete :对于Delete操作,ORM通常只关心映射到主键的ID属性,不过,正确的做法仍然是根据ID先通过ORM读取,然后判断权限,最后删除。简单的代码如下:

1. void delete(String id) {
2.      // 从数据库读取User:
3.      User p = load(User. class , u.getId());
4.      // 检查当前用户有无权限修改:
5.      // TODO: ...
6.      // 删除:
7.      delete(p);
8. }

严格按照正确的方法做CRUD操作,使用ORM才能事半功倍。

级联读取

数据库表支持外键关联,因此,ORM也可以把多个JavaBean按照数据库的外键关系联系起来,比如可以在读User对象时把其关联的Profile对象也一并读出来,即所谓级联读取。这又是一个使用起来要非常小心谨慎的功能。

首先,我的建议是级联读取的层次最好是0或1,一般不要超过3,千万不可设为无限,否则,一个简单的查询可能就读取了上万条记录,在开发时由于并发用户只有1,往往看不出问题,等到部署了发现服务器经常内存溢出,其实是级联读取太多导致的。

其次,级联有一对多和多对一两种(一对一可以并入第二种),要非常小心地使用一对多,除非有十分的把握确定“多”的一端只有不超过100条记录。比 如设计论坛时读取“版面”Board时如果有一对多顺便把“话题”Topic一并读入了,随着Topic越来越多,每次读取Board的内存占用也越来越 多,直到最后内存溢出。因此,我的建议是最好不用一对多,凡是有一对多的需求全部采用分页查询的方式解决。

最后,大多数ORM对级联读取都是采用join的方式,在数据量很大的情况时,join操作很慢,而且无法水平分割数据库表。对读取要求很高的应用,最好不要设置级联读取。

缓存

绝大多数ORM都会提供缓存,通常还分为一级缓存和二级缓存。一级缓存只在当前会话内有效,当我们在一个会话里反复读取同一个对象时,只有第一次ORM会从数据库中读取,后续请求会直接从缓存中读取,例如:


1.int id=12345;
2.User u1 = load(User.class, id); // 从数据库读
3.User u2 = load(User.class, id); // 从一级缓存读
4.System.out.println(u1==u2); // True
 

实际上,很少有人会写出这样的代码,所以,一级缓存几乎没有什么作用。

而二级缓存就作用于整个应用。不过,当数据量很小的时候,通过增大数据库服务器的内存就和使用缓存没什么区别,当数据量非常大的时候,二级缓存的命 中率很低,原因当然是缓存大小不够,因此,针对海量数据通常都要自己动手,用memcached做专门的缓存服务器来提高性能。所以,二级缓存不开也罢。

确定事务范围,小心使用Lasy Loading

使用ORM也需要对数据库事务有一定了解,通常ORM的一个会话对应一个数据库事务,如果事务持续时间长,占用的数据库资源就长,数据库并发处理能 力就会降低,所以,事务范围越短越好。对于Web应用,把事务限制在Controller中就比限制在Controller+View中要短,通过MVC 框架提供的各种拦截器可以很方便地开启和关闭事务。当事务限制在Controller时,到了View渲染的时候,就无法使用LasyLoading功能 了。Lasy Loading虽然简单,但不当使用也会造成严重的性能问题,所以还是不用为妙。

以上对ORM框架的使用做了一个简单的概括,实际应用中还需要通过大量实践慢慢探索。

分享到:
评论

相关推荐

    如何高效使用JavaEE ORM框架

    ### 如何高效使用JavaEE ORM框架 #### ORM的原理与应用 对象关系映射(Object-Relational Mapping,简称ORM)是一种程序技术,用于将关系型数据库中的数据映射为对象模型,使得开发者可以在面向对象的环境中操作...

    高效使用JavaEE ORM框架

    ### 高效使用JavaEE ORM框架 #### ORM框架概述与原理 对象关系映射(Object-Relational Mapping,简称ORM)是一种程序技术,用于将面向对象的应用程序中的数据与底层数据库系统之间的交互桥接起来。在Java开发领域...

    高效使用JavaEE+ORM框架.pdf

    本文将深入探讨ORM框架的原理、使用方法及避免常见陷阱的策略。 首先,ORM框架的核心原理是将JavaBean类的属性与数据库表的字段建立映射关系。通过读取配置文件,ORM框架能够自动关联JavaBean的属性和数据库字段。...

    javaee框架总结 文档总结, ssm ssh快速上手

    JavaEE框架是企业级应用程序开发...总结,JavaEE框架如SSM和SSH为开发人员提供了高效、灵活的开发工具,它们降低了开发复杂性,提高了代码质量。通过理解并熟练掌握这些框架,你可以构建出强大且易于维护的企业级应用。

    javaEE框架实现宿舍管理系统.rar

    它通过ORM(对象关系映射)技术将Java对象与数据库表对应起来,使得开发者可以使用面向对象的方式来处理数据库事务,而无需关心底层SQL语句。Hibernate提供了Session接口进行数据的CRUD(创建、读取、更新、删除)...

    JavaEE企业级框架

    6. **Spring框架**:Spring是JavaEE开发中广泛使用的轻量级框架,它提供了依赖注入(DI)和面向切面编程(AOP)等功能,还有Spring MVC、Spring Boot和Spring Data等子项目,涵盖了Web开发、数据访问、事务管理等多...

    JAVAEE 初学者SSH框架

    在JAVAEE开发领域,SSH框架是许多初学者和专业开发者首选的技术栈,它由Spring、Struts和Hibernate三个开源框架组合而成,为Web应用程序提供了一种高效、灵活的开发解决方案。SSH框架的集成使得开发者能够更专注于...

    学习JavaEE以及框架时候的一些项目

    JavaEE是企业级应用开发的重要平台,它提供了一系列标准和组件,使得开发者可以构建高效、可扩展的分布式应用程序。在学习JavaEE的过程中,通常会涉及多个框架,这些框架可以帮助简化开发流程,提高代码的可维护性和...

    lib包jar包javaee开发框架包

    在给定的"lib包jar包javaee开发框架包"中,我们可以推测这可能包含了多个与Java EE开发相关的框架和库的jar文件。例如,它可能包括以下常见的Java EE框架和组件: 1. **Spring框架**:这是一个广泛使用的轻量级框架...

    基于javaEE三大框架ssh实现的办公管理系统

    3. **Hibernate框架**:Hibernate是一个对象关系映射(ORM)工具,它将Java对象和数据库表进行映射,使得开发者可以使用面向对象的方式来操作数据库。在办公管理系统中,Hibernate简化了数据访问层的代码,通过HQL...

    基于JavaEE的快速开发框架

    Tephra旨在构建一个稳定、高效、易于集群、快速扩展的JavaEE开发框架。目前,Tephra已经具备了以下特性: 提供类级别的热更新,但仅建议在需要快速修正严重BUG、并且无法立即进行全更新时使用。 提供全冗余方式的...

    javaEE中SSH框架jar包.zip

    总结起来,SSH框架的使用大大简化了JavaEE应用的开发过程,提高了代码的可维护性和可扩展性。它通过组合这三个强大的框架,为企业级应用提供了完整的解决方案,从用户交互到业务逻辑再到数据存储,都有相应的工具和...

    javaEE框架构建2022

    JavaEE框架构建2022主要涵盖了现代企业级应用程序开发的核心技术与框架。作为一个专业的IT行业专家,我将深入解析这个主题,详细讲解JavaEE框架的构建及其在2022年的最新发展。 首先,JavaEE(Java Enterprise ...

    Javaee三大框架课程设计

    JavaEE三大框架,即Struts2、Spring和Hibernate,是Java企业级开发中的核心组件,广泛应用于构建高效、可维护的Web应用。本课程设计旨在深入理解和熟练掌握这三大框架的集成与应用。 首先,Struts2是MVC(Model-...

    基于Javaee ssh框架的在线考试系统毕业论文

    【JavaEE SSH框架在线考试系统】是一个典型的Java企业级应用,使用了Struts2作为表现层框架、Spring作为业务层框架、Hibernate作为持久层框架,实现了完整的MVC(Model-View-Controller)设计模式。SSH框架结合了这...

    javaee框架技术aa

    2. **JPA与Hibernate**:Java Persistence API(JPA)是JavaEE中用于对象关系映射(ORM)的标准接口,允许开发者以面向对象的方式操作数据库。Hibernate是JPA的一种实现,它提供了丰富的功能,如事务管理、缓存策略...

    开发javaee框架所需的全部包

    3. **Hibernate**:Hibernate是一个对象关系映射(ORM)框架,它允许开发者使用面向对象的方式来操作数据库。通过Hibernate,你可以避免直接编写SQL,而是使用Java对象进行数据操作,大大简化了数据库访问。 4. **...

    javaee框架练习Code.rar

    这个名为"javaee框架练习Code.rar"的压缩包文件提供了基础的练习代码,帮助学习者深入理解并掌握这些框架的使用。 首先,Spring框架是JavaEE应用中的核心框架,它提供了依赖注入(Dependency Injection,DI)和面向...

    基于 JavaEE 的快速开发框架 Tephra-JavaEE

    Tephra旨在构建一个稳定、高效、易于集群、快速扩展的JavaEE开发框架。目前,Tephra已经具备了以下特性: 提供类级别的热更新,但仅建议在需要快速修正严重BUG、并且无法立即进行全更新时使用。 提供全冗余方式的...

Global site tag (gtag.js) - Google Analytics