对CMP应正确看待,难道真的一无是处?

浏览完论坛上的帖子,感觉很多大侠对CMP的使用在观点上都存在偏颇,这对后来者和J2EE新手纯粹就是误导。在我看来,系统规模不大或中等的情况下,使用合适的IDE进行EJB2.0版的CMP开发,效率高,代码质量好,运行稳定,对速度的影响也没有象有些人描述的那样恐怖。我不清楚为什么大家都一窝蜂似的抛弃CMP而转投一些五花八门的持久性方案。

是为了使系统结构精益求精,还是为了显示技术实现与众不同?可能本人经验浅薄,能力和认知有限,直到现在也没碰到过Schema设计中有非常复杂的多对多、甚至只对某个字段的映射情况,我想如果有人碰到这种情况的话,多半是因为系统分析没做细致,数据库表结构也没经过优化到BNF3。我认为现在流行的AppServer中,各厂商对CMP的实现都还可以,在性能调优方面,在灵活性设置方面,我实在感觉不到那些JDO实现方案或Hibernate有什么明显的优势。

别人说的并不重要,重要的是自已两者都去试一下,对比对比,看哪一种更适合你。我个人感觉, 跟其它O/R Mapping 比, CMP还需要很多地方要完善, 但绝不是你说的一无是处。

另外,我也不得不承认很多人在使用CMP并没有考虑到CMP的粒度问题,毕竟CMP由于效率问题的限制,只支持粗粒度的Object,而Hibernate等,他们可以支持粗细两种。

所以大家使用CMP时,请一定正确使用粒度问题,在这一点上,还请Banq 赐教.我还没有开始研究petstore的代码, 垦请Banq具体说一下, 例如: 一张表与一个CMP对应 不好的话,应如何去重构呢?谢谢!

如果用AggregatEntity/DependentObject, 来解决以上问题,原理有点象VO, 进行抽象封装,但是如果我调aggregatEntity中的Setter方法, 它会调各个DependentObject中的Setter方法,我不太明白的是,各个DependentObject中的Setter方法如何实现,不会是BMP或是JDBC SQL吧?
如果不是,那是如何实现的呢?

我不太理解你提的DependedObject是不是就是说关联的CMP对象。反正按我的理解CMP中所有的Setter和Getter方法到最后都是基于JDBC实现的,但是并不是说每次调用都做一次数据库访问,AppServer会根据某种策略进行批量DB操作。

<<我不太理解你提的DependedObject是不是就是说关联的CMP对象

DependentObject不是关联的CMP对象。

我只是自已把自已问住了,如果DependentObject不用JDBC SQL实现,那如何利用EJB中O/R Mapping 的优势, 如果DependentObject不用JDBC SQL实现,那还要CMP做接口类于嘛?

上个贴子写的不对,现在改一下也UP一下。

如果DependentObject不用JDBC SQL实现,那如何利用EJB中O/R Mapping 的优势? 如果DependentObject用JDBC SQL实现,那还要Aggregate EntityBean做什么?

如何在CMP中实现一Bean对一表的重构?

如果说不使用Session Facade模式的话,我认为EB还是一个很有意义的的东西,因为EB是唯一直接支持跨RMI的持久化方案。但是由于EB的效率和减少跨RMI的网络调用的原因,EB已经完全被封装到SB的后面,EB的分布式调用的功能,EB的安全验证功能,EB的容器事务功能完全被前面的SB给做了,结果EB就只剩下了唯一的ORM功能了,单就ORM这一点来说EB实在是一个非常非常糟糕的东西。那么EB还有什么功能值得我非去用它不可呢?

用 Session Bean + DAO + Hibernate 来取代 Session Bean + Entity Bean,不但能够极大降低软件设计难度,软件开发难度,软件调试难度和软件部署难度,而且还可以提高允许效率,降低硬件要求。

不要把EB直接拿来和Hibernate做比较,两者不是一个范畴的东西,而应该整体比较两种方案:
Session Bean + DAO + Hibernate
Session Bean + Entity Bean
我找不出来第二方案有哪怕一点方面能够比第一方案好的。

呵呵,这篇文章以前看过,不过笔者只认同EJB中的 stateless-Session beans and messaging beans。

我提的问题在EJB实现中的确很难说清楚,不过我个人认为:Sun提出的aggregate entitybean模式仅仅是对BMP说的,如果用在CMP中,就自相矛盾了。

总的来说,CMP局限性太多,因此才有这么多J2EE Core Patterns 来解决很多EJB中的性能问题。CMR也不好,越多的CMP,越差的性能,而且CMP还不能脱离数据库中表的外键使用。

to bruce

" 一张表与一个CMP对应 不好的话,应如何去重构呢?"
使用CMR很方便的前提条件是对数据表设计有限制的。
如果使用CMR,那么就将两个表的对应关系单独设计成一张表,如:


CREATE TABLE customer (
id varchar(50) NOT NULL default '',
firstName varchar(50) default '',
lastName varchar(50) default '',
UNIQUE KEY customerID (id)
) TYPE=InnoDB;
# --------------

CREATE TABLE address (
addressID varchar(50) NOT NULL default '0',
street varchar(50) default '',
city varchar(50) default '',
zip varchar(50) default '',
state varchar(50) default '',
customerID varchar(50) default '',
PRIMARY KEY (addressID),
KEY customerID (customerID)
) TYPE=InnoDB;

这两种表是一对多关系,这将两个表一对多关系设计在address一个表中,这是过去我们统计喜欢作的,但是使用CMR时,最后单独设计一张表,如下:


CREATE TABLE customer (
id varchar(50) NOT NULL default '',
addressID varchar(50) NOT NULL default '0',
KEY addrssID (addressID),
UNIQUE KEY customerID (id)
) TYPE=InnoDB;


这样做有两个好处:
1.符合CMP的CMR内部实现机制,性能好;
2.方便关系重整。

关于CMP性能,我还要补充两句,
为什么“J2EE Core Patterns 来解决很多EJB中的性能”?

因为EJB是个框架组件技术,这种技术在以前一般人没有碰到过,把它当做API使用,API没有框架那样对应用继承介入那么深入。

要想用好EJB,必须了解EJB机制,使自己的应用系统符合EJB本身的节拍,可以说是符合客观规律吧,不再象以前编程那样,由程序员天马行空,想怎么做就怎么做,使用EJB就必须使用这些模式,按照这个框架做,否则违反规律必导致性能降低。

这些都是出于保证项目质量、实现重用性角度考虑的,所以喜欢自由,有个性的程序员是不喜欢EJB的。

但是在大规模生产中,我们更需要的是规则和稳定易懂的程序代码。这已经谈开去了。

总之,EJB不是API,是框架,用框架就是要有限制,这种限制是靠设计模式来实现的。这样J2EE项目的架构设计就非常重要,这些都是架构设计的内容。

再贴一次我个人对Hibernate的定位和认识:

Hibernate是JDBC和实体Bean之间的一个选择,虽然它在开发上与图形化CMP开发相比,节省了一些setXXX字段的编程工作量,但是Hibernate和CMP还是不同重要级别的技术。

Hibernate是替代Jdbc或连接池直接操作的技术,现在还有人津津乐道在研究JDBC 3.0的,象JDBC这样低层的技术除了Hibernate这样的产品研究者比较关注以外,对于一般应用者已经没有价值,这在研究方向上就发生了问题,在J2ee领域,后人总是不断站在前人的框架或层结构基础上的,就象使用Html已经没有必要知道Windows的图形API一样,J2EE领域现在关心的是如何软件如何最大重用,如何划分更细腻的层次,Hibernate无疑是持久层一项好的技术。

Struts+Hibernate确实很诱人,Struts将难以对象化的表现层实现了对象封装,其中ActionForm实际是VO变种,而持久层Hibernate输入输出参数都是VO,这样原来两个
很难实现对象化的层次被对象化了,确实是一个令人激动的事情,以后再有J2EE初学者,就要告诉它们,你们可以不学JDBC这些低层的技术了,直接从Hibernate和Struts
开始学吧,他们会觉得J2EE不再那么难了,可惜我们这些入道早点的“前辈”就要不断煎受取舍的痛苦了。

当然,Struts_Hibernate架构中,没有提供层次来防止很重要的业务逻辑层,因为这一般是由EJB的Sesssion Bean来完成,当然,也可以由
Web层的javaBeans来实现,如同OFbiz, Jive那样做一样,但是对象池等缓冲性能优化、事务锁机制、集群分布式技术都要自己实现,这些当然没有
由EJB容器实现的Session Bean来得干净,而CMP虽然不是一种O/R技术,但是作为由容器实现的技术和Session Bean的标准结合,因此我愿意采取
以下这样的技术:



Struts+ EJB Session Bean ---> CMP或BMP (重要数据、在有一对多关系或多对一关系时首选)
|--> Hibernate (替代以前的DAO技术中JDBC SQL直接读操作,当然性能要求更高,直接采取JDBC)

谢谢Banq的回复,

把一对多,多对多的关系用一个关联表来处理的确是个好办法,不过我还是要仔细想想。

<<这样做有两个好处:
<<1.符合CMP的CMR内部实现机制,性能好;
<<2.方便关系重整。


1。我想不仅关联表对CMR有性能上的改善,而且对一些数据库里join 有很多外键的表的时候,性能也会提高。

2。关联表使持久层对所有的表和各种关系都同样对待,简化开发与重构。

由此我们可以探讨一下引入关联表的优势.