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 ,不需要显式声明或者处理的异常)来报告并发失败要好得多。
http://blog.csdn.net/gaoqian19820731/article/details/6256544
相关推荐
在使用Feign客户端发送GET请求时,如果需要传递复杂的查询条件或分页参数,开发人员往往会倾向于使用Java POJO(Plain Old Java Object)对象作为方法参数。例如: ```java @FeignClient("microservice-provider-...
在Java开发中,数据访问对象(DAO)模式是一种常见的设计模式,用于封装对数据库的操作,使得业务逻辑与数据访问逻辑分离。JDBC(Java Database Connectivity)是Java平台中用于访问数据库的标准API,但它直接使用...
Spring框架的依赖注入设计模式让开发者能够轻松地管理对象之间的依赖关系,而EJB 3.0的Java注解则简化了EJB的声明式编程模型,使得容器可以自动处理事务、安全性和持久化等复杂任务。 总之,“POJO Application ...
Java 快速开发平台 J-Hi 是一款 JAVA WEB 应用软件快速开发开源平台,主要服务于软件企业和传统行业企事业单位信息中心的开发人员,为他们提供一套完整的一站式的 JAVA WEB 应用软件快速开发解决方案。该平台包括...
它能将JSON字符串自动转化为符合Java POJO(Plain Old Java Object)规范的类,而且特别的是,它会将JSON中的下划线命名方式自动转换为Java中的驼峰式命名。 首先,让我们理解一下JSON和Java POJO之间的转换原理。...
- **POJO类中的布尔型变量**:避免在POJO类中布尔类型的变量名前加上`is`,以防止序列化问题。例如,使用`boolean deleted`而非`Boolean isDeleted`。 - **包名与类名规范**:包名一律使用小写,并且每个包名段仅...
- **响应式设计**: 自动适应不同设备和屏幕尺寸,确保优秀的用户体验。 **应用场景** Vaadin适用于需要开发高质量、高度定制化的Web应用程序的企业。 **挑战** - **学习成本**: 对于初学者来说,Vaadin的学习成本...
在具体命名风格上,类名采用UpperCamelCase(大驼峰式命名),而方法名、参数名等使用lowerCamelCase(小驼峰式命名),有助于提高代码的阅读性和易懂性。常量则全部使用大写字母,单词之间用下划线分隔。 在OOP...
JSP是Java平台上的一个重要技术,用于创建动态网页,它结合了Java编程语言的强大力量和HTML的易用性,使得开发人员可以方便地构建交互式、数据驱动的Web应用。 **JSP核心概念** 1. **JSP页面结构**:JSP页面由静态...
综上所述,EJB3.0在很大程度上解决了EJB2.1中存在的问题,通过引入POJO模型、IOC模式、O/R Mapping技术、元数据批注等先进技术,极大提升了开发效率和系统的可维护性。这些改变使得EJB3.0成为了Java企业级开发的重要...
**强制规定**:类名采用`UpperCamelCase`风格,即驼峰式大写,但某些特殊情况下除外,例如领域模型中的DO(Data Object)、BO(Business Object)、DTO(Data Transfer Object)、VO(View Object)等。 **正例**:...
相对Hibernate和Apache OJB 等“一站式”ORM解决方案而言,ibatis 是一种“半 自动化”的ORM实现。 所谓“半自动”,可能理解上有点生涩。纵观目前主流的ORM,无论Hibernate 还是 Apache OJB,都对数据库...
- 对于高级的J2EE开发者来说,如果他们倾向于使用EJB会话Bean、POJO类、O/R映射等技术,则可能会发现本书提供的开发方式不是最理想的。对于这类开发者,Oracle提供了另一种基于ADF的开发指南,该指南更加侧重于如何...
- **POJO命名**:通常由Hibernate自动生成,符合实体对象命名规则。 - **DAO类命名**:同样由Hibernate自动生成,但需确保遵循数据库操作接口的命名习惯。 ### 注释规范 良好的注释可以极大提升代码的可读性。主要...
9. **前端框架**:如Bootstrap、Angular、Vue.js等,可以快速构建响应式、移动优先的Web界面,提高开发效率。 10. **安全机制**:包括身份验证(Authentication)和授权(Authorization),防止未授权访问。Spring ...
Spring的核心特性包括了依赖注入(DI)、面向切面编程(AOP)以及基于POJO的轻量级和最小侵入式编程模型。 2. **企业级应用**:通常指的是需要处理大量数据和业务逻辑,同时要求高可用性、安全性和可伸缩性的应用...
- 支持**POJO**(Plain Old Java Object,普通的Java对象)风格的开发,使得代码更加简洁明了。 - 规范化的API设计确保了不同JPA实现之间的高度兼容性。 #### 2. MyEclipse支持下的JPA开发 - **MyEclipse**是一...
此外,类名使用UpperCamelCase(驼峰式命名),而方法名、参数名、成员变量和局部变量则使用lowerCamelCase(小驼峰命名)。常量命名需要全部大写,并用下划线隔开。 在类命名的细节上,手册提出了类名命名需避免...
在MVC模式下,模型通常由JavaBeans(也称为POJO,Plain Old Java Object)实现,它们封装了业务逻辑和数据。在Eclipse中,可以创建Java类来实现这些功能,并通过JSP页面上的EL(Expression Language)或JSTL(Java...