`
xxka87xxka
  • 浏览: 17026 次
最近访客 更多访客>>
p_7
社区版块
存档分类
最新评论

POJO式开发

 
阅读更多

POJO式开发
2011年03月17日
  POJO         POJO 就是简单 java 对象,不实现任何特殊接口。 POJO 这一名字由 Fower 、 Rebbecca 、 Parsos 、 Josh MacKenzie(Foeler POJO) 发明,目的地是为了给普通 Java 对象取个令人兴奋的、过目不忘的名字。
  早期 EJB 及其存在的问题
  EJB1.0 版本发布于 1998 年,它提供了两种企业 bean :会话 bean 和实体 bean 。会话 bean 便是无状态服务或与客户端之间的有状态会话。实体 bean 表示数据库里的数据,最初意在实现业务对象。 EHB2 提炼了 EJB 编程模型。不仅增加了支持由容器管理的关系增强型实体 bean ,还新增了消息驱动 bean( 负责处理 Java Message Service 或 JMS ,消息 ) 。
  EJB 存在的问题
  尽管有很多书帮助开发人员对付 EJB ,并学会如何有效的使用 EJB ,但是 EJB 的;两个主要问题并没有直接解决。
  第一,    EJB 鼓励开发人员编写过程式应用程序
  第二,    使用 EJB 开发相当麻烦
  过程式设计的缺点:
  对业务逻辑的组织方式主要有两种:过程式或面向对象。过程式方式以函数为单元组织代码,这些函数操作单独的简单数据对象。在过程式架构中,数据结构遍布各处,并作为参数传入函数,或返回给调用函数。 数据与操作之间的关系非常松散 ,并且完全由开发人员自己维护。在面向对象语言出现之前,这种编程方式主导了软件开发。
  与之相比,面向对象方法则以对象为单元组织代码,这些对象 具有状态和行为 ,并与其他对象协作。 数据结构和操作定义在一个语言构造单元内,数据和对数据操作并存于其中。数据和操作之间的关系 ( 和状态 ) 由语言本省维护 。与过程式设计相比,面向对象设计更易理解、维护、扩展和测试。
  如果业务逻辑够简单,过程式设计方法倒也不成问题,但是业务逻辑总有变得愈加复杂的趋势。一旦需求改变,业务逻辑就必须实现新的特性, EJB的代码量会不断增加。
  EJB2 在一定程度上就是鼓励人们编写过程式代码, 实现新行为时,不必像设计真正的对象模型那样费心地识别类并赋予其职责。相反,你可以编写一个新的会话 bean 方法或在现有方法里添加代码 。
  这钟过程式的设计方法,有些开发人员仍把持久对象简单的视为一种向数据库存取数据和编写过程式业务逻辑方法,这就是所谓的贫血模型
  EJB 开发的麻烦:
  n          你必须面对恼人而长的编辑 - 编译 - 调试周期
  n          你得面对关注点缺少分离的显示
  n            你必须编写大量的代码才能实现一个 EJB
  n          你必须编写数据传输对象 (DTO)
  用 POJO 开发
  用 POJO 进行开发,仅有 POJO 本身还是不够的。在企业应用程序里,你还需要诸如事务管理、安全和持久化等服务,此前这些服务由 EJB 容器提供。现在的解决方案是使用所谓"轻量级"框架来代替 J2EE STACK 里的一些"重量级"部分。主要是 4 种轻量级框架: Hibernate 、 JDO 、 Ibatis 和 Spring 。
  这些技术的主要特征在于他们都是非侵入式的。它们提供事务和持久化时并不要求应用程序类实现任何特殊接口。甚至当应用程序的类需要运行在事务里或者持久化的时候,它们仍是 POJO 。
  典型的 EJB 和 POJO 方法比较
  典型的 EJB 方法 POJO 方法 组织 过程式业务逻辑 面向对象设计 实现 基于 EJB POJO 数据库访问 JDBC/SQL 或实体 Bean 持久层框架 返回给表示层的数据 DTO 业务对象 事务管理 EJB 容器管理的事务 Spring 框架 应用程序组装 显示的 JNDI 查询 依赖注入     l          面向对象设计
  整个设计更容易理解和维护
  更易于测试
  更易扩展
  l          使用 POJO
  开发更加容易
  更加快捷
  可移植性增强
  l          持久化 POJO
  使用 JDO 和 Hibernate 提供透明持久化,这意味着类不会意识到它们是持久的。应用程序只需要调用持久层框架 API 保存、查询和删除持久对象、而且对测试也很方便。
  l          消除 DTO
  DTO 又称为值对象( value object )。 DTO 只是一个由成员变量组成的简单行为对象,用于从业务层向表示层返回数据。这是由于表示层无法高效地访问 EJB2 实体 bean ,因此 EJB 程序需要 DTO 。
  向表示层返回 Hibernate 、 JDO 、 EJB3 对象有两种方式。一种选择是表示层返回仍持久地的对象。另一种做法是让业务层返回脱管对象。
  l         是 POJO 具有事务性
  用 spring 管理事务。对测试也很方便。
  系统设计时需要考虑的五大因素:
  
  1 、如何组织业务逻辑
  2 、如何封装业务逻辑,以及暴露给表示层及其他客户程序调用的接口
  3 、如何访问数据库
  4 、如何处理短事务中的并发
  5 、如何处理长期运行事务中的并发 决策 选项 业务逻辑封装 EJB Session Fa??ade 模式 POJO Fa??ade 模式 Exposed Domain Model 模式 数据库访问 直接使用JDBC
  iBATIS
  Hibernate
  JDO 数据库事务中的并发 不理睬该问题
  悲观锁
  乐观锁
  可串行化隔离级别 长期运行事务中的并发 不理睬该问题
  Pessimistic Offline Lock
  模式
  Optimistic Offline Lock 模式     以上5 个决策每个都有多种选项。基于EJB 的设计,它由会话bean 实现的过程式代码组成,并使用JDBC 访问数据库。相比之下,基于POJO 的设计由对象模型组成,通过JDO 、Hibernate 等O/R 框架映射到数据库,并用使用Spring 进行事务管理的POJO fa??ade 进行封装。每种选项都有优缺点,这也决定了它只能适用于某种具体情况。每种选项都会在一个或多个方面做出一定的妥协,包括功能性、开发难易度、可维护性和可用性等,需要自己的应用程序作出最佳选择。
  封装业务逻辑
  业务逻辑的接口由那些可被表示层调用的类型(type )和方法(method ) 组成。接口设计的要点是应当封装多少业务逻辑的实现,并对表示层不可见。封装隐藏了业务逻辑的实现细节,可以防止表示层受业务逻辑变化的影响,从而提升可 维护性。同时还需考虑怎样处理事务、安全性和远程调用等问题,因为通常这些都是业务逻辑接口代码的职责。一般来说,业务层接口应保证对业务层的每个调用都 在事务中执行,以便保证数据库的数据一致性。同样的,业务层接口还要验证调用者是否有足够的权限来调用某种业务方法。此外,它还要负责处理某些远程客户 端。  
  若存在表示层远程访问业务层API 的情况,尽量将业务层的API 设计成粗粒度的,这样对业务层的调用越少,数据库事务数量就越少,内存缓存对象的机会就越多。还能减少网络来回传输次数。
  单个数据库 事务中的并发
  完全事务脚本、乐观(optimistic )锁、悲观(pessimistic )锁 
  完全事务脚本 是一种解决方案是使用完全和其他事务隔离的事务,用数据库的话来说,就是隔离级别为serializable (串行化)的事务(悲观锁的另一种方案)。数据库保证:执行多个 serializable 事务的结果和一个个串行执行它们的结果一样。serializable 事务避免了更新丢失、读取不一致等问题。一些数据库还提供了repeatable read (能够保持一致的重复读取)和Read committed 的 隔离级别,完全隔离事务有两个主要优点:一是使用简单;二是避免了很多并发问题,包括修改丢失和读取不一致的问题。完全隔离事务的主要缺点是开销太大,降 低了性能和规模扩展性,不管有没有并发更新,都需要额外开销。而且,由于死锁和其他并发相关问题,完全隔离事务比低隔离级别的事务的失败频率更高。用serializable 或者repeatable read 隔离级别的事务,这种方案不需要数据库模式变化。因为数据库的serializable 事务机制能够处理并发更新,所以不需要用语句来锁住记录,也不需要维护版本号。在spring 中可以通过配置数据源的属性"defaultTransactionIsolation "为"SERIALIZABLE "来实现。 
  乐观锁的工作原理 是让应用程序检查它即将更新的数据是否已被另一个事务修改(自该数据上次读取以来)。实现乐观锁的一种常见做法是在每个表里添加一个版本字段,每次应用程序更新数据表记录时就增加这个版本字段。每个UPDATE 语句中的WHERE 子句会根据上次读取的值来判断这个版本号是否改变。使用诸如JDO 和Hibernate 的持久层构架时,实现乐观锁更为容易,因为它们已将乐观锁作为配置选项提供。 
  应用程序或持久层框架有三种方法可以判断一条记录自从上次读取出来后是否被修改过。 
  第一种方法是 用一个version (版本)字段来跟踪记录修改状况 ,每次修改,version 都会递增。事务只需要把原来读出的 version 和当前version 进行比较,就可以判断一条记录是否被修改过。应用程序检查和修改version 字段是比较简单的做法,通常也是最好的做法。
  第二种方法是 用时间戳字段,每次应用程序修改数据,时间戳也会更新 。 事务只需要把原来读出的时间戳和当前时间戳进行比较,就可以判断一条记录是否被修改过。这个表结构也很容易实现,尤其是这种情况下,数据表经常已经有一个 时间戳字段来记录用户修改记录的时间。然而,时间戳的问题是,如果两个修改操作之间的时间差小于时钟最小单位,那么一个事务可能覆盖另一个事务的修改。所 以,只有在无法增加version 字段的遗留系统中,才应该使用时间戳,否则,尽量使用version (版本)。
  第三种方法是 把上次读出的字段值和现有字段值进行比较 。这种方法最大的好处是,不需要引入version 或者时间戳字段,所以可以用在遗留系统中。这个方法的一个缺点是使得SQL UPDATE 更加复杂,因为WHERE 子句里面包含所有的字段的条件(具体原因我们后面会详述)。还必须正确处理null 字段,可能比较复杂。比如,有一次我发现,一个持久层框架不能正确比较空字符串,因为Oracle 把空字符串认为是null ,这和Java 不一样。我们在数据表里面增加了一个版本字段,解决了这个问题。
  第三种方法的另一个缺点是,浮点数字段不能精确比较,浮点数字段的修改可能发现不了。由于这些问题,应用程序只有在别无选择,无法应用版本和时间戳的情况下,才应该使用这种方法。
  悲观锁的工作原理 是 当读取某些记录时,事务先锁住这些记录,这样可以防止其他事务访问这些数据记录。具体细节要视数据库而定,不过糟糕的是,并非所有数据库都支持悲观锁。如果数据库支持悲观锁,在直接执行SQL 语句的应用程序中,实现悲观锁非常容易。在JDO 或Hibernate 应用程序中使用悲观锁更为容易。JDO 以配置选项的方式提供悲观锁,而Hibernate 则提供一个简单实用的API ,来锁定对象。
  获取锁的机制是数据库相关的,并非所有数据库都支持。在Oracle 数据库中,应用程序通过SELECT FOR UPDATE 语句锁住选出的记录,从而实现悲观锁。如果已经有事务锁住记录,执行SELECT FOR UPDATE 语句的事务就会被阻塞。如果其他事务更新、删除或者试图用SELECT FOR UPDATE 选取这些记录,阻塞情况就会发生。事务一直阻塞,直到事务提交或者回滚。如果事务不想等待,可以采用SELECT FOR UPDATE NO WAIT ,如果不能立即锁住记录,就返回ORA-00054 错误。你还可以用SELECT FOR UPDATE WAIT 来指定等待时间。要注意的是:一些数据库对SELECT FOR UPDATE 的用法有限制。例如,Oracle 里面,SELECT FOR UPDATE 只能用在顶层SQL ,而不能嵌在子查询里面。还有一些SQL 特性不能和SELECT FOR UPDATE 一起使用。这些特性包括DISTINCT ,集合统计函数(max 、min 、sum 、count ),GROUP BY 。SELECT FOR UPDATE 也不能用在某些类型的view 和嵌套的SELECT 里面。
  处理长事务中的并发
  乐观离线锁(Optimistic Offline Lock) 模式、悲观离线锁(Pessimistic Offline Lock ) 模式 
  乐观离线锁模式 是 扩展此前描述的乐观锁机制,在编辑过程的最后一个数据库事务里,检查数据自最初读取后并未改变。例如,你可以使用共享数据表里的版本号字段实现这一机制。 在编辑过程开始时,应用程序先将版本号存储在会话状态里。然后,当用户保存其更改时,应用程序进行检查,保证会话状态里保存的版本号和数据库中的版本号一致. 由于乐观离线锁模式只在用户要保存修改后的数据时才进行检测,在实现诸如"修改订单"用例时,要用户放弃好几分钟才完成的操作,用户肯定会非常恼火,此时更好的选择是使用悲观离线锁 .
  悲观离线锁模式 是在编辑过程开始之初,就锁定共享数据,以防止其他用户编辑该共享数据。这种方式与此前描述的悲观锁机制类似,只不过这里锁由应用程序而不是数据库实现。由于每次只有一个用户能编辑共享数据,因此可保证用户能保存自己的修改。
  通知并发更新失败 当DAO 或者数据库认为当前的两个事务不能并发运行时,就会发生并发失败。DAO 可以允许JDBC SQLException 传播到DAO 的调用者。不过,有两个原因说明这种做法不是一个好主意。抛出SQLException 的第一个问题是JDBC 相关。应用程序也可以使用JDO 这样的持久层,但是抛出其他的非JDBC 异常。理想情况下,更高层的应用程序组件不应该知道底层访问了数据库。 SQLException 的另一个问题是,SQLException 是一个checked exception (非Runtime Exception ,需要显式声明或者捕获的异常),需要DAO 调用者或者捕捉SQLException ,或者在方法签名上声明继续抛出 SQLException ,这种情况下,调用者代码会变得杂乱。使用unchecked exceptions (Runtime Exception ,不需要显式声明或者处理的异常)来报告并发失败要好得多。
分享到:
评论

相关推荐

    ibatis 开发指南

    相对Hibernate和Apache OJB 等“一站式”ORM解决方案而言,ibatis 是一种“半 自动化”的ORM实现。 所谓“半自动”,可能理解上有点生涩。纵观目前主流的ORM,无论Hibernate 还是 Apache OJB,都对数据库...

    metaworks4:Metaworks 4是一个进步的企业Web框架,可促进基于POJO的域驱动开发,支持微服务的体系结构以及材料设计和响应式Web。 Metaworks 4利用了VueJS,Spring Data和Spring Hateoas。 此外,Metaworks4可以与OCE的组件(如IAM,API-GW,计费)组成,以启用MSA架构

    Metaworks 4是一个进步的企业Web框架,可促进基于POJO的域驱动开发,支持微服务的体系结构以及材料设计和响应式Web。 Metaworks 4利用了VueJS,Spring Data和Spring Hateoas。 另外,Metaworks4可以与OCE的组件(如...

    iBATIS 2.0 开发指南

    相对Hibernate和Apache OJB 等“一站式”ORM解决方案而言,ibatis 是一种“半 自动化”的ORM实现。 所谓“半自动”,可能理解上有点生涩。纵观目前主流的ORM,无论Hibernate 还是 Apache OJB,都对数据库结构提供了...

    Spring常问的真实大厂面试题汇总(含答案)

    Spring 框架⽬标是简化Java企业级应⽤开发,并通过POJO为基础的编程模型促进良好的编程习惯。 Spring是⼀个轻量级的IoC和AOP容器框架。是为Java应⽤程序提供基础性服务的⼀套框架,⽬的是⽤于简化企业应⽤程序的开发...

    ibatis开发指南

    相对Hibernate和Apache OJB等“一站式”ORM解决方案而言,ibatis 是一种“半  自动化”的ORM实现。  所谓“半自动”,可能理解上有点生涩。纵观目前主流的 ORM,无论 Hibernate 还是  Apache OJB,都对数据库...

    iBatis开发资料

    相对Hibernate和Apache OJB 等“一站式”ORM解决方案而言,ibatis 是一种“半 自动化”的ORM实现。 所谓“半自动”,可能理解上有点生涩。纵观目前主流的ORM,无论Hibernate 还是 Apache OJB,都对数据库结构提供了...

    《MyEclipse 6 Java 开发中文教程》前10章

    10.5.2.4 用Spring 2.0 的aop和tx声明式配置解决事务提交问题 247 10.5.2.5 用Spring 2.0 的@Transactional标注解决事务提交问题(最佳方案) 251 10.5.2.6 使用 HibernateTemplate 实现分页查询 254 10.6 小结 255 ...

    Ibatis开发指南.rar

    Ibatis 开发指南 相对Hibernate和 Apache OBJ 等 "一站式" ORM 解决方案而言, ibatis 是一种 "半自动化的" ORM实现 所谓"半自动化" ,可能理解上有点生涩.纵观目前主流的ORM,无论Hibernate还是Apache OJB,都是对...

    Java代码生成工具(傻瓜式操作无需教程的代码生成工具) v2.0.zip

    生成hibernate pojo类,dao类,service类,action类。  生成保存,删除,修改,批量保存,批量修改,批量删除,按条件查询,分页查询等功能。  生成各大主流框架配置文件及jsp页面。  一键生成整个项目,加入...

    apache-camel-demo

    Apache Camel是一个基于规则路由和中介引擎,提供企业集成模式的Java对象(POJO)的实现,通过应用程序接口(或称为陈述式的Java领域特定语言(DSL))来配置路由和中介的规则。领域特定语言意味着Apache Camel支持你...

    SpringMVC大威天龙.docx

    SpringMVC是Spring提供的一个强大而灵活的Web框架 借助于注解 SpringMVC提供了几乎是POJO的开发模式 使得控制器的开发和测试更加简单 二 SpringMVC优点 1. 角色划分清晰 2. 分工明确 而且扩展相当灵活 3. 和Spring...

    ibatis 开发指南(pdf)

    43 <br>ibatis 开发指南 相对Hibernate 和Apache OJB 等“一站式”ORM 解决方案而言,ibatis 是一种“半 自动化”的ORM 实现。 所谓“半自动”,可能理解上有点生涩。纵观目前主流的ORM ,无论...

    Spring-Series:Spring&Spring Boot&Spring Cloud&Alibaba Cloud微服务与云原生实战

    使用Spring进行开发,对开发人员比较轻量,可以使用POJO和Java Bean的开发方式,使应用面向接口开发,充分支持面向对象的设计方法。非侵入性的方式增加了服务的功能,为灵活选择不同的服务实现提供了基础,这也是...

    毕业设计springboot+vue音乐网站项目

    前端使用: vue/cli “^...5.更深入体会的是MVVM架构开发模式,流水线式创建实体并实现业务逻辑: domain/pojo/bean → dao/mapper → mapper.xml → service → serviceimpl → controller 6.记得优先对前端进行数据校验.

    ibatis实现过程

    相对Hibernate和Apache OJB 等“一站式”ORM解决方案而言,ibatis 是一种“半 自动化”的ORM实现。 所谓“半自动”,可能理解上有点生涩。纵观目前主流的ORM,无论Hibernate 还是 Apache OJB,都对数据库结构提供了...

    springmvc demo

    即使用了MVC架构模式的思想,将web层进行职责解耦,基于请求驱动指的就是使用请求-响应模型,框架的目的就是帮助我们简化开发,Spring Web MVC也是要简化我们日常Web开发的。 Spring Web MVC也是服务到工作者模式的...

    Rio:Rio是一种开源技术,为开发,部署和管理由服务组成的分布式系统提供了动态架构。

    主要功能包括: 分布式系统的动态架构内置的故障检测和恢复服务基于策略的SLA实施支持外部系统,封装其他框架的控制和监视部署时对Maven工件解析的内置支持可扩展的服务开发和部署支持: POJO 春天基于Maven的工件...

    Lombok jar包|lombok-v1.18.4jar.zip

    Lombok 是一种 Java 实用工具,可用来帮助开发人员消除 Java 的冗长,尤其是对于简单的 Java 对象(POJO)。它通过注释实现这一目的。通过在开发环境中实现 Lombok,开发人员可以节省构建诸如 hashCode() 、equals()...

    SSH全注解demo

    全注解SSH框架Demo,适用于企业式j2EE开发框架。 已经完全搭建好环境,有一个简单小案例。如果需写自己项目,可以把POJO类及DAO等删除即可。

Global site tag (gtag.js) - Google Analytics