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

PO and POJO

阅读更多

原文:http://danni505.blog.51cto.com/15547/99441

 

POJO = pure old java object or plain ordinary java object or what ever.

PO = persisent object 持久对象

就是说在一些Object/Relation Mapping工具中,能够做到维护数据库表记录的persisent object完全是一个符合Java Bean规范的纯Java对象,没有增加别的属性和方法。全都是这样子的:


[code:1]public class User {
private long id;
private String name;
public void setId(long id) {
this.id = id;
}
public void setName(String name) {
this.name=name;
}
public long getId() {
return id;
}
public String getName() {
return name;
}
} [/code:1]

---------------------------------------------------------------------------
首先要区别持久对象和POJO

持久对象实际上必须对应数据库中的entity,所以和POJO 有所区别。比如说POJO 是由new创建,由GC回收。但是持久对象是insert数据库创建,由数据库delete删除的。基本上持久对象生命周期和数据库密切相关。另外持久对象往往只能存在一个数据库Connection之中,Connnection关闭以后,持久对象就不存在了,而POJO 只要不被GC回收,总是存在的。

由于存在诸多差别,因此持久对象PO(Persistent Object)在代码上肯定和POJO 不同,起码PO相对于POJO 会增加一些用来管理数据库entity状态的属性和方法。而ORM追求的目标就是要PO在使用上尽量和POJO 一致,对于程序员来说,他们可以把PO当做POJO 来用,而感觉不到PO的存在。

JDO的实现方法是这样的:
1、编写POJO
2、编译POJO
3、使用JDO的一个专门工具,叫做Enhancer,一般是一个命令行程序,手工运行,或者在ant脚本里面运行,对POJO 的class文件处理一下,把POJO 替换成同名的PO。
4、在运行期运行的实际上是PO,而不是POJO

该方法有点类似于JSP,JSP也是在编译期被转换成Servlet来运行的,在运行期实际上运行的是Servlet,而不是JSP。

Hibernate的实现方法比较先进:
1、编写POJO
2、编译POJO
3、直接运行,在运行期,由Hibernate的CGLIB动态把POJO 转换为PO。

由此可以看出Hibernate是在运行期把POJO 的字节码转换为PO的,而JDO是在编译期转换的。一般认为JDO的方式效率会稍高,毕竟是编译期转换嘛。但是Hibernate的作者Gavin King说CGLIB的效率非常之高,运行期的PO的字节码生成速度非常之快,效率损失几乎可以忽略不计。

实际上运行期生成PO的好处非常大,这样对于程序员来说,是无法接触到PO的,PO对他们来说完全透明。可以更加自由的以POJO 的概念操纵PO。另外由于是运行期生成PO,所以可以支持增量编译,增量调试。而JDO则无法做到这一点。实际上已经有很多人在抱怨JDO的编译期Enhancer问题了,而据说JBossDO将采用运行期生成PO字节码,而不采用编译期生成PO字节码。

另外一个相关的问题是,不同的JDO产品的Enhancer生成的PO字节码可能会有所不同,可能会影响在JDO产品之间的可移植性,这一点有点类似EJB的可移植性难题。

-----------------------------------------------------------------------------------
由这个问题另外引出一个JDO的缺陷。

由于JDO的PO状态管理方式,所以当你在程序里面get/set的时候,实际上不是从PO的实例中取values,而是从JDO StateManager中取出来,所以一旦PM关闭,PO就不能进行存取了。

在JDO中,也可以通过一些办法使得PO可以在PM外面使用,比如说定义PO是transient的,但是该PO在PM关闭后就没有PO identity了。无法进行跨PM的状态管理。

而Hibernate是从PO实例中取values的,所以即使Session关闭,也一样可以get/set,可以进行跨Session的状态管理。

在分多层的应用中,由于持久层和业务层和web层都是分开的,此时Hibernate的PO完全可以当做一个POJO 来用,也就是当做一个VO,在各层间自由传递,而不用去管Session是开还是关。如果你把这个POJO 序列化的话,甚至可以用在分布式环境中。(不适合lazy loading的情况)

但 是JDO的PO在PM关闭后就不能再用了,所以必须在PM关闭前把PO拷贝一份VO,把VO传递给业务层和web层使用。在非分布式环境中,也可以使用 ThreadLocal模式确保PM始终是打开状态,来避免每次必须进行PO到VO的拷贝操作。但是不管怎么说,这总是权宜之计,不如Hibernate 的功能强。

分享到:
评论

相关推荐

    IDEA自动生成代码,包括PO层、DAO、SERVICE、SWAGGER注释类

    进入"File > Settings > Editor > File and Code Templates",在"Classes"模板中添加所需字段和方法。 3. **Lombok插件**:Lombok是一个流行的库,能够帮助消除POJO类中的冗余代码。安装Lombok插件后,只需在类上...

    Struts、Spring、Hibernate&Ajax;学习笔记总结

    - **POJO 转 PO**:持久化过程中,POJO 通常会被转换为 PO,以便于与数据库交互。 - **POJO 转 DTO**:当需要跨层传输数据时,POJO 可能会被转换为 DTO。 - **POJO 转 VO**:当数据需要展示给用户时,POJO 会被转换...

    使用@IdClass创建联合主键,并实现外部关联

    // getter and setter } ``` 接下来,我们需要创建Build实体类。在Build实体类中,我们使用@IdClass注解来标注联合主键。联合主键由buildID和centerID两个字段组成。 首先,我们需要创建一个BuildUnionPkId类,...

    Mybatis输入输出映射及动态SQL Review

    <select id="findUserById" parameterType="int" resultType="com.mybatis.po.User"> select * from user where id=#{id} ``` 其中,`#{id}`是一个占位符,MyBatis会自动替换为实际传入的值。 2. **输入POJO...

    Blog:充当日常笔记或者个人博客吧

    Nginx配置文件详解Linux 安装JenkinsJAVA 多线程详解java 多线程学习How to create a Hello World with IntelliJ and Aspect JJava各种对象(PO,BO,VO,DTO,POJO,DAO,Entity,JavaBean,JavaBeans)的区分Java finally...

    Hibernate_DEV_GUIDE.pdf

    - **PO (Persistent Object)**: 持久化对象是数据库表对应的对象。 - **VO (Value Object)**: 值对象通常用于传输数据,不含业务逻辑。 5. **其他高级特性**: - **Inverse and Cascade**: 控制关联对象的生命...

    Mybatis新手教程之简单入门

    // getter and setter methods @Override public String toString() { return "User{" + "id=" + id + ", username='" + username + '\'' + ", password='" + password + '\'' + ", address='" + address + ...

    整理后java开发全套达内学习笔记(含练习)

    abstract (关键字) 抽象 ['æbstrækt] access vt.访问,存取 ['ækses]'(n.入口,使用权) algorithm n....Annotation [java] 代码注释 [ænәu'teiʃәn] anonymous adj.匿名的[ә'nɒnimәs]'(反义:directly adv....

Global site tag (gtag.js) - Google Analytics