分类 Java 下的文章

CAP理论

CAP理论断言任何基于网络的数据共享系统,最多只能满足数据一致性、可用性、分区容忍性三要素中的两个要素。但是通过显式处理分区情形,系统设计师可以做到优化数据一致性和可用性,进而取得三者之间的平衡。
自打引入CAP理论的十几年里,设计师和研究者已经以它为理论基础探索了各式各样新颖的分布式系统,甚至到了滥用的程度。NoSQL运动也将CAP理论当作对抗传统关系型数据库的依据。
CAP理论主张任何基于网络的数据共享系统,都最多只能拥有以下三条中的两条:
•数据一致性(C),等同于所有节点访问同一份最新的数据副本;
•对数据更新具备高可用性(A);
•能容忍网络分区(P)。
CAP理论的表述很好地服务了它的目的,即开阔设计师的思路,在多样化的取舍方案下设计出多样化的系统。在过去的十几年里确实涌现了不计其数的新系统,也随之在数据一致性和可用性的相对关系上产生了相当多的争论。“三选二”的公式一直存在着误导性,它会过分简单化各性质之间的相互关系。现在我们有必要辨析其中的细节。实际上只有“在分区存在的前提下呈现完美的数据一致性和可用性”这种很少见的情况是CAP理论不允许出现的。
虽然设计师仍然需要在分区的前提下对数据一致性和可用性做取舍,但具体如何处理分区和恢复一致性,这里面有不计其数的变通方案和灵活度。当代CAP实践应将目标定为针对具体的应用,在合理范围内最大化数据一致性和可用性的“合力”。这样的思路延伸为如何规划分区期间的操作和分区之后的恢复,从而启发设计师加深对CAP的认识,突破过去由于CAP理论的表述而产生的思维局限。
为什么“三选二”公式有误导性
理解CAP理论的最简单方式是想象两个节点分处分区两侧。允许至少一个节点更新状态会导致数据不一致,即丧失了C性质。如果为了保证数据一致性,将分区一侧的节点设置为不可用,那么又丧失了A性质。除非两个节点可以互相通信,才能既保证C又保证A,这又会导致丧失P性质。一般来说跨区域的系统,设计师无法舍弃P性质,那么就只能在数据一致性和可用性上做一个艰难选择。不确切地说,NoSQL运动的主题其实是创造各种可用性优先、数据一致性其次的方案;而传统数据库坚守ACID特性(原子性、一致性、隔离性、持久性),做的是相反的事情。下文“ACID、BASE、CAP”小节详细说明了它们的差异。
事实上,CAP理论本身就是在类似的讨论中诞生的。早在1990年代中期,我和同事构建了一系列的基于集群的跨区域系统(实质上是早期的云计算),包括搜索引擎、缓存代理以及内容分发系统1。从收入目标以及合约规定来讲,系统可用性是首要目标,因而我们常规会使用缓存或者事后校核更新日志来优化系统的可用性。尽管这些策略提升了系统的可用性,但这是以牺牲系统数据一致性为代价的。
关于“数据一致性 VS 可用性”的第一回合争论,表现为ACID与BASE之争2。当时BASE还不怎么被人们接受,主要是大家看重ACID的优点而不愿意放弃。提出CAP理论,目的是证明有必要开拓更广阔的设计空间,因此才有了“三选二”公式。CAP理论最早在1998年秋季提出,1999年正式发表3,并在2000年登上Symposium on Principles of Distributed Computing大会的主题演讲4,最终确立了该理论的正确性。
“三选二”的观点在几个方面起了误导作用,详见下文“CAP之惑”小节的解释。首先,由于分区很少发生,那么在系统不存在分区的情况下没什么理由牺牲C或A。其次,C与A之间的取舍可以在同一系统内以非常细小的粒度反复发生,而每一次的决策可能因为具体的操作,乃至因为牵涉到特定的数据或用户而有所不同。最后,这三种性质都可以在程度上衡量,并不是非黑即白的有或无。可用性显然是在0%到100%之间连续变化的,一致性分很多级别,连分区也可以细分为不同含义,如系统内的不同部分对于是否存在分区可以有不一样的认知。
要探索这些细微的差别,就要突破传统的分区处理方式,而这是一项根本性的挑战。因为分区很少出现,CAP在大多数时候允许完美的C和A。但当分区存在或可感知其影响的情况下,就要预备一种策略去探知分区并显式处理其影响。这样的策略应分为三个步骤:探知分区发生,进入显式的分区模式以限制某些操作,启动恢复过程以恢复数据一致性并补偿分区期间发生的错误。
ACID、BASE、CAP
ACID和BASE代表了两种截然相反的设计哲学,分处一致性-可用性分布图谱的两极。ACID注重一致性,是数据库的传统设计思路。我和同事在1990年代晚期提出BASE,目的是抓住当时正逐渐成型的一些针对高可用性的设计思路,并且把不同性质之间的取舍和消长关系摆上台面。现代大规模跨区域分布的系统,包括云在内,同时运用了这两种思路。
这两个术语都好记有余而精确不足,出现较晚的BASE硬凑的感觉更明显,它是“Basically Available, Soft state, Eventually consistent(基本可用、软状态、最终一致性)”的首字母缩写。其中的软状态和最终一致性这两种技巧擅于对付存在分区的场合,并因此提高了可用性。
CAP与ACID的关系更复杂一些,也因此引起更多误解。其中一个原因是ACID的C和A字母所代表的概念不同于CAP的C和A。还有一个原因是选择可用性只部分地影响ACID约束。ACID四项特性分别为:
原子性(A)。所有的系统都受惠于原子性操作。当我们考虑可用性的时候,没有理由去改变分区两侧操作的原子性。而且满足ACID定义的、高抽象层次的原子操作,实际上会简化分区恢复。
一致性(C)。ACID的C指的是事务不能破坏任何数据库规则,如键的唯一性。与之相比,CAP的C仅指单一副本这个意义上的一致性,因此只是ACID一致性约束的一个严格的子集。ACID一致性不可能在分区过程中保持,因此分区恢复时需要重建ACID一致性。推而广之,分区期间也许不可能维持某些不变性约束,所以有必要仔细考虑哪些操作应该禁止,分区后又如何恢复这些不变性约束。
隔离性(I)。隔离是CAP理论的核心:如果系统要求ACID隔离性,那么它在分区期间最多可以在分区一侧维持操作。事务的可串行性(serializability)要求全局的通信,因此在分区的情况下不能成立。只要在分区恢复时进行补偿,在分区前后保持一个较弱的正确性定义是可行的。
持久性(D)。牺牲持久性没有意义,理由和原子性一样,虽然开发者有理由(持久性成本太高)选择BASE风格的软状态来避免实现持久性。这里有一个细节,分区恢复可能因为回退持久性操作,而无意中破坏某项不变性约束。但只要恢复时给定分区两侧的持久性操作历史记录,破坏不变性约束的操作还是可以被检测出来并修正的。通常来讲,让分区两侧的事务都满足ACID特性会使得后续的分区恢复变得更容易,并且为分区恢复时事务的补偿工作奠定了基本的条件。
CAP和延迟的联系
CAP理论的经典解释,是忽略网络延迟的,但在实际中延迟和分区紧密相关。CAP从理论变为现实的场景发生在操作的间歇,系统需要在这段时间内做出关于分区的一个重要决定:
•取消操作因而降低系统的可用性,还是
•继续操作,以冒险损失系统一致性为代价
依靠多次尝试通信的方法来达到一致性,比如Paxos算法或者两阶段事务提交,仅仅是推迟了决策的时间。系统终究要做一个决定;无限期地尝试下去,本身就是选择一致性牺牲可用性的表现。
因此以实际效果而言,分区相当于对通信的时限要求。系统如果不能在时限内达成数据一致性,就意味着发生了分区的情况,必须就当前操作在C和A之间做出选择。这就从延迟的角度抓住了设计的核心问题:分区两侧是否在无通信的情况下继续其操作?
从这个实用的观察角度出发可以导出若干重要的推论。第一,分区并不是全体节点的一致见解,因为有些节点检测到了分区,有些可能没有。第二,检测到分区的节点即进入分区模式——这是优化C和A的核心环节。
最后,这个观察角度还意味着设计师可以根据期望中的响应时间,有意识地设置时限;时限设得越短,系统进入分区模式越频繁,其中有些时候并不一定真的发生了分区的情况,可能只是网络变慢而已。
有时候在跨区域的系统,放弃强一致性来避免保持数据一致所带来的高延迟是非常有意义的。Yahoo的PNUTS系统因为以异步的方式维护远程副本而带来数据一致性的问题5。但好处是主副本就放在本地,减小操作的等待时间。这个策略在实际中很实用,因为一般来讲,用户数据大都会根据用户的(日常)地理位置做分区。最理想的状况是每一位用户都在他的数据主副本附近。
Facebook使用了相反的策略6:主副本被固定在一个地方,因此远程用户一般访问到的是离他较近,但可能已经过时的数据副本。不过当用户更新其页面的时候是直接对主副本进行更新,而且该用户的所有读操作也被短暂转向从主副本读取,尽管这样延迟会比较高。20秒后,该用户的流量被重新切换回离他较近的副本,此时副本应该已经同步好了刚才的更新。
CAP之惑
CAP理论经常在不同方面被人误解,对于可用性和一致性的作用范围的误解尤为严重,可能造成不希望看到的结果。如果用户根本获取不到服务,那么其实谈不上C和A之间做取舍,除非把一部分服务放在客户端上运行,即所谓的无连接操作或称离线模式7。离线模式正变得越来越重要。HTML5的一些特性,特别是客户端持久化存储特性,将会促进离线操作的发展。支持离线模式的系统通常会在C和A中选择A,那么就不得不在长时间处于分区状态后进行恢复。
“一致性的作用范围”其实反映了这样一种观念,即在一定的边界内状态是一致的,但超出了边界就无从谈起。比如在一个主分区内可以保证完备的一致性和可用性,而在分区外服务是不可用的。Paxos算法和原子性多播(atomic multicast)系统一般符合这样的场景8。像Google的一半做法是将主分区归属在单一个数据中心里面,然后交给Paxos算法去解决跨区域的问题,一方面保证全局协商一致(global consensus)如Chubby9,一方面实现高可用的持久性存储如Megastore10。
分区期间,独立且能自我保证一致性的节点子集合可以继续执行操作,只是无法保证全局范围的不变性约束不受破坏。数据分片(sharding)就是这样的例子,设计师预先将数据划分到不同的分区节点,分区期间单个数据分片多半可以继续操作。相反,如果被分区的是内在关系密切的状态,或者有某些全局性的不变性约束非保持不可,那么最好的情况是只有分区一侧可以进行操作,最坏情况是操作完全不能进行。
“三选二”的时候取CA而舍P是否合理?已经有研究者指出了其中的要害——怎样才算“舍P”含义并不明确11,12。设计师可以选择不要分区吗?哪怕原来选了CA,当分区出现的时候,你也只能回头重新在C和A之间再选一次。我们最好从概率的角度去理解:选择CA意味着我们假定,分区出现的可能性要比其他的系统性错误(如自然灾难、并发故障)低很多。
这种观点在实际中很有意义,因为某些故障组合可能导致同时丢掉C和A,所以说CAP三个性质都是一个度的问题。实践中,大部分团体认为(位于单一地点的)数据中心内部是没有分区的,因此在单一数据中心之内可以选择CA;CAP理论出现之前,系统都默认这样的设计思路,包括传统数据库在内。然而就算可能性不高,单一数据中心完全有可能出现分区的情况,一旦出现就会动摇以CA为取向的设计基础。最后,考虑到跨区域时出现的高延迟,在数据一致性上让步来换取更好性能的做法相对比较常见。
CAP还有一个方面很多人认识不清,那就是放弃一致性其实有隐藏负担,即需要明确了解系统中存在的不变性约束。满足一致性的系统有一种保持其不变性约束的自然倾向,即便设计师不清楚系统中所有的不变性约束,相当一部分合理的不变性约束会自动地维持下去。相反,当设计师选择可用性的时候,因为需要在分区结束后恢复被破坏的不变性约束,显然必须将各种不变性约束一一列举出来,可想而知这件工作很有挑战又很容易犯错。放弃一致性为什么难,其核心还是“并发更新问题”,跟多线程编程比顺序编程难的原因是一样的。

OSGI Spring Hibernate的优势

在网上看到这么一句话觉得总结的非常好:
从高内聚,低耦合到设计模式,从 Ioc 、 Spring 框架 到 SOA 我们一步一步的抽象着、分离着。很显然,我们需要一个灵活而不失严谨的架构,需要一个功能强进而不令人生畏的产品;
企业的应用软件发展还有着很大的空间和尺度,也大概明白为什么OSGI起源于1999年却近几年才进入软件行业,当时软件业确实还不发达,人们确实想不了这么多,做软件只为了能解决一些问题而做。而如今更多是要资源最大化共享,就想着怎么能把原来做过的软件集成起来,不用再做个新的,于是就有了SOA。随着Eclipse的成功,大家对它以OSGI为核心的插件体系无不赞叹,原来做软件可以像搭积木一样的拼装,多么美妙,人们也就认识到了OSGI的重要性和带来的好处,近两年OSGI正在飞速发展,相信以后会有更大的发展空间,网上有人预言说将来OSGI一定会装在60%的java虚拟机上,还有人说这么好的架构应该直接纳入JDK,这些都有点极端,但是可以看出它是多么的优秀。越来越多的软件开始支持OSGI。
OSGI的强项是它的动态加载和对Bundle之间的通信和管理及依赖关系,而更细粒度bundle内部则没有严格的管理体系,Spring可以对bundle内部进行更为细粒度的管理,Spring将在配置文件中增加直接支持OSGI的配置项。
他们的组合可以把底耦合的应用程序“模块化”。
运行期间多个版本的应用同时部署,动态选择,当然这是OSGI的特性,但是有Spring的配置将更好。
运行期间多模块(服务)的替换。
运行期间动态部署,更新或反部署模块。
应用Spring配置,装配模块。
用简单和熟悉的编程方式开发具有OSGI特征的程序。
Hibernate现在也可以集成到OSGI,为OSGI持久层又添了一笔,可以看出Spring+OSGI+hibernate前途无量。

OSGi的优缺点

对于OSGi,有人评论称OSGi是“Spring之后的下一个big thing”。不过该文的作者后来又觉得,OSGi也有不少的问题,其中之一就是它在把技术变得复杂化。作者是这样说的:
  我对OSGi不怀疑并承认OSGi解决了许多问题,而且它支持一些出众的结构模型比如高模块化(high modularization)以及微服务(micro services)。然而从另外一个角度来说,在使用了OSGi几年之后,也体验了它在不同领域的表现(我是指开发领域)之后,我真的开始怀疑OSGi了。
  这是我喜欢和讨厌的OSGi的一些方面:
  它从几百个具有代表性的小bundle中创建出一个系统的概念非常棒。OSGi bundle很好的一点是它们定义了边界:不仅从依赖关系的意义上,而且从运行时间的意义上也是这样。每个bundle可以充当一个微应用,有自己的lifecycle和用户,每个bundle能够仔细地断定出哪个对象对外暴露。好好地使用它们,会带给系统以松耦合,并增加再使用的可能性。而与此同时,OSGi的lifecycle使life更加复杂。实际上,追踪服务和管理服务所引发的各个问题很讨厌(我曾看到过在它们的bundle activators使用大型的state machines来管理所有事情,这种样板化代码没有人愿意写)。幸运的是有Spring DM来帮我们管理这些。坦白说,如果没有Spring DM我绝不会动手开始OSGi项目。尽管Spring DM大大降低了bundle启动的复杂度,但仍然很麻烦。我仍然需要启动OSGi的运行时间、安装启动bundles,我还需要确保所有其他我所需要的bundles已经安装和启动。
  我个人觉得,作为开发者,我们应当迫使自己执行系统的约束。我们不得不自动核对定义的限制,比如说,如果我们读取了一些我们并不想读取的类,构建程序就会失败。OSGi的版本概念,通过定义输入和输出包,将架构参数(architectural constraints)首次带入开发者的日常生活,并引入了一系列新的问题。OSGi是这样解决运行时间的版本问题的:它给每个bundle自己的class loader,并让class loader看起来像它所在的版本一样。这也带来一系列问题,因为它改变了你环境工作的方式。你的代码在所有你的单元测试中都可以通过,但一旦执行在OSGi的运行时间上,就会崩溃;Libraries崩溃因为这提升了运行时间中的类;Singletons被设计为静态对象不止一次地被创建,周而复始。当你在不断地调整你的模块构建说明时你会经常终止,而且绝对会在你的整个系统中传播反直观的依赖关系。Spring DM也是这个问题:通过在你的服务中添加一些指令并且不断地调整你的class loaders,你仍然需要调整和传送依赖关系。
  尤其是类的导入更是带来很麻烦的问题。你很快会注意到,没有强大和自动集成的测试组件来配合OSGi,你无法继续下去。
  现在说一下我的结论:
  在考虑OSGi之前,我会切实核实是否在不关闭系统的情况下我能否在运行时间中转换bundles,即使在这种情况下,我也会再次查看这些需求,来看看是否我会把他们限制在一个角落里,在这里我可以使用其他技术在动态时间上来动态地加载模块。还有其他选择可以生成这种结构条例(比如使用一个IOC container,使用独立的container来执行模块依赖等等……)许多这些东西都很接近KISS原则,避免所有其他附件的样板化代码并构建配置,这因此让你更加敏捷。
  回归到我的题目上,还有一种技术拥有这样的特点(我是指让技术更加复杂),那就是EJB。Spring是最流行的实例:技术更加复杂,开发周期更加困难。也许我们会在未来的几年内在OSGi中看到同样的境遇?我无法断定,时间将验证一切。

java的(PO,VO,TO,BO,DAO,POJO)解释

O/R Mapping 是 Object Relational Mapping(对象关系映射)的缩写。通俗点讲,就是将对象与关系数据库绑定,用对象来表示关系数据。在O/R Mapping的世界里,有两个基本的也是重要的东东需要了解,即VO,PO。
  VO,值对象(Value Object),PO,持久对象(Persisent Object),它们是由一组属性和属性的get和set方法组成。从结构上看,它们并没有什么不同的地方。但从其意义和本质上来看是完全不同的。
1.VO是用new关键字创建,由GC回收的。
  PO则是向数据库中添加新数据时创建,删除数据库中数据时削除的。并且它只能存活在一个数据库连接中,断开连接即被销毁。
2.VO是值对象,精确点讲它是业务对象,是存活在业务层的,是业务逻辑使用的,它存活的目的就是为数据提供一个生存的地方。
  PO则是有状态的,每个属性代表其当前的状态。它是物理数据的对象表示。使用它,可以使我们的程序与物理数据解耦,并且可以简化对象数据与物理数据之间的转换。
3.VO的属性是根据当前业务的不同而不同的,也就是说,它的每一个属性都一一对应当前业务逻辑所需要的数据的名称。
  PO的属性是跟数据库表的字段一一对应的。
PO对象需要实现序列化接口。
————————————————-
PO是持久化对象,它只是将物理数据实体的一种对象表示,为什么需要它?因为它可以简化我们对于物理实体的了解和耦合,简单地讲,可以简化对象的数据转换为物理数据的编程。VO是什么?它是值对象,准确地讲,它是业务对象,是生活在业务层的,是业务逻辑需要了解,需要使用的,再简单地讲,它是概念模型转换得到的。
首先说PO和VO吧,它们的关系应该是相互独立的,一个VO可以只是PO的部分,也可以是多个PO构成,同样也可以等同于一个PO(当然我是指他们的属性)。正因为这样,PO独立出来,数据持久层也就独立出来了,它不会受到任何业务的干涉。又正因为这样,业务逻辑层也独立开来,它不会受到数据持久层的影响,业务层关心的只是业务逻辑的处理,至于怎么存怎么读交给别人吧!不过,另外一点,如果我们没有使用数据持久层,或者说没有使用hibernate,那么PO和VO也可以是同一个东西,虽然这并不好。
—————————————————-
java的(PO,VO,TO,BO,DAO,POJO)解释
PO(persistant object) 持久对象
在o/r映射的时候出现的概念,如果没有o/r映射,没有这个概念存在了。通常对应数据模型(数据库),本身还有部分业务逻辑的处理。可以看成是与数据库中的表相映射的java对象。最简单的PO就是对应数据库中某个表中的一条记录,多个记录可以用PO的集合。PO中应该不包含任何对数据库的操作。
VO(value object) 值对象
通常用于业务层之间的数据传递,和PO一样也是仅仅包含数据而已。但应是抽象出的业务对象,可以和表对应,也可以不,这根据业务的需要.个人觉得同DTO(数据传输对象),在web上传递。
TO(Transfer Object),数据传输对象
在应用程序不同tie(关系)之间传输的对象
BO(business object) 业务对象
从业务模型的角度看,见UML元件领域模型中的领域对象。封装业务逻辑的java对象,通过调用DAO方法,结合PO,VO进行业务操作。
POJO(plain ordinary java object) 简单无规则java对象
纯的传统意义的java对象。就是说在一些Object/Relation Mapping工具中,能够做到维护数据库表记录的persisent object完全是一个符合Java Bean规范的纯Java对象,没有增加别的属性和方法。我的理解就是最基本的Java Bean,只有属性字段及setter和getter方法!。
DAO(data access object) 数据访问对象
是一个sun的一个标准j2ee设计模式,这个模式中有个接口就是DAO,它负持久层的操作。为业务层提供接口。此对象用于访问数据库。通常和PO结合使用,DAO中包含了各种数据库的操作方法。通过它的方法,结合PO对数据库进行相关的操作。夹在业务逻辑与数据库资源中间。配合VO, 提供数据库的CRUD操作…
O/R Mapper 对象/关系 映射
定义好所有的mapping之后,这个O/R Mapper可以帮我们做很多的工作。通过这些mappings,这个O/R Mapper可以生成所有的关于对象保存,删除,读取的SQL语句,我们不再需要写那么多行的DAL代码了。
实体Model(实体模式)
DAL(数据访问层)
IDAL(接口层)
DALFactory(类工厂)
BLL(业务逻辑层)
BOF Business Object Framework 业务对象框架
SOA Service Orient Architecture 面向服务的设计
EMF Eclipse Model Framework Eclipse建模框架
—————————————-
PO:全称是
persistant object持久对象
最形象的理解就是一个PO就是数据库中的一条记录。
好处是可以把一条记录作为一个对象处理,可以方便的转为其它对象。
BO:全称是
business object:业务对象
主要作用是把业务逻辑封装为一个对象。这个对象可以包括一个或多个其它的对象。
比如一个简历,有教育经历、工作经历、社会关系等等。
我们可以把教育经历对应一个PO,工作经历对应一个PO,社会关系对应一个PO。
建立一个对应简历的BO对象处理简历,每个BO包含这些PO。
这样处理业务逻辑时,我们就可以针对BO去处理。
VO :
value object值对象
ViewObject表现层对象
主要对应界面显示的数据对象。对于一个WEB页面,或者SWT、SWING的一个界面,用一个VO对象对应整个界面的值。
DTO :
Data Transfer Object数据传输对象
主要用于远程调用等需要大量传输对象的地方。
比如我们一张表有100个字段,那么对应的PO就有100个属性。
但是我们界面上只要显示10个字段,
客户端用WEB service来获取数据,没有必要把整个PO对象传递到客户端,
这时我们就可以用只有这10个属性的DTO来传递结果到客户端,这样也不会暴露服务端表结构.到达客户端以后,如果用这个对象来对应界面显示,那此时它的身份就转为VO
POJO :
plain ordinary java object 简单java对象
个人感觉POJO是最常见最多变的对象,是一个中间对象,也是我们最常打交道的对象。
一个POJO持久化以后就是PO
直接用它传递、传递过程中就是DTO
直接用来对应表示层就是VO
DAO:
data access object数据访问对象
这个大家最熟悉,和上面几个O区别最大,基本没有互相转化的可能性和必要.
主要用来封装对数据库的访问。通过它可以把POJO持久化为PO,用PO组装出来VO、DTO
—————————————————————–
PO:persistant object持久对象,可以看成是与数据库中的表相映射的java对象。最简单的PO就是对应数据库中某个表中的一条记录,多个记录可以用PO的集合。PO中应该不包含任何对数据库的操作.
VO:value object值对象。通常用于业务层之间的数据传递,和PO一样也是仅仅包含数据而已。但应是抽象出的业务对象,可以和表对应,也可以不,这根据业务的需要.个人觉得同DTO(数据传输对象),在web上传递.
DAO:data access object数据访问对象,此对象用于访问数据库。通常和PO结合使用,DAO中包含了各种数据库的操作方法。通过它的方法,结合PO对数据库进行相关的操作.
BO:business object业务对象,封装业务逻辑的java对象,通过调用DAO方法,结合PO,VO进行业务操作;
POJO:plain ordinary java object 简单无规则java对象,我个人觉得它和其他不是一个层面上的东西,VO和PO应该都属于它.
———————————————
VO:值对象、视图对象
PO:持久对象
QO:查询对象
DAO:数据访问对象
DTO:数据传输对象
—————————————-
struts 里的 ActionForm 就是个VO;
hibernate里的 实体bean就是个PO,也叫POJO;
hibernate里的Criteria 就相当于一个QO;
在使用hibernate的时候我们会定义一些查询的方法,这些方法写在接口里,可以有不同的实现类.而这个接口就可以说是个DAO.
个人认为QO和DTO差不多.
—————————————-
PO或叫BO,与数据库最接近的一层,是ORM中的O,基本上是数据库字段对应BO中的一个属性,为了同步与安全性考虑,最好只给DAO或者Service调用,而不要用packcode,backingBean,或者BO调。
DAO,数据访问层,把VO,backingBean中的对象可以放入。。。。
DTO,很少用,基本放入到DAO中,只是起到过渡的作用。
QO,是把一些与持久性查询操作与语句放入。。
VO,V层中用到的基本元素与方法等放其中。如果要其调用BO,则要做BO转换VO,VO转换BO操作。VO的好处是其页面的元素属性多于BO,可起到很好的作用。。。。
—————————————–
楼上的不对吧,PO是持久化对象。BO=business object—业务对象。
PO可以严格对应数据库表,一张表对映一个PO。
BO则是业务逻辑处理对象,我的理解是它装满了业务逻辑的处理,在业务逻辑复杂的应用中有用。
VO:value object值对象、view object视图对象
PO:持久对象
QO:查询对象
DAO:数据访问对象——同时还有DAO模式
DTO:数据传输对象——同时还有DTO模式

OSGi概念

OSGi(Open Service Gateway Initiative)技术是面向Java的动态模型系统。OSGi服务平台向Java提供服务,这些服务使Java成为软件集成和软件开发的首选环境。Java提供在多个平台支持产品的可移植性。OSGi技术提供允许应用程序使用精炼、可重用和可协作的组件构建的标准化原语。这些组件能够组装进一个应用和部署中。
OSGi亦称做Java语言的动态模块系统,它为模块化应用的开发定义了一个基础架构。OSGi容器已有多家开源实现,比如Knoflerfish、Equinox和Apache的Felix。您可以通过这些容器,把您的应用程序劈分为多个模块单元,这样,您就可以更容易地管理这些模块单元之间的交叉依赖关系。
OSGi规范和Servlet规范及EJB规范类似,该规范定义了两种对象,一是容器对外提供的服务对象,另一个是容器和您的应用程序之间必须遵守的契约,其中,服务对象是容器要实现的。您如果想要在OSGi平台上进行开发,首先,您必须要使用OSGi API来创建您的应用,然后将之部署到OSGi容器中。从开发者的角度看,OSGi具有以下优点:
a) 您可以在不重启容器的情况下,动态地安装、卸载、启动和停止您的应用程序中的不同模块;
b) 对于您应用程序中的某一特定模块,容器可以同时运行该模块的多个版本;
c) OSGi为开发嵌入式应用、移动应用、富互联网应用(RIA)提供了非常优秀的基础架构
如果说您使用Servlet容器开发您的网络应用,使用EJB容器开发交易式应用,您可能会问,为什么我们还需要另外的容器呢?对这个问题的简短回答是,OSIG容器是专门为开发复杂的Java应用准备的,在这些应用的开发过程中,您非常需要将这些应用分割为一个个的模块。在本系列以后的文章中,我将针对这个问题进行展开并深入回答。
1. OSGi在企业开发中的应用
OSGi联盟(OSGiAlliance)于1999年3月开始着手制定OSGi规范,其主要目的就是要制定一套开放式标准,以便向局域网及其中的设备提供可管理的服务;其基本思路是,一旦您在网络设备(如服务器和嵌入式设备)上使用了OSGi服务平台,您就可以在网络上的任何地方管理这些设备上运行的软件组件的生命周期,可以在后台对这些组件进行安装、升级或卸载,但不需要打断该设备的正常运行。
近年来,OSGi技术在嵌入式系统及网络设备市场得到广泛应用。现在,由于Eclipse的成功,OSGi在企业开发中逐渐成为切实可行的、较有价值的一种技术。
1.1. 业界对OSGi的支持逐渐上升
2003年,Eclipse开发团队开始想办法提高Eclipse工具集的模块化,以便让它成为更加动态的富客户端平台。Eclipse团队最终选中OSGi框架作为其组件的运行时模型,2004年6月发布的Eclipse3.0就是第一个基于OSGi平台的版本。现在几乎所有的企业应用服务器都支持OSGi,Spring也通过一个叫“OSGi服务平台上的Spring动态模型(亦称之为OSGiSpring)”的项目来支持OSGi。该项目提供OSGi基础架构,以便我们在Spring的企业开发中更容易使用OSGi。
2. 开放源码的OSGi容器
从企业开发者的角度看,OSGi容器的要求很低,您可以很容易地把它嵌入到企业应用中,比如我们在开发Web应用时,我们可以把这个Web应用分为多个模块,一个模块负责视图层,另一个模块负责DAO层,第三个模块负责数据访问层,如果我们使用OSGi容器来管理这些模块之间的交叉依赖,我们就可以在不用重启该Web应用的前提下,将DAO层从速度较慢的升级到速度较快的DAO。
只要您的应用和OSGi规范兼容,您的应用就应该可以运行在任何OSGi容器中,现在比较流行的开放源码的OSGi容器有以下三种:
a) Equinox容器是参照OSGi规范第4版实现的,它构成了Eclipse IDE的核心—模块化的Java运行时;它实现了OSGi规范4中规定的必须强制实现的功能,同时,它也实现了OSGi规范中大部分的可选功能;
b) Knoflerfish是OSGi规范第3版和第4版的开源实现,它实现了OSGi规范规定的必须实现的功能及部分可选功能;
c) Apache的Felix是Apache软件基金会实现的OSGi开源容器,至本文截稿时为止,该容器还没有和OSGi规范完全兼容。

MYSQL索引在查询中如何使用?

假如你有一个表,
SQL> CREATE TABLE test_tab (
2 id INT,
3 name VARCHAR(10),
4 age INT,
5 val VARCHAR(10)
6 );
你的业务,有一个查询,是
SELECT * FROM test_tab WHERE name = 一个外部输入的数据
刚开始,数据不多的时候,执行效果还不错。
随着数据量的增加,这个查询,执行起来,越来越慢了。
然后在 name 上面 建立了索引
CREATE INDEX idx_test4_name ON test_tab (name );
这样, 可以加快前面那个查询的速度。
但是,某天,你执行了下面这个SQL, 发现速度又慢了
SELECT * FROM test_tab WHERE age = 25
为啥呢? 因为 age 字段上面,没有索引
索引只在 name 上面有
换句话说, 也就是 WHERE 里面的条件, 会自动判断,有没有 可用的索引,如果有, 该不该用。
多列索引,就是一个索引,包含了2个字段。
例如:
CREATE INDEX idx_test_name_age ON test_tab (name, age);
那么
SELECT * FROM test_tab
WHERE
name LIKE ‘张%’
AND age = 25
这样的查询,将能够使用上面的索引。
多列索引,还有一个可用的情况就是, 某些情况下,可能查询,只访问索引就足够了, 不需要再访问表了。例如:
SELECT
AVG( avg ) AS 平均年龄
FROM
test_tab
WHERE
name LIKE ‘张%’
这个时候, name 与 age 都包含在索引里面。 查询不需要去检索表中的数据。

mysql语句大全

选择:
select * from user where user.id=1;
插入:
insert into user(user.id,user.name,user.pwd) values('3','testname','testpwd')
insert into booktest(booktest.id,booktest.name,booktest.price,booktest.userid) values(1,'好书名',15,null)
删除:
delete from user where id=3
更新:
update user set user.name='updatename' where user.id=2
Like语句:
select * from user where user.name like '%name%'
排序:
select * from user order by user.id desc
总数:
select count(*) from user
求和:
select sum(book.price) from book
平均:
select avg(book.price) from book
最大:
select max(book.price) from book
最小:
select min(book.price) from book
left join:
select * from user u left join book b on u.id=b.userid;
Group by:
select u.id,u.name,count(*) from user u left join book b on u.id=b.userid group by u.id;
IN:
select * from book where price in(25,10)
NOT IN:
select * from book where price not in(25,10)
子查询:
select * from user where user.id in(select book.userid from book)
Between:
select * from book where book.price between 5 and 30
时间函数:
select DAYOFWEEK('1998-02-03');
select WEEKDAY('1997-10-04 22:23:00');
创建表
CREATE TABLE booktest (
id INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
name VARCHAR(1024) NOT NULL,
price int(10) not null,
userid int(10)
)
TABLESPACE ts_1 STORAGE DISK
ENGINE NDBCLUSTER;