- 浏览: 76370 次
- 性别:
- 来自: 广州
最新评论
-
wayilau:
第24条,是不是有问题呀。。。
教你认人 -
xiaoBaoProgramme:
很好的一篇文章,顶。
html页面嵌套html页面 -
JUnique:
...
SSH -
yihuijie2011:
...
SSH -
linpark:
没事来看看~
SSH
精通EJB第二版 笔记
第一章:
构建一个大型的商务系统时需要考虑的因素
远程方法调用
平衡负载
透明故障恢复
后台集成
事务
群集
动态重部署
无损关机
登录和检查
系统管理
线程化
面向消息的中间件
对象生命周期
资源共享
安全
高速缓(冲)存
可重用中间件
EJB简介
是一个关于用JAVA语言开发的可部署的服务器端组件的组件体系结构。
三大优点:
业界认可的
移植容易实现
快速应用系统开发
EJB实际上分两部分:
规范
一组java接口
如果你不想跟随EJB技术,那么你还有其它的两种选择:
微软.NET平台可控组件
对象管理组织的(OMG’s)公共对象请求代理结构(CORBA)
作为一种商务解决方案的EJB
ejb是专门用来解决商务问题的,EJB组件(企业Beans),可执行如下任务:
执行商务逻辑
访问数据库
访问其它系统
胖客户(GUI有关,java中包括小应用程序(applet)和应用程序(application))
动态生成的WEB页
基于XML的web服务封装器
javabean是不可部署的,而EJB是可部署的.
第二章:EJB基础
EJB技术基于其它两项技术:Java RMI-IIOP和JNDI
附录A有相关知识
Java RMI-IIOP(Java Remote Method Invocation over the Internet Inter_ORB Protocol)与RMI
在java中,RMI-IIOP不是执行远程方法调用的唯一方法,你还可用RMI(JAVA远程方法调用).RMI是java中执行远程方法调用的最初方式,RMI使用java.rmi包.而RMI-IIOP是同CORBA兼容的RMI的特殊版本,RMI-IIOP同时使用java.rmi和javax.rmi.但EJB和J2EE强迫使用RMI-IIOP。
远程方法调用:
RPC
远程调用引发的一些问题:
编组和解组
参数传递协定(值传递,引用传递)
网络机器的不稳定性
远程接口:
接口
实现
使用RMI-IIOP时,必须建立称为远程接口定制接口,扩展java.rmi.Remote接口。
远程对象实现
扩展javax.rim.PortableRemoteObject。PortableRemoteObject是可以派生远程对象的基类。当远程对象被构造时,它自动调用PortableRemoteObject的构造函数。
或不扩展javax.rim.PortableRemoteObject。从另外的定制类中继承实现。
主键生成算法的问题
线程问题
JVM崩溃时
根程序和程序框架
在RMI-IIOP中网络实现的体系结构。
RMI需要以一种方式模拟一个本地对象,这个本对象称为根程序(Stub),它负责接收方法的本地调用,并将这些方法的调用委派给他们实际对象的执行代码,而这些代码有可能位于网络另一端,这就使得每个远程调用看起来像是本地调用。
根程序对于客户是本地的,程序框架对于远程对象是本地的。程序框架负责接收通过网络发来的调用(可能来自一个根程序),并将这些调用分配给远程对象的执行代码。
对象序列化和参数传递:
根程序和程序框架的功能是处理参数。
值传递:
用RMI请求一个方法时,传给远程对象的所有参数都是通过值传递的。意味着,将所有参数从一个机器复制到另一个机器。
通过值传递参数有一个问题,如果试图将一个对象通过网络传递,并且该对象引用了其它对象,在目标机器上怎样分清这些引用呢?一个机器的内存地址不会与另一个机器相同的内存地址相映射。同样目标机器中可能不会正好存在这个被引用的对象,我们怎么处理这种情况?java为了处理这个问题引入了对象序列化的概念来处理这个问题。
序列化是将一个Java对象转化为一个描述该对象的位块(bit-blob)。对象一旦变为bit-blob形式,就可以发送到任何地方的硬盘或网络上。准备再使用该对象时,必须将bit-blob解序列化成一个java对象。
实现java.lang.Serializable接口,这只是一个标识接口。当没有定义特定的序列化和解序列化方法,就会采用默认的序列化机制。
序列化规则
任何简单的基本类型(int,char等)自动地被序列化了的,并且在解序列化时是有效的。
JAVA对象可以选择被包含在序列化BIT-BLOB中,也可选择不包含在内。
用暂态关键字标注的对象不能序列化,并且在解序列化时无效。
怎样标识暂态transient
标识为暂态的理由:
对象非常大
对象代表了一个不能在目标机器上重新构建的资源。
对像代表了不想用序列化流传的敏感信息
对象序列化和RMI-IIOP
java RMI-IIOP依赖于通过远程方法调用传递参数的对象序列化
命名和目录服务器
一个命名服务器可心执行以下这些功能:
它把名称和对象关联起来(命名绑定到对象上)
提供一个根据命名查找对象的工具(查寻对象)
目录服务器是一个扩展和提高了的命名服务器,它为使用属性提供了目录对象的操作。一个目录是所有目录对象结合起来的一个系统。
LDAP
JNDI是命名和目录系统相互作用的一个基于JAVA的客户系统,它是命名和目录服务器上的一座桥梁,命脉名和目录服务器给不同的目录提供了一个共同的接口。
JNDI的优点:
能够仅仅通过学习单一的API来访问所有类型的目录服务器信息。
JNDI把应用程序从协议和实现的详细资料中隔离开来
使用JNDI可以从目录里读写全部JAVA对象
可以连接不同类型的目录
在J2EE中JNDI被用于多种目的:
使用JNDI获取对Java Transaction API(JTA) UserTransation接口引用。
使用JNDI连接资源工厂,如JDBC驱动程序,激活JAVA消息服务驱动程序
使用JNDI查询其它Bean
JNDI的结构体系:
两部分组成:客户端API和服务技术接口(SPI)。客户端API允许JAVA代码执行目录操作,对于所有类型的目录,它都是一样的。JNDI SPI 是一个命名和目录服务器供应商插入插件的接口,它正好和API相反,API允许用户一个单一完整的接口代码,而SPI允许命名和目录服务器提供商在系统里安装他们自已专有的协议。
JNDI结构体系类似于JDBC:
JDBC API JDBC驱动
JNDI API JNDI SPI
现在很多JNDI服务器提供商,包括LDAP,NIS,Novel NDS,SLP,CORBA,文件系统,RMI-IIOP。
J2ee服务器包含了JNDI实现。通常由J2EE服务器供应商提供定制实现。JNDI成为同RMI-IIOP,JMS结合在一起的由服务器提供的另一服务。
JNDI概念:
原字命名是一个简单的,基础的,不可分割的命名。
复合命名是由0个或多个原子命名组合在一起的。
绑定是一个名称到一个对象的关联。
命名系统,命名空间和合成命名
一个命名系统是一组相互连接的上下文。
在一个命名系统中,命名空间包含命名系统里所有的名称。
合成命名(composite name)是跨越多重命名系统的命名。
初始上下文生成库
命名空间字符串的起点被称为初始上下文,我们使用一个初始上下文生成库获取初始上下文,初始上下文生成库的任务是生成初始上下文。初始上下文生成库是由特定的JNDI服务技术提供的。
JNDI编程
Java.naming.factory.initial标识的是JNDI驱动程序类。
RMI-IIOP和JNDI的集成
有两种基本的应用方式:
使用JNDI API,RMI-IIOP服务器首先将自身发布到JNDI树。
客户使用JNDI来查询RMI-IIOP服务器
JNDI树通常与J2EE服务器运行在一起。当启动J2EE服务器时,JNDI树在进程内运行到J2EE服务器,同时启动。J2EE服务器也包含能够连接到此JNDI树实现的JNDI驱动程序。
2.1实体Bean
类型:
会话Bean
实体Bean
消息驱动Bean
分布式对象
EJB组件是基于分布式对象的,一个分布式对象是一个可以从远程系统调用的对象,它可以由一个进程中的用户来调用,也可由一个进程之外的用户来调用,或网络上的用户来调用。
客户端 — Stub (存根程序)— 网络 — Skelelon(框架程序)— 分布式对象
(家里部分)
实例调度的概念
应用程序服务器能够智能管理多种部署组件所需的资源,这些资源包括线程,套接字连接,数据库连接等。EJB规范中,容器的责任是在幕后提供全部的资源管理任务。除了资源管理以外,EJB容器还负责控制已部署的Bean组件的生存期。有一种叫实例池调度的调度方式,其好处是Bean池要比实际连接它的客户数目少得多。
Java RMI-IIOP and EJB对象
Javax.ejb.EJBObject扩展自java.rmi.Remote。java.rmi.Remote接口是基于IIOP的Java远程方法调用的一部分(RMI-IIOP)。任何实现java.rmi.Remote的对象都是远程对象。由于EJB容器提供的EJB对象实现远程接口,它也间接实现了java.rmi.Remote接口,这意味着,EJB对象是有网络功能的RMI-IIOP对象,可被其它JAVA虚拟机或者位于网络其它地方的机器调用。EJB远程接口实际上是RMI-IIOP远程接口。被调用的远程对象的方法都必须抛出java.rmi.RemoteException异常。远程接口必须遵守RMI-IIOP参数传递约定,必须是RMI-IIOP规定的有效类型,包括基本类型,可序列化对象,JAVA RMI远程对象。
2.4.3 Home 对象
客户端是调用EJB对象,而不是直接调用Bean。那么客户端是如何获得对EJB对象的引用呢?客户端从EJB对象“生成库”要求得到一个EJB对象,这个“生成库”负责对EJB对象的实例化和回收,这个生成库就是Home对象。
Home对象职责:
生成EJB对象
杳找现存的EJB对象(仅限于实体Bean)
删除EJB对象
Home接口必须扩展javax.ejb.EJBHome。javax.ejb.EJBHome也是扩展自java.rmi.Remote。
Home对象,EJB对象,Bean实例的关系:
有几个Home对象和每个Bean对应呢?问题的答案是和供应商有关,大多数容器中,HOME对象和每个BEAN实例关系常是1:N。编写Home对象时,它应是线程安全的,这样它才能响应多个并发的客户端请求。
每个Bean实例对应多少个EJB对象实例?当EJB对象是多线程的时,有些容器采用1:N关系。当EJB对象是单线程时,有些可能采用M:N的关系,M代表初始化的EJB对象数目,N代表调度池中Bean实例数目。
这些对于一个Bean供应商来说,都不要紧,因为容器对你来说,是透明的。
2.4.4本地接口
home接口一个不好之处是通过接口生成Bean是很慢的,对于通过远程接口调用Bean也是同样。因为当你远程调用一个EJB对象时,有以下步骤:
客户端调用一个本地STUB
Stub将参数整理成一种适合网络传输的形式
Stub通过网络Skeleton连接
Skeleton调用EJB对象
EJB对象完成所需的中间件服务(如连接缓冲,事务处理,安全检查,生命周期服务)
一旦EJB对象调用了企业Bean实例,并且Bean完成了它的工作,以上步骤都将返回Home中重复执行。
这种方式带来太多的系统开销。
EJB2.0中带来一个新功能解决这样的问题,你可以通过本地对象,高效调用Bean。本地对象实现本地接口。本地调用Bean过程如下:
客户端调用本地对象
本地对象完成所需的中间件服务
一旦企业级Bean实例完成了它的工作,它将控制权返回给本地对象,本地对象再将控制权返回客户端。
这就免去了stub,skeleton,网络,整理/再整理参数的步骤了。
javax.ejb.EJBLocalObject
javax.ejb.EJBLocalHome
本地接口有两个重要的坏处:
只有当你在同一进程中调用Bean时,它才有效。
它们通过引用而不是值来对参数进行marshal。这也许会因为没有复制参数而加快你的应用系统,但这也同时改变了你的应用系统的语义关系。
2.4.5部署描述
EJB2.0中部署描述符是一个XML文件,
可用部署描述来指定下列要求:
Bean的管理和生命周期要求
持久性要求(仅限实体 Bean)
事务处理要求
安全性要求
2.4.6供应商特有文件
2.4.7EJB-jar文件
Bean类,Home接口,Remote接口以及部署描述文件,供应商特有文件一旦生成,就可以将这些文件打包成一个EJB-jar文件了,此文件是一个压缩文件,格式为.zip。
第二章:你的第一个Bean
如何开发一个EJB组件?
第一,写组合你的Bean的.java文件(组件接口,Home接口,Bean类,帮助类)
第二,写部署描述符
第三,编译.java文件成为.class文件
第四,使用jar工具,创建一个EJB-jar文件,包含.class文件和部署描述符。
第五,在你的容器中部署EJB-jar文件
第六,配置你的EJB服务器
第七,启动EJB容器,并确认已载入你的EJB-jar文件
第八,写一个客户端测试.java文件,测试。
接口java.rmi.Remote
接口javax.ejb.EJBLocalObject HelloWorldLocal接口 HelloWorldEJBLocal对象
接口javax.ejb.EJBObject HelloWorldRemote接口 HelloWorldEJB对象
接口javax.ejb.EJBHome HelloWorldHome接口 HelloWorldHome对象
接口javax.ejb.EJBLocalHome HelloWorldLocalHome接口 HelloWorldLocalHome对象
接口java.io.Serializable javax.ejb.EnterpriseBean接口 HelloWorldBean类
EJB与异常:
EJB中每一个有网络功能的对象都守RMI-IIOP标准,而且都必须抛出一个远程异常。
更一般地,EJB定义下列异常:
系统级异常
应用程序级异常
两类异常处理方法大不一样
系统级异常不必抛回给客户端。EJB对象是EJB容器生成的Bean包装器,充当客户端和Bean本身的中间人,能够拦住Bean抛出的任何异常,这使得EJB对象能选择哪些异常让客户端看到。而应用程序级的异常则必须抛回客户。
除了区分并处理系统级异常和应用程序级异常外,EJB对象还负责捕获所有Bean可能抛出的所有无法控制的异常。
当调用create()和remove()方法时会发生什么:
EJBContexts:通向容器的路径
容器将所有信息都放在一个叫EJBContext的对象中,
当EJB-jar文件部署在EJB容器时,一般执行以下几个步骤:
第一, 核对EJB-jar中的文件
第二, EJB容器提供的工具生成EJB对象和Home对象。
第三, EJB容器提供的工具生成任何必要的RMI-IIOP存根(Stubs)和骨架(SKeletons)
执行完这些之后,启动EJB容器(如果它还没开始运行)。
可选的EJB客户端的jar文件
EJB-client.jar
…
<ejb-jar>
<enterprise-beans>…</ enterprise-beans
<!-->
<ejb-client-jar>HelloClient.jar</ejb-client-jar>
</ejb-jar>
这个文件完全是可选的,多数都不会使用
3.12理解点样调用Bean
两种不同类型的客户端
基于Java RMI-IIOP的客户端
CORBA客户端
不管是使用CORBA还是使用RMI-IIOP,典型的客端代码有以下特点:
查找Home对象
使用Home对象创建EJB对象
调用EJB对象的商业方法
从内存中清除EJB对象
查找Home对象
如何应用JNDI定位Home对象
3.14 实现组件接口
第四章:会话Bean介绍
会话Bean代表的是调用它的客户程序所完成的工作,会话Bean是商务过程对象。
会话Bean和实体Bean之间的一个主要的区别就是它们的存活周期。相对来说,会话Bean存活周期短。一般地,客户会话时间长短决定着一个会话Bean使用的长短。EJB容器在客户端中止连接时清除会话Bean。一般来说,当应用服务器崩溃时或者机器崩溃时,会话Bean的生命周期也就会结束。会话Bean是非持久性对象,这意味着会话Bean不存储于永久性存储器中。
4.2会话Bean子类型
有状态会话Bean(对话型)
是服务于商务过程而设计的Bean。这些商务过程往往要跨越很多方法请求和事务处理。为了实现这个目标,状态会话Bean保留每个客户的状态。如果一个状态会话Bean的状态在方法调用期间改变,那么在接下来的调用过程中,与Bean对应的客户的状态也变。
无状态会话Bean(非对话型)
只保留单一对话内容,它们没有状态是因为它们不与客户程序进行多方法对话。
如果一个Bean的一次对话只持续单一的方法调用,该Bean就叫无状态会话Bean。在每一个方法调用完之后,容器可能会选择销毁这个无状态会话Bean,或者重新生成一个,这样就消除了所有过去的调用相关信息。当然容器也可以选择保存实例,客户端可得用。无状态会话Bean并不保存方法之间状态。无状态会话Bean可以保持不与任何特定客户相关的状态。为了使无状态会话Bean对客户端程序有用,客户端必须将Bean需要的所有客户作为参数传递给商务逻辑方法。因为无状态会话Bean不保存任何对话状态,同一个无状态会话Bean类的实例都是相同的,这意味着任何无状态会话Bean可以为任何客户端程序请求服务,因它们是等同的,实际上每个方法调用中,无状态会话Bean可以存储在调度池内,被重用和在客户端程序之间交换。
4.3状态会话Bean的特征
4.3.1对状态会话Bean实现调度池调度
对于状态会话Bean来说,实现调度池调度就不像无状态会话Bean那么简单。
容器不能简单地调度Bean和将它们动态地分配给任意一个客户端程序方法请求,因为每一个Bean都存储一个特定客户状态。但仍然需要对状态会话Bean采取调度池调度,因为这样可节省资源和提升整个系统的可伸缩性。
上下文交换
EJB容器采用这个模式来保存状态会话Bean资源。为了限制会话Bean实例在内存中的数量,EJB容器将状态会话Bean交换出去,其对话状态保存在硬盘或其它存储器中,这种方法叫钝化。当钝化的Bean原先的客户端对其触发方法进行调用时,被钝化的对话状态重新交换给Bean,这叫做激活化。注意,接收激活的不一定是原先的Bean实例。但是这没有关系,因为新的Bean实例从原先的Bean实例钝化时的那一点重新开始对话。
钝化/活化,有可能导致I/O瓶颈。
EJB容器如何决定哪个Bean钝化/活化,这与EJB容器有关,常采用的一种钝化策略是最近最少使用策略。只要Bean没有被调用,钝化随时都可以发生,什么时候钝化完全由EJB容器决定。注意:参与事务处理的Bean只有等事务处理完成后,才能被钝化。
大多数EJB容器采取JUST-IN-TIME策略激活Bean。当用户请求时才发生。一般而言,钝化/活化对无状态会话Bean无用处,因此它可被EJB容器随意地从内存中清除。
4.3.2对话状态遵从的规则
更严格地讲,Bean的对话状态应遵从JAVA对象序列化所规定的原则。
如果满足下面两点的话,Bean的每一个成员变量都被认为是Bean对话状态的一部分:
1, 成员变量是非瞬变基本类型
2, 成员变量是非瞬变java对象
Bean还可能持有容器实现的对象的引用。容器必须在钝化/活化时保存以下内容:、
1, EJB对象的引用
2, HOME对象的引用
3, EJB上下文的引用
4, JNDI命名上下文
4.3.3钝化/活化回调方法
当EJB容器钝化BEAN时,它将BEAN的对话状态写辅助存储器,EJB容器通知Bean它将调用Bean必需的回调方法ejbPassivate() ,以执行钝化操作,ejbPassivate()方法事先告知Bean,它所保留的对话状态将被交换出去。EJB容器使用ejbPassivate()方法通知Bean,这一点很重要,它让Bean释放所占用的资源。一旦ejbPassivate()方法调用结束时,Bean必须处于可被钝化状态。
相反的过程发生在活化过程中。序列化的对话状态被读回内存,EJB容器使用对象序列化或类似方式重建内存状态。EJB容器接着调用Bean必需的ejbActivate()方法,此方法让Bean有机会恢复它在ejbPassivate()过程中所释放的资源。
除非你使用开放性资源,例如套接字连接和数据库连接,这些资源在激活后必须重新建立,你不用去关心ejbPassivate()的实现了,在大多数情况下,你不需要向这些方法中加入任何东西。
(家里部分)
SessionContext接口扩展EJBContext接口
对于会话Bean来说,当你的Bean要调用另外一个Bean和你的Bean传递一个引用进,方法getEJBObject()和getEJBLocalObject()方法是很有用的。在java中一个对象可以通过关键字this来获取其自身的引用,但在EJB中,一个Bean不能使用this并把它传递给其它Bean,因为所有的客户端程序都是通过Bean的EJB对象间接地调用Bean中的方法的。这样,Bean只能通过它的EJB对象来引用自身,而不是通过关键字this。
4.3.6会话Bean的生命周期图表
状态会话Bean的生命周期与无状态会话Bean的生命周期类似,但是两者又存在以下重要区别:
第一, 因为每个实例都包含状态,所以没有等价实例的调度池
第二, 存在钝化与活化的过渡
第三, 不要依赖于ejbRemove()
容器可以在任可时候调用ejbRemove(),就算容器认为Bean已经被清除了。注意,容器在即使在其崩溃时或重大异常发生时也可能永远不会调用Bean的ejbRemove()方法。
第五章 实体Bean介绍
实体Bean是能够存放在永久性存储空间中的持久性对象,这意味着你可以用实体Bean来对你的商务中的基础数据建模。
5.1持久性的概念
实体Bean是持久性对象。
Java对象序列化
一般来说,利用对象序列化来存储查询对象的代价很高,而且麻烦,对于大规模的应用,提交基于商务数据的查询是必要的,这使得简单的对象序列化不适于持久存储。
对象-关系型数据库映射
存储java对象的另一个常用方法是使用传统的关系型数据库。
与简单的对象序列化相比,对象-关系型数据库映射是一种复杂的持久对象机制。
对象数据库
对象数据库管理系统(ODBMS)是持久化存储器,保存着全部对象。这没有对象-关系型数据库映射层,因为java对象本身作为完整的对象被存储。因此你不需要针对关系型数据库API编程,而是针对对象数据库API进行编程。
对象查询语言(OQL)
对象数据库也有很好的性能和可扩展性。提供了非常强大的完整性与安全性。不过对象数据库产品还没有被行业充分地接受。
5.2什么是实体Bean
应用逻辑组件(会话Bean能很好地模型化这些应用逻辑组件)
持久数据组件(实体Bean就是这些持久组件)
为什么要把商务数据当做对象来处理,而不是处理数据库中的原始数据呢?答案是将数据视为对象很便利的,能方便地操作并管理。
你应把实体Bean想象成:
一个在内存中的持久数据的Java表现形式
能够知道如何从一个存储空间中读取它自已并用这些存储的数据组合成它的域
一个可以在内存中即时被修改的对象并且改变数据的值
可持久化,所以它可以再次被存回存储空间中,从而更新了数据库中的数据
实体Bean包含的文件:
包含所有EJB必包含的组件外,还有:‘
实体Bean类:映射一个数据模式中的一个实体定义,
实体Bean的主键类:使每个实体Bean都不同。一个主键是一个可能包含任意多个属性的对象。无论什么数据,唯一地标识一个实体Bean数据实例都是必须的。
5.3实体Bean的特征
服务器崩溃或者数据库崩溃都不会影响一个实体Bean的生存期。因为它是永久性的。
实体Bean实例是一个对应到数据库中的视图。
ejbLoad()从持久存储空间读入数据到实体Bean在内存的域中。
ejbStore()保存Bean实例的当前域到底层的数据存储空间。容器决定调用这两个方法。、
5.3.3几个实体Bean实例可能代表同一底层数据
允许多个客户端共享相同的实体Bean实例,但这对EJB不适合的,原因有两个:一是保证线程安全编码困难,二是多个执行的线程会使事务几乎不可能被底层的事务处理系统所控制,原因是EJB规定只有一个线程可以不断地运行在一个Bean实例当中。三种Bean都是单线程的。要求每一个Bean每次只服务于一个客户,这会引起瓶颈,为了提升性能,我们可以允许容器实例化同一个实体Bean类的多个实例。这将允许多个客户端并发地访问这些相互独立的实例,每个实例都代表同一个底层实全数据,多个Bean实例代表同一个数据,这又带来一个新问题:数据破坏。为了达到实体Bean实例缓存的一致性,每个实体Bean实例必须进行与底层存储空间例行同步,容器通过调用Bean的ejbLoad()和ejbStore()方法调用返回来同步Bean和底层的存储空间。Bean和底层存储空间同步频率由事务决定的。事务允许每个客户端的请求与所有其它请求相隔离。
5.3.4实体Bean实例可以被收集再利用
激活和挂起,当一个实体Bean实例被挂起,它要释放占用资源并将它的状态保存到底层存储空间中,因此容器会在Bean被挂起之前调用它的ejbStore()方法。同样地当一个实体Bean实例被激活,它不但要获得它所要的资源,还必要从数据库中加载最新数据。容器会在实体Bean被激活之后调用它的ejbLoad()方法。
ejbActivate()(激活方法)
ejbPassivate()(挂起方法)
5.3.5保持实体Bean的两种方法:
Bean管理的持久性
容器管理的持久性
5.3.6实体Bean的创建与删除
ejbCreate()
ejbRemove()
理解实体Bean是怎样被生成和销毁的
实体Bean的查找:
查询一个实体Bean类似于在SQL中执行一条select语句。会话Bean不能查找。
5.4实体上下文
第六章 编写Bean管理的持久性的实体Bean
扩展javax.ejb.EntityBean
其方法:
setEntityContext() 将一个Bean和环境信息联系起来
ejbFind…(…) 当Bean实例还在池中,查到Bean数据实例。至少必有一个ejbFindByPrimaryKey()方法
ejbHome…(…) Home方法,这些方法不与任何给定的数据实例(或行)相关,因为Home方法是在缓冲池中的Bean调用的,而且发生在Bena与任何的特定数据关联之前,所以它是一种特殊的方法。客户端通过Home接口或者本地Home接口调用Home方法。
ejbCreate(…)创建新的数据库数据并初始化你的Bean(如果你不想EJB客户羰能创建新的数据库数据,你可不写这个方法)
ejbPostCreate(…)对于每一个ejbCreate()方法,你的Bean类必须定义一个ejbPostCreate()方法,而且相同的参数。容器恰好在ejbCreate()方法之后调用ejbPostCreate()方法。
ejbActivate()激活
ejbLoad()加载数据库中的数据到Bean 实例中
ejbStore()将Bean实例中数据更新到数据库中
ejbPassivate()挂起
ejbRemove()删除数据库中的数据,它不是用于删除java对象的
unsetEntityContext()将Bean与环境分离。当你的实体Bean实例被删除之前容器调用这个方法
定位器方法的一些规则:
一, 都以ejbFind开头,
二, 必需有一个ejbFindByPrimaryKey()方法
三, 可以有多个不同定位器方法,每个都可有不同名称与参数。
四, 一个定位器方法必须返回它找到的实体Bean的主键,如果它找到多于一个,就返回一个主键集合
五, 与ejbCreate()方法一样,客户端不能在Bean实例自身上调用定位器方法。、
六, 实体Bean实例给容器返回一个主键。而Home对象返回一个EJB对象给客户端程序。
七, 除了强制性的前缀ejb和在Find中大写首字母外,Bean类签名与Home签名是相同的。
八, 当客户端程序调用Home对象的定位器方法时,Home对象让Bean找到所有符合客户端程序要求的主键。接着,Bean返回一个这些主键的集合给容器。
第六章:Bean管理持久性的实例
这个例子AccountBean类的代码为三部分:
Bean管理状态域
商务逻辑方法
EJB所必需的方法
6.4融会贯通:遍历BMP实体生命周期
理解容器与BMP实体Bean交互。
BMP实体Bean的生命周期:
第一, 不存在状态表示实体Bean还没有被初始化,
第二, 容器通过调用实体Bean类中的newInstance()方法,生成一个新的实例。这会调用你实体Bean的默认构造器,在内存中产生一个新的实例。下一步,容器使实体Bean和一个实体环境对象关联起来---完成这个任务要调用一个返回方法,setEntityContext(EntityContext ctx),只有在容器想要增加可用实体Bean实例池时,这上步才发生。
第三, 实体Bean和其它实体Bean存在于调度池中。这时,实体Bean并没有把任何实体Bean数据库中的数据加载进来,而且它也没有占用任何Bean特定的资源。
第四, 当客户端要创建一个新的数据库中的数据时,它在你的实体Bean的HOME对象上调用一个create方法,然后容器从调度池中取得一个实体Bean实例,并调用这个实例的ejbCreate()方法。
第五, 当Bean处于准备就绪状态时,它被绑定在特定的数据上,并因此绑定一个特定EJB对象上。
第六, 有两种方法把实体Bean扔回到调度池中。
第七章:编写容器管理的持久实体Bean
所有CMP实体Bean被分解为两个类:一个类是超类,由你编写,它包含实体Bean数据逻辑。另一个类是子类,由容器生成,它包含持久化逻辑。
7.1.2CMP实体Bean不包含声音字段
容器可能有一个位向量,它被用来跟踪实体Bean中被修改的字段,而这些字段要被写入存储介质中的。
你的Bean可能持有其它Bean的引用,容器必须要保持这些关系的引用完整。
get/set方法也是在子类中出现
超类中有这get/set方法的抽象方法
7.1.4CMP实体Bean有一个抽象的持久化模式
部署描述符中声明相关字段
CMP实体Bean拥有查询语言
EJB查询语言:EJB-QL是一种语法类似于SQL,面向对象,用于查询实体Bean的查询语言。它包含一个select从名,from从句一个可选的where从句。
7.1.6CMP实体Bean可以包含ejbSelect()方法:
是一个查询方法,Bean中作为一个辅助方法来访问数据库。ejbSelect方法并不通过远程接口或本地接口暴露给终端客户,它只能在Bean内部调用,要么从一个HOME方法,要么从一个商务方法中调用。它的价值在于以下三点:
第一, Select方法可以执行你的Bean所需要的细粒度数据库操作,但是你不要把它暴露给客户端。
第二, 它能从相关的其他实体Bean中提取数据,
第三, 像finder方法一样,select方法可以返回实体Bean。但是实体方法更加强大。
CMP和BMP之间主要差别在于如何Bean类和部署描述符的不同。远程接口,本地接口,Home接口,本地Home接口,主键类,基本上都是一样的,这意味着,在不改变客户程序情况下可以在CMP与BMP之间切换。
7.2实现容器管理持久性的指导原则
setEntityContext():与环境信息关联
ejbFind…(…):你不用为CMP编写定位器方法,
ejbCreate(…):创建新数据库中数据并初始化你的Bean
ejbPostCreate(…):
ejbActivate():
ejbLoad():
ejbStore():
ejbPassivate():
ejbRemove():
unsetEntityContext():
当容器解释EJB-QL时,它就生成数据库访问代码。
<![CDATA[SELECT OBJECT(a) FROM ProductBean AS a WHERE name = ?1]]>
CDATA,会告知XML的解释器略其中的文本。
Cmp不一定要定义主键类,而使用容器管理的一个域来作为主键类。
<primkey-field>productID</primkey-field>
但是应尽量避免使用域作为主键类,原因是主键类的封装器可以使你不必关心怎样在底层数据存储中惟一地表示自已。
第八章:消息驱动Bean
消息驱动Bean是一种通信轻型工具,能访问消息通道的特殊Bean。
在一些场合它比消息驱动Bean比RMI-IIOP更适合。
本章包括:
异步行为,面向消息中间件
JMS教程
消息驱动Bean功能
消息驱动Bean与实体Bean,会话Bean比较
如何开发消息驱动Bean
更高级的有关消息驱动Bean的主题
使用消息驱动Beanr的目的
RMI-IIOP的三个挑战:
性能
可靠性
支持多发送/接收
java消息服务(JMS)
MOM(Message-oriented middleware)
JMS两部分:API,SPI(plugin JMS Driver)JMS驱动程序知道如何同特定的MOM实现进行对话。
与JNDI,JDBC类同。
担保消息发送是如何工作的?
通过使用担保消息发送,面向消息中间件系统可以持久化您的消息到一个文本,数据库或者其它的存储介质中。
担保消息的一种变化形式是鉴定消息发送。鉴定消息发送不但可以保证从消息发生者到消息使用者的消息的发送成功,而且还会生成使用收条,此收条被发送到消息发生者,用来表示消息已经成功收到并使用。
担保消息发送的另一种变化形式是存储转发。储存转发可以使得消息发生者成功地发送消息到非活动MOM系统。
8.2.1消息机制的域
当使用消息机制时,要选择消息机制的域。域是为消息机制所起的富有想像力的名称,有如下几种类型的域:
发布/订阅方式(pub/sub)(类似于看电视):是分布式事件驱动处理模型的实现。
点到点方式(类似于打电话):
请求/应答方式(类似于RMI-IIOP):
8.2.2JAVA消息服务API
JAVA消息服务API比RMI-IIOP更加复杂,
javax.jms
javax.mail
javax.mail.event
javax.mail.internet
javax.mail.search
Java消息服务编程模型:
1,定位java消息服务驱动程序 (用JNDI完成)
2,创建java消息服务连接
3,创建java消息服务会话
4,定位java消息服务目的地
5,创建java消息服务发生者/java消息服务使用者
5, 发送/接收消息
消息驱动Bean实际上是作为我们的消息使用者的。
单线程Bean与多线程Bean的比较:
EJB一个好处就是你不需要编写线程安全的代码。你可以作为单线程来设计你的EJB,并不用担心并发客户访问你的组件时的线程问题。EJB容器会自动实例化你的组件的多个实例来对并发的请求提供服务。
EJB规范不允许多线程Bean。
使用线程的一种替代的方法是使用事务消息API,如java消息务服务。这样会允许分布式对象环境中异步方式。Java消息服务可以使你安全并可靠地实现多任务,而不会出现Bean本身同线程相混乱的程况。
8.3java消息服务同EJB集成:
消息驱动Bean:是能够接收JMS消息的特殊的EJB组件,消息驱动Bean使用来自队列或主题的消息,这些消息可以是由任意有效的JMS客户发送的。消息驱动Bean从任意的发送消息给它的客户中分离。客户不能通过组件接口来访问消息驱动Bean。Java消息服务是用来发送消息到消息驱动Bean的API。
消息驱动Bean主要特点:
1, 没有主接口,本地主接口,远程接口,或本地接口
2, 具有单个弱类型的商务方法。消息驱动Bean仅仅能接收来自java消息服务目的地的消息。此方法叫做onMessage()。你不能提供多种不同的消息驱动Bean的商务方法。
3, 不具有任何返回值。这是因为消息驱动Bean同消息发生者分离,消息发生者不会等你的消息驱动Bean来响应,因为它持续处理发送的消息。
4, 不能够发送异常给客户。这是因为消息发生者不会等你的消息驱动Bean来接收消息。实际上EJB规范禁止消息驱动Bean抛出应用异常。但可生成系统异常,容器处理系统异常。
5, 是无状态的。
6, 可以是持久的也可以是非持久的订阅者。对主题持久的订阅意味着java消息服务订阅者接收所有消息,就算在订阅者为非活动状态的情况下。而对主题的非持久的订阅意味着订阅者仅仅能接收订阅活动时所发布的信息。
8.4开发消息驱动Bean
实现两个接口类,分别为:
javax.jms.messageListener
javax.ejb.MessageDrivenBean
每一个消息驱动Bean类必须提供一个ejbCreate()方法,返回void,并不接收任何参数。
消息驱动Bean生命周期:
要么处于“不存在”状态,要么处于“组合”状态。
方法介绍:
onMessage(Message)为Bean所有使用的每一条消息调用此方法,此方法的参数是被使用的引入消息。
ejbCreate()当消息驱动Bean第一次被创建并被加入到Bean池中时调用此方法。
ejbRemove()
setMessageDrivenContext(MessageDrivenContext ctx)
例子
高级概念
事务:
消息驱动Bean不会和发送消息的消息发生者运行在同一个事务中,因为通常有两个事务与每一个持久的JMS消息相联系。
安全性
消息驱动Bean不会接收发送消息的消息发生者的安全性标识,因为没有标准的方法来安全性信息加到JMS消息中。因此你不能使用消息驱动Bean执行EJB安全性操作。
负载平衡:
消息驱动Bean的一个特点是有理想的复杂平衡范例。
在群集中的多重消息使用:
难点
第九章:为Bean增加功能
9.1.1从其它的Bean调用Bean
为了使你的Bean调用其它Bean,你需要完成所有客户端程序要完成的一系列操作。你可能需要:
第一, 调用JNDI查找其他Bean的Home对象
第二, 调用Home对象的create()方法
第三, 调用EJB对象的商务方法
第四, 调用EJB对象的remove()方法
首先要提供JNDI初始化参数,JNDI驱动程序,它在不同容器之间是不同的。Bean应是与容器无关的,在Bean中写入有关JNDI的代码会破坏可移植性。幸好,你从一个Bean查找另一个Bean,不需要提供任何JNDI初始化参数。你只需要获得默认的JNDI初始化上下文环境。容器在你的Bean运行之前设置默认的JNDI初始化上下文环境。
9.1.2理解EJB引用:
EJB引用是你用来查找Bean的JNDI位置的别名。这个别名也许不与部署员部署Bean所用到的JNDI位置相对应。程序代码通过别名来查找Home,然后部署员将这个别名与他所选定的JNDI位置绑定在一起。
9.2资源库
如何通过EJB组件来执行对外部资源的调用。资源库是一个资源的提供者,如JMS驱动程序和JDBC驱动程序或JCA资源适配器。资源库是给你提供连接驱动程序的。
连接收集再利用:
连接收集再利用是对Scoket的利用。这增加了系统的可扩展性。连接收集再利用是内建于大多数容器中的。Jdbc为连接收集再利用指定了标准接口。这些完全是幕后发生的,与你Bean中代码无关。
要开始使用一个资源库,首先要定位它。EJB规定用JNDI来查找资源库。这很有用,你只要学习一个JNDI API,就可以查找所有驱动程序(JMS,JDBC,JCA等)。另外这些资源可能要授权,EJB规范提供了两种验证自我的方法:
一,在你的Bean程序代码中自行执行验证(res-auth元素设为Application)
二,让部署员为你处理身份的验证(res-auth元素设为Container)
9.3环境属性:
怎样在运行期定制你的Bean?
Bean的环境属性是在运行时间内Bean读取的特定应用程序属性。这些属性可用来定制你的Bean并使你的Bean成为数据驱动的Bean。这是一种相对于数据库中存储数据快速而简便的方法。
使用环境属性的第一步是在部署描述符中声明它们。容器读取这个部署描述,让你的Bean在运行期间能访问这个环境属性。
9.4理解EJB安全性:
为EJB系统增加安全性,客户端必须通过两个安全措施:
第一, 客户端必须通过验证(验证身份,EJB调用方法之前)
第二, 客户端必须通过授权。(获得通过验证的用户是否允许某项操作,发生在EJB方法调用期间)
验证:
在EJB1.1之前,验证不是可移植的,与容器相关。在ejb2.0之后,验证变得健壮并可移植。你可通过一个j2ee中的单独的API-java验证和授权服务(JAAS)来完成验证。
JAAS概描:
JAAS是一个能使你在JAVA中验证用户和给用户授权的可移植性接口。简而言之它能使你进入一个系统而不要知道底层是采用什么安全系统的。JAAS的强大之处在于它能使用几乎所有的安全系统。
你在使用JAAS时,有两种可能的情况:
第一, 当你拥有一个与远程EJB系统连接的单独的应用系统时,用户将向应用系统提供证明身份的信息。
第二, 当你拥有一个连接到Servlet/JSP层的基于Web浏览器的客户端程序时,基于web浏览器的用户将向Servlet/JSP层提供证明身份的信息。
Web浏览器可用如下四种方式之一来提供证明身份信息:
1, 基本验证(不是一种安全的方式)
2, 基于表格的验证(类似于基本验证)
3, 摘要验证(web客户端应用程序向web服务器提供一个特殊的消息摘要)
4, 证书验证
JAAS体系结构
授权
安全性的传播
9.5理解EJB对象句柄
第三部分:高级EJB概念:
10.4事务在EJB组件中的应用
本质上讲,EJB组件可以使用事务。
10.4.1后台事务系统的抽象分离
在EJB中你的代码不会直接受到底层事务系统影响,你的EJB组件也不会与事务管理器,资源管理器直接发生关系。你开发的应用程序代码时并不关心处于底层的后台事务系统,底层事务系统抽象分离于运行在后台的EJB容器。
10.4.2声明型事务,编程型事务和客户端初始化事务
划分事务边界。
EJB有两种划分事务边界的方法:
编程型
声明型
编程型事务
大多数现有系统都使用编程型事务来划分事务边界。这种方法,你必要将事务的逻辑操作编写入你的应用程序代码中。你必须负责发布一个事务开始的声明和一个提交或异常结束的声明。
声明型事务
声明型事务允许组件自动地参与到事务中去。就是你的EJB组件不会发布事务开始,提交或异常结束的声明,而是由EJB容器来为你做这件事。这是很有价值的,因为Bean组件不需要接触事务API。在部署描述符中指定以哪一种方式加入事务,<transaction-type>(Container/Bean)。
客户端初始的事务:
执行事务的最后一个途径是在你的Bean之外,从客户端编写代码来开始和结束事务。客户端程序调用企业级Bean仍然需要通过编写代码来使用编程方式或声明方式控制事务。
10.4.3选择事务的类型
事务与实体Bean
Bean管理的事务对于实体Bean是不合适的。实体Bean必须使用声明方式的事务。
而会话Bean和消息驱动Bean可以使用Bean管理的事务。
编程方式控制事务的好处是Bean可以完全控制事务边界。相比之下,如果以声明方式或客户端初始化方式控制事务的话,你的Bean只能要么运行在一个事务当中,要么不运行在一个事务中。声明方式控制事务的好处在于它们比较简单。而且不要改动源码就可对事务进行优化。
10.5容器管理的事务
指示容器怎样去执行一个事务
事务属性就是Bean组件特有的一种设定,这设定可以控制你的Bean组件加入事务的方式。事务属性是Bean部署描述符中必不可少的部分。
事务与消息驱动Bean
消息驱动Bean,事务类型的选择对其影响很大。
若使用容器管理的事务,消息驱动Bean将在它执行商务逻辑的同时在同一事务中从目的地读取消息,如果出现了问题,事务将执行恢复,而且将出现消息确认。如果是Bean管理的事务,在消息驱动Bean接收到消息后,事务将分别开始和结束,然后你可以使用部署描述符确认模式来通知容器对消息进行确认的时间。如果你根本不支持事务,容器将在稍后的一个时间确认消息。
若选择Bean管理事务,当出现问题之后,它不能保证将消息指向原来的目的地,因为Bean没有办法指出发生的问题。对于消息驱动Bean我们推荐使用容器管理的事务。
你必须为Bean中所有商务方法设置事务属性。
另外,对于实体Bean你必须为HOME接口方法设置事务属性,因为HOME接口中的创建方法在数据库中插入数据,而这个操作必须是事务的。
事务的属性:
每一个EJB组件都必须有一个事务的属性设定。下面列出部署描述中事务的属性:
Required如果希望Bean始终运行在事务中,选它。
RequiresNew如果当Bean组件被调用,你希望开始一个新的事务,使用它。
Support它只运行在一个事务当中,当已运行一个事务,只是加入,当没有事务时,开始一个新的事务
Mandatory要求当你的Bean组件被调用时,事务必须已经被运行。否则返回一个javax.ejb.TransactionRequired异常。Mandatory是一个安全属性。它保证了你的Bean必运行在事务中。若没有正在运行的事务,任何方法都不能调用你的Bean组件。
NotSupported你的Bean组件不能运行于事务中。
Never也意味着你的Bean不能运行于事务当中。
注意:
实体Bean和带有SessionSynchronization的状态会话Bean必须使用事务,因为它们都必是事务性的,你不能对他们使用:Never,NotSupport,Supports属性,若你这样做,则其将是不可移植的。另外处理客户端程序事务的属性对于消息驱动Bean来说将是没有意义的,这些属性包括:Never,Supports,RequiresNew,Mandatory。
10.6EJB中的编程型事务
相比之下,编程型事务允许更高级的事务控制,但它们却不容易使用。为了自已控制事务边界,你必须使用java事务API(JTA)。
10.6.1CORBA的对象事务处理服务(OTS)
OTS服务就是一系列格式规范的接口,这些接口指明了事务将如何在后台运行,并且使用事务管理者,资源管理者和事务对象互相协作。OTS分为两部分:CosTransactions和CosTSPortability。
CosTransactions接口是一种基本接口,通过这个接口,事务对象/组件,资源管理者和事务管理者可以共同操作。这些接口保证了上述参与者可以任意组合。
CosTSPortability接口是为多参与者执行事务提供了一种可移植方式。
OTS的内部机制与EJB组件的开发一点都不相关。作为EJB程序员,不用关心底层事务服务,不必理解复杂的中间件API。EJB使你不用接触事务服务,如OTS。
10.6.2java事务处理服务(JTS)
只有系统开发商才需要了解OTS的内部机制。但它对你却很有用,所以SUN将OTS分为:JTS(Java Transaction Service)与JTA(Java Transaction API)
JTS就是为系统级开发商设计的CORBA OTS 的JAVA 映射。JTS为后台的事务管理者和资源管理者定义了一个接口。通过使用这个接口,不同开发商的产品可以共同操作。它还对事务管理者和资历源管理周边的对象和使用对象进行了定义。作为应用程序开发员不必关心大多数OTS,包括JTS。你只要关心允许你通过编程控制事务边界的JTA。
10.6.3 JTA
JTA就是被组件和应用程序开发员所使用的一种事务处理API。你可在客户代码或Bean组件代码中使用JTA通过编程方式控制事务的边界。
JTS包括两种接口:
一种是基于X/Open XA 资源管理者的
另一种是用于支持事务的编程控制的(javax.transactionUserTransaction)。
10.6.4声明型事务和编程型事务的应用范例比较
放弃事务:
放弃事务意味着强制一个事务放弃其动作,当出现问题时,你就需要结束一个事务,这些问题可能是数据库无法连接或者客户端传输了错误的参数。
可心调用rollback()放弃一个事务,但你怎样放弃你参与到其中但却是别人启动的一个事务呢?
有两种性况:
第一,你的事务参与者是一个使用声明型事务的EJB组件:调用EJB Context对象的setRollBackOnly()方法。
第二,你的事务参与者不是一个EJB组件,比如说是一个JAVA对象:可通过查找JRA并且调用JTA的setRollbackOnly()方法来放弃一个事务。
10.7如何使用客户代码控制事务:
控制事务的最后一种方式就是客户端代码。你可在调用Bean组件的客户端代码中使用JTA。要想从客户端代码中控制事务, 你必须通过JAVA命名和目录接口(JNDI)来访问JTA UserTranaction接口。你应尽可能将事务保持在很短的周期内,较长周期的事务会引起多用户操作的中断。若是你要一个长周期的事务,你应使用分布式锁处理机制,例如CORBA锁服务,不幸的是,J2EE中并没有类似分布式的锁服务.
10.8事务的隔离
隔离性能够保证并发用户彼此相互隔离.就算它们对同一数据库时行操作.底层事务系统通过后台运行并发控制来实现隔离性.
10.8.1并发控制的需求:
加锁.
隔离性与锁:
性能问题
死锁问题
为提高性能,事务将锁分为两个主要类型:读取锁(非独占型的)和写入锁(独占型的)
隔离性与EJB的理论:.
作为EJB开发者,你需要控制事务与另一个事务相互隔离的程度(可严可松的隔离).EJB为你提供了不同的隔离级来适应不同的需要.隔离级允许你在不关心底层细节的情况下指定并发控制.
隔离级分四种:
READ_UNCOMMITTED模式:不保证任何隔离性
READ_COMMITTED模式:可解决不当读取问题
REPEATABLE_READ模式:可以解决不可重复读取问题
SERIALIZABLE模式:可以解决幻影读取问题
不当读取问题:当你的应用程序从还没有提交永久性更新的数据库中读取数据时,就会产生不当读取问题
何时使用READ_COMMITTED模式:用这模式,你无法读取那些已经写入但没被提交的数据,这意味着你读取的任何数据都是一致性的数据。
这种模式主要用于从数据库中读取数据并形成数据值报表的程序中。这是大多数数据库默认的隔离级。
不可重复读取问题:
当一个组件从数据库中读取数据时,数据发生了变化,这时就会产生不可重复读取问题。其原因可能是另一个并发事务修改了你的正在读取的数据。
何时用REPEARABLE_READ模式:
无论你什么时候在数据库中读取已提交的数据,你都可以在以后重新读取此数据,并且数据的值与第一次读取相同。因此你的数据库是可重复读取的。当你要更新资源中一个或多个数据项时,就使用这个模式。你希望能够读取每一个正在修改的数据行并更新它们,而且知道此时这些数据行不会被其它事务所修改。
幻影读取问题:
是指两次数据库读取操作之间,一组新的数据会在数据库中出现。不可重复读取问题与幻影问题的区别在于:现存的数据被改变时所发生的是不可重复读取的数据,而插入新的数据时所发生的是幻影读取问题。
何时使用SERIALIZABLE模式:
此模式保证了事务互不干扰地连续执行,并在整个事务过程中强迫执行ACID属性中的隔离性。这意味着每个事务将真正地隔离于其它事务。在必须具有完全的事务隔离的关键任务系统中,将会用这一模式。这将保证你不会读取没提交的数据。
隔离级越高,性能越慢。
10.8.7隔离性与EJB
怎样在一个EJB环境中建立隔离
一, 如果你是Bean管理事务,则可用资源管理器API指定隔离级别。
二, 如果是容器管理事务,无法在部署描述符中指定隔离级,要么使用资源管理器API,要么依赖容器工具或者数据库工具来指定隔离级别。
隔离的可移植性问题:
没有一种可移植的方式来为容器管理事务的Bean指定隔离级别的办法,你要依赖于容器或数据库。
10.8.8限制式和开放式并发控制
EJB所遵循的两种基本的对象并发控制策略是限制式和开放式。
限制式需要在事务其间对数据上锁以保证没有其它人对数据进行修改。适于小规模系统。可扩展性差
开放式不对数据上锁,当数据库冲突时就rollback。适用于大型系统。
10.9分布式事务
跨越多层的有多个事务加入的事务集。分布式平面事务允许多个由不同开发商编写的应用服务器在同一个事务中进行合作。
10.9.1稳定性与两阶段提交协议
事务分两阶段执行:
阶段一,所有资源的更新都写入事务日志。
阶段二,执行真正更新。
事务被分成两个阶段来完成被叫做两阶段提交协议(2PC)。它允许多个事务管理者和资源管理者参与到一个事务中。
10.9.2事务的通信协议和事务上下文
事务上下文就是一个保存了系统当前事务状态的对象。EJB规范并不支持这个级别上的互操作性,来自不同供应商服务器不能保证协同工作。
因2PC性能很差,大多数组织很少与两个不同的供应商打交道。
10.10在EJB中设计事务对话
终止商务过程
第一章:
构建一个大型的商务系统时需要考虑的因素
远程方法调用
平衡负载
透明故障恢复
后台集成
事务
群集
动态重部署
无损关机
登录和检查
系统管理
线程化
面向消息的中间件
对象生命周期
资源共享
安全
高速缓(冲)存
可重用中间件
EJB简介
是一个关于用JAVA语言开发的可部署的服务器端组件的组件体系结构。
三大优点:
业界认可的
移植容易实现
快速应用系统开发
EJB实际上分两部分:
规范
一组java接口
如果你不想跟随EJB技术,那么你还有其它的两种选择:
微软.NET平台可控组件
对象管理组织的(OMG’s)公共对象请求代理结构(CORBA)
作为一种商务解决方案的EJB
ejb是专门用来解决商务问题的,EJB组件(企业Beans),可执行如下任务:
执行商务逻辑
访问数据库
访问其它系统
胖客户(GUI有关,java中包括小应用程序(applet)和应用程序(application))
动态生成的WEB页
基于XML的web服务封装器
javabean是不可部署的,而EJB是可部署的.
第二章:EJB基础
EJB技术基于其它两项技术:Java RMI-IIOP和JNDI
附录A有相关知识
Java RMI-IIOP(Java Remote Method Invocation over the Internet Inter_ORB Protocol)与RMI
在java中,RMI-IIOP不是执行远程方法调用的唯一方法,你还可用RMI(JAVA远程方法调用).RMI是java中执行远程方法调用的最初方式,RMI使用java.rmi包.而RMI-IIOP是同CORBA兼容的RMI的特殊版本,RMI-IIOP同时使用java.rmi和javax.rmi.但EJB和J2EE强迫使用RMI-IIOP。
远程方法调用:
RPC
远程调用引发的一些问题:
编组和解组
参数传递协定(值传递,引用传递)
网络机器的不稳定性
远程接口:
接口
实现
使用RMI-IIOP时,必须建立称为远程接口定制接口,扩展java.rmi.Remote接口。
远程对象实现
扩展javax.rim.PortableRemoteObject。PortableRemoteObject是可以派生远程对象的基类。当远程对象被构造时,它自动调用PortableRemoteObject的构造函数。
或不扩展javax.rim.PortableRemoteObject。从另外的定制类中继承实现。
主键生成算法的问题
线程问题
JVM崩溃时
根程序和程序框架
在RMI-IIOP中网络实现的体系结构。
RMI需要以一种方式模拟一个本地对象,这个本对象称为根程序(Stub),它负责接收方法的本地调用,并将这些方法的调用委派给他们实际对象的执行代码,而这些代码有可能位于网络另一端,这就使得每个远程调用看起来像是本地调用。
根程序对于客户是本地的,程序框架对于远程对象是本地的。程序框架负责接收通过网络发来的调用(可能来自一个根程序),并将这些调用分配给远程对象的执行代码。
对象序列化和参数传递:
根程序和程序框架的功能是处理参数。
值传递:
用RMI请求一个方法时,传给远程对象的所有参数都是通过值传递的。意味着,将所有参数从一个机器复制到另一个机器。
通过值传递参数有一个问题,如果试图将一个对象通过网络传递,并且该对象引用了其它对象,在目标机器上怎样分清这些引用呢?一个机器的内存地址不会与另一个机器相同的内存地址相映射。同样目标机器中可能不会正好存在这个被引用的对象,我们怎么处理这种情况?java为了处理这个问题引入了对象序列化的概念来处理这个问题。
序列化是将一个Java对象转化为一个描述该对象的位块(bit-blob)。对象一旦变为bit-blob形式,就可以发送到任何地方的硬盘或网络上。准备再使用该对象时,必须将bit-blob解序列化成一个java对象。
实现java.lang.Serializable接口,这只是一个标识接口。当没有定义特定的序列化和解序列化方法,就会采用默认的序列化机制。
序列化规则
任何简单的基本类型(int,char等)自动地被序列化了的,并且在解序列化时是有效的。
JAVA对象可以选择被包含在序列化BIT-BLOB中,也可选择不包含在内。
用暂态关键字标注的对象不能序列化,并且在解序列化时无效。
怎样标识暂态transient
标识为暂态的理由:
对象非常大
对象代表了一个不能在目标机器上重新构建的资源。
对像代表了不想用序列化流传的敏感信息
对象序列化和RMI-IIOP
java RMI-IIOP依赖于通过远程方法调用传递参数的对象序列化
命名和目录服务器
一个命名服务器可心执行以下这些功能:
它把名称和对象关联起来(命名绑定到对象上)
提供一个根据命名查找对象的工具(查寻对象)
目录服务器是一个扩展和提高了的命名服务器,它为使用属性提供了目录对象的操作。一个目录是所有目录对象结合起来的一个系统。
LDAP
JNDI是命名和目录系统相互作用的一个基于JAVA的客户系统,它是命名和目录服务器上的一座桥梁,命脉名和目录服务器给不同的目录提供了一个共同的接口。
JNDI的优点:
能够仅仅通过学习单一的API来访问所有类型的目录服务器信息。
JNDI把应用程序从协议和实现的详细资料中隔离开来
使用JNDI可以从目录里读写全部JAVA对象
可以连接不同类型的目录
在J2EE中JNDI被用于多种目的:
使用JNDI获取对Java Transaction API(JTA) UserTransation接口引用。
使用JNDI连接资源工厂,如JDBC驱动程序,激活JAVA消息服务驱动程序
使用JNDI查询其它Bean
JNDI的结构体系:
两部分组成:客户端API和服务技术接口(SPI)。客户端API允许JAVA代码执行目录操作,对于所有类型的目录,它都是一样的。JNDI SPI 是一个命名和目录服务器供应商插入插件的接口,它正好和API相反,API允许用户一个单一完整的接口代码,而SPI允许命名和目录服务器提供商在系统里安装他们自已专有的协议。
JNDI结构体系类似于JDBC:
JDBC API JDBC驱动
JNDI API JNDI SPI
现在很多JNDI服务器提供商,包括LDAP,NIS,Novel NDS,SLP,CORBA,文件系统,RMI-IIOP。
J2ee服务器包含了JNDI实现。通常由J2EE服务器供应商提供定制实现。JNDI成为同RMI-IIOP,JMS结合在一起的由服务器提供的另一服务。
JNDI概念:
原字命名是一个简单的,基础的,不可分割的命名。
复合命名是由0个或多个原子命名组合在一起的。
绑定是一个名称到一个对象的关联。
命名系统,命名空间和合成命名
一个命名系统是一组相互连接的上下文。
在一个命名系统中,命名空间包含命名系统里所有的名称。
合成命名(composite name)是跨越多重命名系统的命名。
初始上下文生成库
命名空间字符串的起点被称为初始上下文,我们使用一个初始上下文生成库获取初始上下文,初始上下文生成库的任务是生成初始上下文。初始上下文生成库是由特定的JNDI服务技术提供的。
JNDI编程
Java.naming.factory.initial标识的是JNDI驱动程序类。
RMI-IIOP和JNDI的集成
有两种基本的应用方式:
使用JNDI API,RMI-IIOP服务器首先将自身发布到JNDI树。
客户使用JNDI来查询RMI-IIOP服务器
JNDI树通常与J2EE服务器运行在一起。当启动J2EE服务器时,JNDI树在进程内运行到J2EE服务器,同时启动。J2EE服务器也包含能够连接到此JNDI树实现的JNDI驱动程序。
2.1实体Bean
类型:
会话Bean
实体Bean
消息驱动Bean
分布式对象
EJB组件是基于分布式对象的,一个分布式对象是一个可以从远程系统调用的对象,它可以由一个进程中的用户来调用,也可由一个进程之外的用户来调用,或网络上的用户来调用。
客户端 — Stub (存根程序)— 网络 — Skelelon(框架程序)— 分布式对象
(家里部分)
实例调度的概念
应用程序服务器能够智能管理多种部署组件所需的资源,这些资源包括线程,套接字连接,数据库连接等。EJB规范中,容器的责任是在幕后提供全部的资源管理任务。除了资源管理以外,EJB容器还负责控制已部署的Bean组件的生存期。有一种叫实例池调度的调度方式,其好处是Bean池要比实际连接它的客户数目少得多。
Java RMI-IIOP and EJB对象
Javax.ejb.EJBObject扩展自java.rmi.Remote。java.rmi.Remote接口是基于IIOP的Java远程方法调用的一部分(RMI-IIOP)。任何实现java.rmi.Remote的对象都是远程对象。由于EJB容器提供的EJB对象实现远程接口,它也间接实现了java.rmi.Remote接口,这意味着,EJB对象是有网络功能的RMI-IIOP对象,可被其它JAVA虚拟机或者位于网络其它地方的机器调用。EJB远程接口实际上是RMI-IIOP远程接口。被调用的远程对象的方法都必须抛出java.rmi.RemoteException异常。远程接口必须遵守RMI-IIOP参数传递约定,必须是RMI-IIOP规定的有效类型,包括基本类型,可序列化对象,JAVA RMI远程对象。
2.4.3 Home 对象
客户端是调用EJB对象,而不是直接调用Bean。那么客户端是如何获得对EJB对象的引用呢?客户端从EJB对象“生成库”要求得到一个EJB对象,这个“生成库”负责对EJB对象的实例化和回收,这个生成库就是Home对象。
Home对象职责:
生成EJB对象
杳找现存的EJB对象(仅限于实体Bean)
删除EJB对象
Home接口必须扩展javax.ejb.EJBHome。javax.ejb.EJBHome也是扩展自java.rmi.Remote。
Home对象,EJB对象,Bean实例的关系:
有几个Home对象和每个Bean对应呢?问题的答案是和供应商有关,大多数容器中,HOME对象和每个BEAN实例关系常是1:N。编写Home对象时,它应是线程安全的,这样它才能响应多个并发的客户端请求。
每个Bean实例对应多少个EJB对象实例?当EJB对象是多线程的时,有些容器采用1:N关系。当EJB对象是单线程时,有些可能采用M:N的关系,M代表初始化的EJB对象数目,N代表调度池中Bean实例数目。
这些对于一个Bean供应商来说,都不要紧,因为容器对你来说,是透明的。
2.4.4本地接口
home接口一个不好之处是通过接口生成Bean是很慢的,对于通过远程接口调用Bean也是同样。因为当你远程调用一个EJB对象时,有以下步骤:
客户端调用一个本地STUB
Stub将参数整理成一种适合网络传输的形式
Stub通过网络Skeleton连接
Skeleton调用EJB对象
EJB对象完成所需的中间件服务(如连接缓冲,事务处理,安全检查,生命周期服务)
一旦EJB对象调用了企业Bean实例,并且Bean完成了它的工作,以上步骤都将返回Home中重复执行。
这种方式带来太多的系统开销。
EJB2.0中带来一个新功能解决这样的问题,你可以通过本地对象,高效调用Bean。本地对象实现本地接口。本地调用Bean过程如下:
客户端调用本地对象
本地对象完成所需的中间件服务
一旦企业级Bean实例完成了它的工作,它将控制权返回给本地对象,本地对象再将控制权返回客户端。
这就免去了stub,skeleton,网络,整理/再整理参数的步骤了。
javax.ejb.EJBLocalObject
javax.ejb.EJBLocalHome
本地接口有两个重要的坏处:
只有当你在同一进程中调用Bean时,它才有效。
它们通过引用而不是值来对参数进行marshal。这也许会因为没有复制参数而加快你的应用系统,但这也同时改变了你的应用系统的语义关系。
2.4.5部署描述
EJB2.0中部署描述符是一个XML文件,
可用部署描述来指定下列要求:
Bean的管理和生命周期要求
持久性要求(仅限实体 Bean)
事务处理要求
安全性要求
2.4.6供应商特有文件
2.4.7EJB-jar文件
Bean类,Home接口,Remote接口以及部署描述文件,供应商特有文件一旦生成,就可以将这些文件打包成一个EJB-jar文件了,此文件是一个压缩文件,格式为.zip。
第二章:你的第一个Bean
如何开发一个EJB组件?
第一,写组合你的Bean的.java文件(组件接口,Home接口,Bean类,帮助类)
第二,写部署描述符
第三,编译.java文件成为.class文件
第四,使用jar工具,创建一个EJB-jar文件,包含.class文件和部署描述符。
第五,在你的容器中部署EJB-jar文件
第六,配置你的EJB服务器
第七,启动EJB容器,并确认已载入你的EJB-jar文件
第八,写一个客户端测试.java文件,测试。
接口java.rmi.Remote
接口javax.ejb.EJBLocalObject HelloWorldLocal接口 HelloWorldEJBLocal对象
接口javax.ejb.EJBObject HelloWorldRemote接口 HelloWorldEJB对象
接口javax.ejb.EJBHome HelloWorldHome接口 HelloWorldHome对象
接口javax.ejb.EJBLocalHome HelloWorldLocalHome接口 HelloWorldLocalHome对象
接口java.io.Serializable javax.ejb.EnterpriseBean接口 HelloWorldBean类
EJB与异常:
EJB中每一个有网络功能的对象都守RMI-IIOP标准,而且都必须抛出一个远程异常。
更一般地,EJB定义下列异常:
系统级异常
应用程序级异常
两类异常处理方法大不一样
系统级异常不必抛回给客户端。EJB对象是EJB容器生成的Bean包装器,充当客户端和Bean本身的中间人,能够拦住Bean抛出的任何异常,这使得EJB对象能选择哪些异常让客户端看到。而应用程序级的异常则必须抛回客户。
除了区分并处理系统级异常和应用程序级异常外,EJB对象还负责捕获所有Bean可能抛出的所有无法控制的异常。
当调用create()和remove()方法时会发生什么:
EJBContexts:通向容器的路径
容器将所有信息都放在一个叫EJBContext的对象中,
当EJB-jar文件部署在EJB容器时,一般执行以下几个步骤:
第一, 核对EJB-jar中的文件
第二, EJB容器提供的工具生成EJB对象和Home对象。
第三, EJB容器提供的工具生成任何必要的RMI-IIOP存根(Stubs)和骨架(SKeletons)
执行完这些之后,启动EJB容器(如果它还没开始运行)。
可选的EJB客户端的jar文件
EJB-client.jar
…
<ejb-jar>
<enterprise-beans>…</ enterprise-beans
<!-->
<ejb-client-jar>HelloClient.jar</ejb-client-jar>
</ejb-jar>
这个文件完全是可选的,多数都不会使用
3.12理解点样调用Bean
两种不同类型的客户端
基于Java RMI-IIOP的客户端
CORBA客户端
不管是使用CORBA还是使用RMI-IIOP,典型的客端代码有以下特点:
查找Home对象
使用Home对象创建EJB对象
调用EJB对象的商业方法
从内存中清除EJB对象
查找Home对象
如何应用JNDI定位Home对象
3.14 实现组件接口
第四章:会话Bean介绍
会话Bean代表的是调用它的客户程序所完成的工作,会话Bean是商务过程对象。
会话Bean和实体Bean之间的一个主要的区别就是它们的存活周期。相对来说,会话Bean存活周期短。一般地,客户会话时间长短决定着一个会话Bean使用的长短。EJB容器在客户端中止连接时清除会话Bean。一般来说,当应用服务器崩溃时或者机器崩溃时,会话Bean的生命周期也就会结束。会话Bean是非持久性对象,这意味着会话Bean不存储于永久性存储器中。
4.2会话Bean子类型
有状态会话Bean(对话型)
是服务于商务过程而设计的Bean。这些商务过程往往要跨越很多方法请求和事务处理。为了实现这个目标,状态会话Bean保留每个客户的状态。如果一个状态会话Bean的状态在方法调用期间改变,那么在接下来的调用过程中,与Bean对应的客户的状态也变。
无状态会话Bean(非对话型)
只保留单一对话内容,它们没有状态是因为它们不与客户程序进行多方法对话。
如果一个Bean的一次对话只持续单一的方法调用,该Bean就叫无状态会话Bean。在每一个方法调用完之后,容器可能会选择销毁这个无状态会话Bean,或者重新生成一个,这样就消除了所有过去的调用相关信息。当然容器也可以选择保存实例,客户端可得用。无状态会话Bean并不保存方法之间状态。无状态会话Bean可以保持不与任何特定客户相关的状态。为了使无状态会话Bean对客户端程序有用,客户端必须将Bean需要的所有客户作为参数传递给商务逻辑方法。因为无状态会话Bean不保存任何对话状态,同一个无状态会话Bean类的实例都是相同的,这意味着任何无状态会话Bean可以为任何客户端程序请求服务,因它们是等同的,实际上每个方法调用中,无状态会话Bean可以存储在调度池内,被重用和在客户端程序之间交换。
4.3状态会话Bean的特征
4.3.1对状态会话Bean实现调度池调度
对于状态会话Bean来说,实现调度池调度就不像无状态会话Bean那么简单。
容器不能简单地调度Bean和将它们动态地分配给任意一个客户端程序方法请求,因为每一个Bean都存储一个特定客户状态。但仍然需要对状态会话Bean采取调度池调度,因为这样可节省资源和提升整个系统的可伸缩性。
上下文交换
EJB容器采用这个模式来保存状态会话Bean资源。为了限制会话Bean实例在内存中的数量,EJB容器将状态会话Bean交换出去,其对话状态保存在硬盘或其它存储器中,这种方法叫钝化。当钝化的Bean原先的客户端对其触发方法进行调用时,被钝化的对话状态重新交换给Bean,这叫做激活化。注意,接收激活的不一定是原先的Bean实例。但是这没有关系,因为新的Bean实例从原先的Bean实例钝化时的那一点重新开始对话。
钝化/活化,有可能导致I/O瓶颈。
EJB容器如何决定哪个Bean钝化/活化,这与EJB容器有关,常采用的一种钝化策略是最近最少使用策略。只要Bean没有被调用,钝化随时都可以发生,什么时候钝化完全由EJB容器决定。注意:参与事务处理的Bean只有等事务处理完成后,才能被钝化。
大多数EJB容器采取JUST-IN-TIME策略激活Bean。当用户请求时才发生。一般而言,钝化/活化对无状态会话Bean无用处,因此它可被EJB容器随意地从内存中清除。
4.3.2对话状态遵从的规则
更严格地讲,Bean的对话状态应遵从JAVA对象序列化所规定的原则。
如果满足下面两点的话,Bean的每一个成员变量都被认为是Bean对话状态的一部分:
1, 成员变量是非瞬变基本类型
2, 成员变量是非瞬变java对象
Bean还可能持有容器实现的对象的引用。容器必须在钝化/活化时保存以下内容:、
1, EJB对象的引用
2, HOME对象的引用
3, EJB上下文的引用
4, JNDI命名上下文
4.3.3钝化/活化回调方法
当EJB容器钝化BEAN时,它将BEAN的对话状态写辅助存储器,EJB容器通知Bean它将调用Bean必需的回调方法ejbPassivate() ,以执行钝化操作,ejbPassivate()方法事先告知Bean,它所保留的对话状态将被交换出去。EJB容器使用ejbPassivate()方法通知Bean,这一点很重要,它让Bean释放所占用的资源。一旦ejbPassivate()方法调用结束时,Bean必须处于可被钝化状态。
相反的过程发生在活化过程中。序列化的对话状态被读回内存,EJB容器使用对象序列化或类似方式重建内存状态。EJB容器接着调用Bean必需的ejbActivate()方法,此方法让Bean有机会恢复它在ejbPassivate()过程中所释放的资源。
除非你使用开放性资源,例如套接字连接和数据库连接,这些资源在激活后必须重新建立,你不用去关心ejbPassivate()的实现了,在大多数情况下,你不需要向这些方法中加入任何东西。
(家里部分)
SessionContext接口扩展EJBContext接口
对于会话Bean来说,当你的Bean要调用另外一个Bean和你的Bean传递一个引用进,方法getEJBObject()和getEJBLocalObject()方法是很有用的。在java中一个对象可以通过关键字this来获取其自身的引用,但在EJB中,一个Bean不能使用this并把它传递给其它Bean,因为所有的客户端程序都是通过Bean的EJB对象间接地调用Bean中的方法的。这样,Bean只能通过它的EJB对象来引用自身,而不是通过关键字this。
4.3.6会话Bean的生命周期图表
状态会话Bean的生命周期与无状态会话Bean的生命周期类似,但是两者又存在以下重要区别:
第一, 因为每个实例都包含状态,所以没有等价实例的调度池
第二, 存在钝化与活化的过渡
第三, 不要依赖于ejbRemove()
容器可以在任可时候调用ejbRemove(),就算容器认为Bean已经被清除了。注意,容器在即使在其崩溃时或重大异常发生时也可能永远不会调用Bean的ejbRemove()方法。
第五章 实体Bean介绍
实体Bean是能够存放在永久性存储空间中的持久性对象,这意味着你可以用实体Bean来对你的商务中的基础数据建模。
5.1持久性的概念
实体Bean是持久性对象。
Java对象序列化
一般来说,利用对象序列化来存储查询对象的代价很高,而且麻烦,对于大规模的应用,提交基于商务数据的查询是必要的,这使得简单的对象序列化不适于持久存储。
对象-关系型数据库映射
存储java对象的另一个常用方法是使用传统的关系型数据库。
与简单的对象序列化相比,对象-关系型数据库映射是一种复杂的持久对象机制。
对象数据库
对象数据库管理系统(ODBMS)是持久化存储器,保存着全部对象。这没有对象-关系型数据库映射层,因为java对象本身作为完整的对象被存储。因此你不需要针对关系型数据库API编程,而是针对对象数据库API进行编程。
对象查询语言(OQL)
对象数据库也有很好的性能和可扩展性。提供了非常强大的完整性与安全性。不过对象数据库产品还没有被行业充分地接受。
5.2什么是实体Bean
应用逻辑组件(会话Bean能很好地模型化这些应用逻辑组件)
持久数据组件(实体Bean就是这些持久组件)
为什么要把商务数据当做对象来处理,而不是处理数据库中的原始数据呢?答案是将数据视为对象很便利的,能方便地操作并管理。
你应把实体Bean想象成:
一个在内存中的持久数据的Java表现形式
能够知道如何从一个存储空间中读取它自已并用这些存储的数据组合成它的域
一个可以在内存中即时被修改的对象并且改变数据的值
可持久化,所以它可以再次被存回存储空间中,从而更新了数据库中的数据
实体Bean包含的文件:
包含所有EJB必包含的组件外,还有:‘
实体Bean类:映射一个数据模式中的一个实体定义,
实体Bean的主键类:使每个实体Bean都不同。一个主键是一个可能包含任意多个属性的对象。无论什么数据,唯一地标识一个实体Bean数据实例都是必须的。
5.3实体Bean的特征
服务器崩溃或者数据库崩溃都不会影响一个实体Bean的生存期。因为它是永久性的。
实体Bean实例是一个对应到数据库中的视图。
ejbLoad()从持久存储空间读入数据到实体Bean在内存的域中。
ejbStore()保存Bean实例的当前域到底层的数据存储空间。容器决定调用这两个方法。、
5.3.3几个实体Bean实例可能代表同一底层数据
允许多个客户端共享相同的实体Bean实例,但这对EJB不适合的,原因有两个:一是保证线程安全编码困难,二是多个执行的线程会使事务几乎不可能被底层的事务处理系统所控制,原因是EJB规定只有一个线程可以不断地运行在一个Bean实例当中。三种Bean都是单线程的。要求每一个Bean每次只服务于一个客户,这会引起瓶颈,为了提升性能,我们可以允许容器实例化同一个实体Bean类的多个实例。这将允许多个客户端并发地访问这些相互独立的实例,每个实例都代表同一个底层实全数据,多个Bean实例代表同一个数据,这又带来一个新问题:数据破坏。为了达到实体Bean实例缓存的一致性,每个实体Bean实例必须进行与底层存储空间例行同步,容器通过调用Bean的ejbLoad()和ejbStore()方法调用返回来同步Bean和底层的存储空间。Bean和底层存储空间同步频率由事务决定的。事务允许每个客户端的请求与所有其它请求相隔离。
5.3.4实体Bean实例可以被收集再利用
激活和挂起,当一个实体Bean实例被挂起,它要释放占用资源并将它的状态保存到底层存储空间中,因此容器会在Bean被挂起之前调用它的ejbStore()方法。同样地当一个实体Bean实例被激活,它不但要获得它所要的资源,还必要从数据库中加载最新数据。容器会在实体Bean被激活之后调用它的ejbLoad()方法。
ejbActivate()(激活方法)
ejbPassivate()(挂起方法)
5.3.5保持实体Bean的两种方法:
Bean管理的持久性
容器管理的持久性
5.3.6实体Bean的创建与删除
ejbCreate()
ejbRemove()
理解实体Bean是怎样被生成和销毁的
实体Bean的查找:
查询一个实体Bean类似于在SQL中执行一条select语句。会话Bean不能查找。
5.4实体上下文
第六章 编写Bean管理的持久性的实体Bean
扩展javax.ejb.EntityBean
其方法:
setEntityContext() 将一个Bean和环境信息联系起来
ejbFind…(…) 当Bean实例还在池中,查到Bean数据实例。至少必有一个ejbFindByPrimaryKey()方法
ejbHome…(…) Home方法,这些方法不与任何给定的数据实例(或行)相关,因为Home方法是在缓冲池中的Bean调用的,而且发生在Bena与任何的特定数据关联之前,所以它是一种特殊的方法。客户端通过Home接口或者本地Home接口调用Home方法。
ejbCreate(…)创建新的数据库数据并初始化你的Bean(如果你不想EJB客户羰能创建新的数据库数据,你可不写这个方法)
ejbPostCreate(…)对于每一个ejbCreate()方法,你的Bean类必须定义一个ejbPostCreate()方法,而且相同的参数。容器恰好在ejbCreate()方法之后调用ejbPostCreate()方法。
ejbActivate()激活
ejbLoad()加载数据库中的数据到Bean 实例中
ejbStore()将Bean实例中数据更新到数据库中
ejbPassivate()挂起
ejbRemove()删除数据库中的数据,它不是用于删除java对象的
unsetEntityContext()将Bean与环境分离。当你的实体Bean实例被删除之前容器调用这个方法
定位器方法的一些规则:
一, 都以ejbFind开头,
二, 必需有一个ejbFindByPrimaryKey()方法
三, 可以有多个不同定位器方法,每个都可有不同名称与参数。
四, 一个定位器方法必须返回它找到的实体Bean的主键,如果它找到多于一个,就返回一个主键集合
五, 与ejbCreate()方法一样,客户端不能在Bean实例自身上调用定位器方法。、
六, 实体Bean实例给容器返回一个主键。而Home对象返回一个EJB对象给客户端程序。
七, 除了强制性的前缀ejb和在Find中大写首字母外,Bean类签名与Home签名是相同的。
八, 当客户端程序调用Home对象的定位器方法时,Home对象让Bean找到所有符合客户端程序要求的主键。接着,Bean返回一个这些主键的集合给容器。
第六章:Bean管理持久性的实例
这个例子AccountBean类的代码为三部分:
Bean管理状态域
商务逻辑方法
EJB所必需的方法
6.4融会贯通:遍历BMP实体生命周期
理解容器与BMP实体Bean交互。
BMP实体Bean的生命周期:
第一, 不存在状态表示实体Bean还没有被初始化,
第二, 容器通过调用实体Bean类中的newInstance()方法,生成一个新的实例。这会调用你实体Bean的默认构造器,在内存中产生一个新的实例。下一步,容器使实体Bean和一个实体环境对象关联起来---完成这个任务要调用一个返回方法,setEntityContext(EntityContext ctx),只有在容器想要增加可用实体Bean实例池时,这上步才发生。
第三, 实体Bean和其它实体Bean存在于调度池中。这时,实体Bean并没有把任何实体Bean数据库中的数据加载进来,而且它也没有占用任何Bean特定的资源。
第四, 当客户端要创建一个新的数据库中的数据时,它在你的实体Bean的HOME对象上调用一个create方法,然后容器从调度池中取得一个实体Bean实例,并调用这个实例的ejbCreate()方法。
第五, 当Bean处于准备就绪状态时,它被绑定在特定的数据上,并因此绑定一个特定EJB对象上。
第六, 有两种方法把实体Bean扔回到调度池中。
第七章:编写容器管理的持久实体Bean
所有CMP实体Bean被分解为两个类:一个类是超类,由你编写,它包含实体Bean数据逻辑。另一个类是子类,由容器生成,它包含持久化逻辑。
7.1.2CMP实体Bean不包含声音字段
容器可能有一个位向量,它被用来跟踪实体Bean中被修改的字段,而这些字段要被写入存储介质中的。
你的Bean可能持有其它Bean的引用,容器必须要保持这些关系的引用完整。
get/set方法也是在子类中出现
超类中有这get/set方法的抽象方法
7.1.4CMP实体Bean有一个抽象的持久化模式
部署描述符中声明相关字段
CMP实体Bean拥有查询语言
EJB查询语言:EJB-QL是一种语法类似于SQL,面向对象,用于查询实体Bean的查询语言。它包含一个select从名,from从句一个可选的where从句。
7.1.6CMP实体Bean可以包含ejbSelect()方法:
是一个查询方法,Bean中作为一个辅助方法来访问数据库。ejbSelect方法并不通过远程接口或本地接口暴露给终端客户,它只能在Bean内部调用,要么从一个HOME方法,要么从一个商务方法中调用。它的价值在于以下三点:
第一, Select方法可以执行你的Bean所需要的细粒度数据库操作,但是你不要把它暴露给客户端。
第二, 它能从相关的其他实体Bean中提取数据,
第三, 像finder方法一样,select方法可以返回实体Bean。但是实体方法更加强大。
CMP和BMP之间主要差别在于如何Bean类和部署描述符的不同。远程接口,本地接口,Home接口,本地Home接口,主键类,基本上都是一样的,这意味着,在不改变客户程序情况下可以在CMP与BMP之间切换。
7.2实现容器管理持久性的指导原则
setEntityContext():与环境信息关联
ejbFind…(…):你不用为CMP编写定位器方法,
ejbCreate(…):创建新数据库中数据并初始化你的Bean
ejbPostCreate(…):
ejbActivate():
ejbLoad():
ejbStore():
ejbPassivate():
ejbRemove():
unsetEntityContext():
当容器解释EJB-QL时,它就生成数据库访问代码。
<![CDATA[SELECT OBJECT(a) FROM ProductBean AS a WHERE name = ?1]]>
CDATA,会告知XML的解释器略其中的文本。
Cmp不一定要定义主键类,而使用容器管理的一个域来作为主键类。
<primkey-field>productID</primkey-field>
但是应尽量避免使用域作为主键类,原因是主键类的封装器可以使你不必关心怎样在底层数据存储中惟一地表示自已。
第八章:消息驱动Bean
消息驱动Bean是一种通信轻型工具,能访问消息通道的特殊Bean。
在一些场合它比消息驱动Bean比RMI-IIOP更适合。
本章包括:
异步行为,面向消息中间件
JMS教程
消息驱动Bean功能
消息驱动Bean与实体Bean,会话Bean比较
如何开发消息驱动Bean
更高级的有关消息驱动Bean的主题
使用消息驱动Beanr的目的
RMI-IIOP的三个挑战:
性能
可靠性
支持多发送/接收
java消息服务(JMS)
MOM(Message-oriented middleware)
JMS两部分:API,SPI(plugin JMS Driver)JMS驱动程序知道如何同特定的MOM实现进行对话。
与JNDI,JDBC类同。
担保消息发送是如何工作的?
通过使用担保消息发送,面向消息中间件系统可以持久化您的消息到一个文本,数据库或者其它的存储介质中。
担保消息的一种变化形式是鉴定消息发送。鉴定消息发送不但可以保证从消息发生者到消息使用者的消息的发送成功,而且还会生成使用收条,此收条被发送到消息发生者,用来表示消息已经成功收到并使用。
担保消息发送的另一种变化形式是存储转发。储存转发可以使得消息发生者成功地发送消息到非活动MOM系统。
8.2.1消息机制的域
当使用消息机制时,要选择消息机制的域。域是为消息机制所起的富有想像力的名称,有如下几种类型的域:
发布/订阅方式(pub/sub)(类似于看电视):是分布式事件驱动处理模型的实现。
点到点方式(类似于打电话):
请求/应答方式(类似于RMI-IIOP):
8.2.2JAVA消息服务API
JAVA消息服务API比RMI-IIOP更加复杂,
javax.jms
javax.mail
javax.mail.event
javax.mail.internet
javax.mail.search
Java消息服务编程模型:
1,定位java消息服务驱动程序 (用JNDI完成)
2,创建java消息服务连接
3,创建java消息服务会话
4,定位java消息服务目的地
5,创建java消息服务发生者/java消息服务使用者
5, 发送/接收消息
消息驱动Bean实际上是作为我们的消息使用者的。
单线程Bean与多线程Bean的比较:
EJB一个好处就是你不需要编写线程安全的代码。你可以作为单线程来设计你的EJB,并不用担心并发客户访问你的组件时的线程问题。EJB容器会自动实例化你的组件的多个实例来对并发的请求提供服务。
EJB规范不允许多线程Bean。
使用线程的一种替代的方法是使用事务消息API,如java消息务服务。这样会允许分布式对象环境中异步方式。Java消息服务可以使你安全并可靠地实现多任务,而不会出现Bean本身同线程相混乱的程况。
8.3java消息服务同EJB集成:
消息驱动Bean:是能够接收JMS消息的特殊的EJB组件,消息驱动Bean使用来自队列或主题的消息,这些消息可以是由任意有效的JMS客户发送的。消息驱动Bean从任意的发送消息给它的客户中分离。客户不能通过组件接口来访问消息驱动Bean。Java消息服务是用来发送消息到消息驱动Bean的API。
消息驱动Bean主要特点:
1, 没有主接口,本地主接口,远程接口,或本地接口
2, 具有单个弱类型的商务方法。消息驱动Bean仅仅能接收来自java消息服务目的地的消息。此方法叫做onMessage()。你不能提供多种不同的消息驱动Bean的商务方法。
3, 不具有任何返回值。这是因为消息驱动Bean同消息发生者分离,消息发生者不会等你的消息驱动Bean来响应,因为它持续处理发送的消息。
4, 不能够发送异常给客户。这是因为消息发生者不会等你的消息驱动Bean来接收消息。实际上EJB规范禁止消息驱动Bean抛出应用异常。但可生成系统异常,容器处理系统异常。
5, 是无状态的。
6, 可以是持久的也可以是非持久的订阅者。对主题持久的订阅意味着java消息服务订阅者接收所有消息,就算在订阅者为非活动状态的情况下。而对主题的非持久的订阅意味着订阅者仅仅能接收订阅活动时所发布的信息。
8.4开发消息驱动Bean
实现两个接口类,分别为:
javax.jms.messageListener
javax.ejb.MessageDrivenBean
每一个消息驱动Bean类必须提供一个ejbCreate()方法,返回void,并不接收任何参数。
消息驱动Bean生命周期:
要么处于“不存在”状态,要么处于“组合”状态。
方法介绍:
onMessage(Message)为Bean所有使用的每一条消息调用此方法,此方法的参数是被使用的引入消息。
ejbCreate()当消息驱动Bean第一次被创建并被加入到Bean池中时调用此方法。
ejbRemove()
setMessageDrivenContext(MessageDrivenContext ctx)
例子
高级概念
事务:
消息驱动Bean不会和发送消息的消息发生者运行在同一个事务中,因为通常有两个事务与每一个持久的JMS消息相联系。
安全性
消息驱动Bean不会接收发送消息的消息发生者的安全性标识,因为没有标准的方法来安全性信息加到JMS消息中。因此你不能使用消息驱动Bean执行EJB安全性操作。
负载平衡:
消息驱动Bean的一个特点是有理想的复杂平衡范例。
在群集中的多重消息使用:
难点
第九章:为Bean增加功能
9.1.1从其它的Bean调用Bean
为了使你的Bean调用其它Bean,你需要完成所有客户端程序要完成的一系列操作。你可能需要:
第一, 调用JNDI查找其他Bean的Home对象
第二, 调用Home对象的create()方法
第三, 调用EJB对象的商务方法
第四, 调用EJB对象的remove()方法
首先要提供JNDI初始化参数,JNDI驱动程序,它在不同容器之间是不同的。Bean应是与容器无关的,在Bean中写入有关JNDI的代码会破坏可移植性。幸好,你从一个Bean查找另一个Bean,不需要提供任何JNDI初始化参数。你只需要获得默认的JNDI初始化上下文环境。容器在你的Bean运行之前设置默认的JNDI初始化上下文环境。
9.1.2理解EJB引用:
EJB引用是你用来查找Bean的JNDI位置的别名。这个别名也许不与部署员部署Bean所用到的JNDI位置相对应。程序代码通过别名来查找Home,然后部署员将这个别名与他所选定的JNDI位置绑定在一起。
9.2资源库
如何通过EJB组件来执行对外部资源的调用。资源库是一个资源的提供者,如JMS驱动程序和JDBC驱动程序或JCA资源适配器。资源库是给你提供连接驱动程序的。
连接收集再利用:
连接收集再利用是对Scoket的利用。这增加了系统的可扩展性。连接收集再利用是内建于大多数容器中的。Jdbc为连接收集再利用指定了标准接口。这些完全是幕后发生的,与你Bean中代码无关。
要开始使用一个资源库,首先要定位它。EJB规定用JNDI来查找资源库。这很有用,你只要学习一个JNDI API,就可以查找所有驱动程序(JMS,JDBC,JCA等)。另外这些资源可能要授权,EJB规范提供了两种验证自我的方法:
一,在你的Bean程序代码中自行执行验证(res-auth元素设为Application)
二,让部署员为你处理身份的验证(res-auth元素设为Container)
9.3环境属性:
怎样在运行期定制你的Bean?
Bean的环境属性是在运行时间内Bean读取的特定应用程序属性。这些属性可用来定制你的Bean并使你的Bean成为数据驱动的Bean。这是一种相对于数据库中存储数据快速而简便的方法。
使用环境属性的第一步是在部署描述符中声明它们。容器读取这个部署描述,让你的Bean在运行期间能访问这个环境属性。
9.4理解EJB安全性:
为EJB系统增加安全性,客户端必须通过两个安全措施:
第一, 客户端必须通过验证(验证身份,EJB调用方法之前)
第二, 客户端必须通过授权。(获得通过验证的用户是否允许某项操作,发生在EJB方法调用期间)
验证:
在EJB1.1之前,验证不是可移植的,与容器相关。在ejb2.0之后,验证变得健壮并可移植。你可通过一个j2ee中的单独的API-java验证和授权服务(JAAS)来完成验证。
JAAS概描:
JAAS是一个能使你在JAVA中验证用户和给用户授权的可移植性接口。简而言之它能使你进入一个系统而不要知道底层是采用什么安全系统的。JAAS的强大之处在于它能使用几乎所有的安全系统。
你在使用JAAS时,有两种可能的情况:
第一, 当你拥有一个与远程EJB系统连接的单独的应用系统时,用户将向应用系统提供证明身份的信息。
第二, 当你拥有一个连接到Servlet/JSP层的基于Web浏览器的客户端程序时,基于web浏览器的用户将向Servlet/JSP层提供证明身份的信息。
Web浏览器可用如下四种方式之一来提供证明身份信息:
1, 基本验证(不是一种安全的方式)
2, 基于表格的验证(类似于基本验证)
3, 摘要验证(web客户端应用程序向web服务器提供一个特殊的消息摘要)
4, 证书验证
JAAS体系结构
授权
安全性的传播
9.5理解EJB对象句柄
第三部分:高级EJB概念:
10.4事务在EJB组件中的应用
本质上讲,EJB组件可以使用事务。
10.4.1后台事务系统的抽象分离
在EJB中你的代码不会直接受到底层事务系统影响,你的EJB组件也不会与事务管理器,资源管理器直接发生关系。你开发的应用程序代码时并不关心处于底层的后台事务系统,底层事务系统抽象分离于运行在后台的EJB容器。
10.4.2声明型事务,编程型事务和客户端初始化事务
划分事务边界。
EJB有两种划分事务边界的方法:
编程型
声明型
编程型事务
大多数现有系统都使用编程型事务来划分事务边界。这种方法,你必要将事务的逻辑操作编写入你的应用程序代码中。你必须负责发布一个事务开始的声明和一个提交或异常结束的声明。
声明型事务
声明型事务允许组件自动地参与到事务中去。就是你的EJB组件不会发布事务开始,提交或异常结束的声明,而是由EJB容器来为你做这件事。这是很有价值的,因为Bean组件不需要接触事务API。在部署描述符中指定以哪一种方式加入事务,<transaction-type>(Container/Bean)。
客户端初始的事务:
执行事务的最后一个途径是在你的Bean之外,从客户端编写代码来开始和结束事务。客户端程序调用企业级Bean仍然需要通过编写代码来使用编程方式或声明方式控制事务。
10.4.3选择事务的类型
事务与实体Bean
Bean管理的事务对于实体Bean是不合适的。实体Bean必须使用声明方式的事务。
而会话Bean和消息驱动Bean可以使用Bean管理的事务。
编程方式控制事务的好处是Bean可以完全控制事务边界。相比之下,如果以声明方式或客户端初始化方式控制事务的话,你的Bean只能要么运行在一个事务当中,要么不运行在一个事务中。声明方式控制事务的好处在于它们比较简单。而且不要改动源码就可对事务进行优化。
10.5容器管理的事务
指示容器怎样去执行一个事务
事务属性就是Bean组件特有的一种设定,这设定可以控制你的Bean组件加入事务的方式。事务属性是Bean部署描述符中必不可少的部分。
事务与消息驱动Bean
消息驱动Bean,事务类型的选择对其影响很大。
若使用容器管理的事务,消息驱动Bean将在它执行商务逻辑的同时在同一事务中从目的地读取消息,如果出现了问题,事务将执行恢复,而且将出现消息确认。如果是Bean管理的事务,在消息驱动Bean接收到消息后,事务将分别开始和结束,然后你可以使用部署描述符确认模式来通知容器对消息进行确认的时间。如果你根本不支持事务,容器将在稍后的一个时间确认消息。
若选择Bean管理事务,当出现问题之后,它不能保证将消息指向原来的目的地,因为Bean没有办法指出发生的问题。对于消息驱动Bean我们推荐使用容器管理的事务。
你必须为Bean中所有商务方法设置事务属性。
另外,对于实体Bean你必须为HOME接口方法设置事务属性,因为HOME接口中的创建方法在数据库中插入数据,而这个操作必须是事务的。
事务的属性:
每一个EJB组件都必须有一个事务的属性设定。下面列出部署描述中事务的属性:
Required如果希望Bean始终运行在事务中,选它。
RequiresNew如果当Bean组件被调用,你希望开始一个新的事务,使用它。
Support它只运行在一个事务当中,当已运行一个事务,只是加入,当没有事务时,开始一个新的事务
Mandatory要求当你的Bean组件被调用时,事务必须已经被运行。否则返回一个javax.ejb.TransactionRequired异常。Mandatory是一个安全属性。它保证了你的Bean必运行在事务中。若没有正在运行的事务,任何方法都不能调用你的Bean组件。
NotSupported你的Bean组件不能运行于事务中。
Never也意味着你的Bean不能运行于事务当中。
注意:
实体Bean和带有SessionSynchronization的状态会话Bean必须使用事务,因为它们都必是事务性的,你不能对他们使用:Never,NotSupport,Supports属性,若你这样做,则其将是不可移植的。另外处理客户端程序事务的属性对于消息驱动Bean来说将是没有意义的,这些属性包括:Never,Supports,RequiresNew,Mandatory。
10.6EJB中的编程型事务
相比之下,编程型事务允许更高级的事务控制,但它们却不容易使用。为了自已控制事务边界,你必须使用java事务API(JTA)。
10.6.1CORBA的对象事务处理服务(OTS)
OTS服务就是一系列格式规范的接口,这些接口指明了事务将如何在后台运行,并且使用事务管理者,资源管理者和事务对象互相协作。OTS分为两部分:CosTransactions和CosTSPortability。
CosTransactions接口是一种基本接口,通过这个接口,事务对象/组件,资源管理者和事务管理者可以共同操作。这些接口保证了上述参与者可以任意组合。
CosTSPortability接口是为多参与者执行事务提供了一种可移植方式。
OTS的内部机制与EJB组件的开发一点都不相关。作为EJB程序员,不用关心底层事务服务,不必理解复杂的中间件API。EJB使你不用接触事务服务,如OTS。
10.6.2java事务处理服务(JTS)
只有系统开发商才需要了解OTS的内部机制。但它对你却很有用,所以SUN将OTS分为:JTS(Java Transaction Service)与JTA(Java Transaction API)
JTS就是为系统级开发商设计的CORBA OTS 的JAVA 映射。JTS为后台的事务管理者和资源管理者定义了一个接口。通过使用这个接口,不同开发商的产品可以共同操作。它还对事务管理者和资历源管理周边的对象和使用对象进行了定义。作为应用程序开发员不必关心大多数OTS,包括JTS。你只要关心允许你通过编程控制事务边界的JTA。
10.6.3 JTA
JTA就是被组件和应用程序开发员所使用的一种事务处理API。你可在客户代码或Bean组件代码中使用JTA通过编程方式控制事务的边界。
JTS包括两种接口:
一种是基于X/Open XA 资源管理者的
另一种是用于支持事务的编程控制的(javax.transactionUserTransaction)。
10.6.4声明型事务和编程型事务的应用范例比较
放弃事务:
放弃事务意味着强制一个事务放弃其动作,当出现问题时,你就需要结束一个事务,这些问题可能是数据库无法连接或者客户端传输了错误的参数。
可心调用rollback()放弃一个事务,但你怎样放弃你参与到其中但却是别人启动的一个事务呢?
有两种性况:
第一,你的事务参与者是一个使用声明型事务的EJB组件:调用EJB Context对象的setRollBackOnly()方法。
第二,你的事务参与者不是一个EJB组件,比如说是一个JAVA对象:可通过查找JRA并且调用JTA的setRollbackOnly()方法来放弃一个事务。
10.7如何使用客户代码控制事务:
控制事务的最后一种方式就是客户端代码。你可在调用Bean组件的客户端代码中使用JTA。要想从客户端代码中控制事务, 你必须通过JAVA命名和目录接口(JNDI)来访问JTA UserTranaction接口。你应尽可能将事务保持在很短的周期内,较长周期的事务会引起多用户操作的中断。若是你要一个长周期的事务,你应使用分布式锁处理机制,例如CORBA锁服务,不幸的是,J2EE中并没有类似分布式的锁服务.
10.8事务的隔离
隔离性能够保证并发用户彼此相互隔离.就算它们对同一数据库时行操作.底层事务系统通过后台运行并发控制来实现隔离性.
10.8.1并发控制的需求:
加锁.
隔离性与锁:
性能问题
死锁问题
为提高性能,事务将锁分为两个主要类型:读取锁(非独占型的)和写入锁(独占型的)
隔离性与EJB的理论:.
作为EJB开发者,你需要控制事务与另一个事务相互隔离的程度(可严可松的隔离).EJB为你提供了不同的隔离级来适应不同的需要.隔离级允许你在不关心底层细节的情况下指定并发控制.
隔离级分四种:
READ_UNCOMMITTED模式:不保证任何隔离性
READ_COMMITTED模式:可解决不当读取问题
REPEATABLE_READ模式:可以解决不可重复读取问题
SERIALIZABLE模式:可以解决幻影读取问题
不当读取问题:当你的应用程序从还没有提交永久性更新的数据库中读取数据时,就会产生不当读取问题
何时使用READ_COMMITTED模式:用这模式,你无法读取那些已经写入但没被提交的数据,这意味着你读取的任何数据都是一致性的数据。
这种模式主要用于从数据库中读取数据并形成数据值报表的程序中。这是大多数数据库默认的隔离级。
不可重复读取问题:
当一个组件从数据库中读取数据时,数据发生了变化,这时就会产生不可重复读取问题。其原因可能是另一个并发事务修改了你的正在读取的数据。
何时用REPEARABLE_READ模式:
无论你什么时候在数据库中读取已提交的数据,你都可以在以后重新读取此数据,并且数据的值与第一次读取相同。因此你的数据库是可重复读取的。当你要更新资源中一个或多个数据项时,就使用这个模式。你希望能够读取每一个正在修改的数据行并更新它们,而且知道此时这些数据行不会被其它事务所修改。
幻影读取问题:
是指两次数据库读取操作之间,一组新的数据会在数据库中出现。不可重复读取问题与幻影问题的区别在于:现存的数据被改变时所发生的是不可重复读取的数据,而插入新的数据时所发生的是幻影读取问题。
何时使用SERIALIZABLE模式:
此模式保证了事务互不干扰地连续执行,并在整个事务过程中强迫执行ACID属性中的隔离性。这意味着每个事务将真正地隔离于其它事务。在必须具有完全的事务隔离的关键任务系统中,将会用这一模式。这将保证你不会读取没提交的数据。
隔离级越高,性能越慢。
10.8.7隔离性与EJB
怎样在一个EJB环境中建立隔离
一, 如果你是Bean管理事务,则可用资源管理器API指定隔离级别。
二, 如果是容器管理事务,无法在部署描述符中指定隔离级,要么使用资源管理器API,要么依赖容器工具或者数据库工具来指定隔离级别。
隔离的可移植性问题:
没有一种可移植的方式来为容器管理事务的Bean指定隔离级别的办法,你要依赖于容器或数据库。
10.8.8限制式和开放式并发控制
EJB所遵循的两种基本的对象并发控制策略是限制式和开放式。
限制式需要在事务其间对数据上锁以保证没有其它人对数据进行修改。适于小规模系统。可扩展性差
开放式不对数据上锁,当数据库冲突时就rollback。适用于大型系统。
10.9分布式事务
跨越多层的有多个事务加入的事务集。分布式平面事务允许多个由不同开发商编写的应用服务器在同一个事务中进行合作。
10.9.1稳定性与两阶段提交协议
事务分两阶段执行:
阶段一,所有资源的更新都写入事务日志。
阶段二,执行真正更新。
事务被分成两个阶段来完成被叫做两阶段提交协议(2PC)。它允许多个事务管理者和资源管理者参与到一个事务中。
10.9.2事务的通信协议和事务上下文
事务上下文就是一个保存了系统当前事务状态的对象。EJB规范并不支持这个级别上的互操作性,来自不同供应商服务器不能保证协同工作。
因2PC性能很差,大多数组织很少与两个不同的供应商打交道。
10.10在EJB中设计事务对话
终止商务过程
发表评论
-
Cookie跨域 cas
2011-10-27 17:30 1722正常的cookie只能在一个应用中共享,即一个cookie只能 ... -
JQuery中$.ajax()方法参数详解
2011-05-25 13:05 1657url: 要求为String类型的参数,(默认为当前页地址)发 ... -
jquery刷新页面
2011-04-27 23:51 956jquery刷新页面 局部刷新: 这个方法就多了去了,常见 ... -
spring MVC
2011-04-27 23:50 1515需要的JAR包有: spring2.jar cglib-nod ... -
Java hascode
2011-04-10 17:47 819java hascode Java中有两类集合(Colle ... -
spring原理
2011-04-10 00:03 8271、spring原理 s ... -
hibernate的缓存
2011-03-31 14:34 854缓存是介于应用程序和 ... -
Spring AOP之Hello World
2011-03-30 11:36 1007我们使用一个简单的例子来演示一下Spring中的AOP,这是一 ... -
数字推理题规律汇总
2011-03-29 16:48 1043□ 等差数列及其变式 【例题1】2,5,8,() A ... -
freemarker的模板标签获取
2011-03-28 13:23 1734In FreeMarker 2.2, Template has ... -
StringUtils函数全集
2011-01-13 16:45 1278StringUtils函数全集 Strin ... -
jquery+json+servlet
2011-01-11 13:54 5344jquery+json小例子 使用jquery发送请求到s ... -
java - 删除文件
2010-12-30 13:32 1112java删除文件 package IO.file; impo ... -
jquery 赋值函数
2010-12-28 11:14 878$("")是一个jquery对象,而不是一 ... -
jQuery的鼠标事件
2010-12-28 11:13 1941鼠标事件是在用户移动鼠标光标或者使用任意鼠标键点击时触发的。 ... -
获取鼠标在图片对象上的位置
2010-12-27 21:40 1193<!DOCTYPE HTML PUBLIC " ... -
window.opener 与 window.parent 的区别
2010-11-21 22:57 1023我们如果要用到iframe的值传到另一框架就要用到 windo ... -
几个常用代码在IE8和火狐下的对比
2010-11-19 14:44 9751、Input 有的浏览 ... -
window.open()运用
2010-11-18 17:24 1032window.open()支持环境: JavaScript1. ... -
java 环境变量
2010-05-06 10:34 2504电脑属性高级 > 环境变量 > 系统变量 > ...
相关推荐
### 实战EJB知识点解析 #### 一、企业JavaBeans (EJB) 技术概览 **什么是企业JavaBeans技术?** 企业JavaBeans (EJB) 是Java平台上的服务器端组件模型,专为构建可扩展、可靠且跨平台的企业级应用程序而设计。...
**EJB3(Enterprise JavaBeans 3)是Java EE(Enterprise Edition)平台中用于构建企业级应用程序的重要组件模型。这个PPT教程详细介绍了EJB3的各种核心概念和技术,旨在帮助学习者掌握EJB3的核心特性并能实际应用到...
javax.ejb.AccessLocalException.class javax.ejb.CreateException.class javax.ejb.DuplicateKeyException.class javax.ejb.EJBContext.class javax.ejb.EJBException.class javax.ejb.EJBHome.class javax.ejb....
【标题】"Idea搭建EJB架构Demo项目源代码"涉及的是使用IntelliJ IDEA(简称Idea)这个强大的Java集成开发环境来构建一个基于EJB(Enterprise JavaBeans)架构的示例项目。EJB是Java EE(企业版)平台的核心部分,...
Files contained in javax.ejb.jar: META-INF/MANIFEST.MF javax.ejb.AccessLocalException.class javax.ejb.AccessTimeout.class javax.ejb.ActivationConfigProperty.class javax.ejb.AfterBegin.class javax....
EJB中ejb-jar文件配置详解 EJB(Enterprise JavaBean)是一种Java技术,用于开发企业级应用程序。EJB容器提供了许多功能,如事务处理、安全认证、资源管理等,以便开发者更方便地开发企业级应用程序。在EJB中,ejb-...
EJB(Enterprise JavaBeans)是Java企业级应用开发的核心组件之一,主要用于构建可复用、安全和事务处理的服务器端应用程序。本实例将探讨EJB的配置、部署和打包过程,帮助你深入理解如何在实际项目中运用这些技术。...
【实战角度比较EJB2和EJB3的架构异同】 EJB,即Enterprise JavaBeans,是Java EE(企业版Java)平台的核心组件之一,用于构建可复用、分布式的服务器端应用程序。EJB2和EJB3是EJB技术的两个主要版本,它们在架构上...
在Java企业版(Java EE)应用开发中,EJB(Enterprise JavaBeans)是核心组件,用于构建可扩展、安全和事务处理的服务器端应用程序。JBoss AS(现在称为WildFly)是一个开源的应用服务器,它支持Java EE规范,包括...
META-INF / maven / org.glassfish.main.ejb / javax.ejb / pom.properties META-INF / maven / org.glassfish.main.ejb / javax.ejb / pom.xml javax.ejb.AccessLocalException.class javax.ejb.AccessTimeout....
### EJB技术详解 #### EJB 2.0与EJB 1.1的主要区别及其应用场景 EJB(Enterprise JavaBeans)技术自1998年首次推出以来,经历了多个版本的演进,其中EJB 2.0是EJB 1.1的重要升级版,带来了诸多改进和新特性,旨在...
EJB(Enterprise JavaBeans)3.0是Java企业级应用开发的一个重要版本,它极大地简化了EJB的使用,降低了开发复杂性,并引入了许多新特性。在这个“ejb3.0写的登陆应用”中,我们可以深入探讨EJB 3.0在实现登录应用中...
### EJB2.0与EJB3.0的主要区别 #### 一、简介 企业Java Beans(EJB)是Java平台为企业级应用提供的一种组件模型。随着技术的发展,EJB经历了多个版本的迭代,其中EJB 2.0和EJB 3.0是两个重要的里程碑版本。本文将...
使用原始的servlet操作熟悉EJB的实体管理。 本实例主要功能:实现对员工、角色、账号、部门的关系管理。 本实例的实体设计:部门-员工:一对多。员工-账号:一对一。账号-角色:一对一。 主要采用EJB进行会话管理。...
EJB(Enterprise JavaBeans)是Java EE(Enterprise Java Platform)平台的一部分,主要用于构建分布式、事务处理、多客户端支持以及安全的后端企业级应用。EJB3.0是EJB规范的一个重要版本,它引入了许多简化开发的...
【EJB计算个人所得税】 企业级JavaBean(Enterprise JavaBeans,简称EJB)是Java平台上的一个核心组件,用于构建可扩展、安全且事务管理的分布式应用程序。在本项目"计算个人所得税"中,EJB被用作后端服务,处理...
EJB集群是EJB技术的一个重要特性,它允许EJB容器(如JBOSS)在多台服务器上分布和复制EJB实例,以实现高可用性和负载均衡。 在给定的示例中,我们看到一个简单的无状态会话Bean(Stateless Session Bean)`...
### EJB原理图详解 #### 一、EJB工作原理概览 EJB(Enterprise JavaBeans)是Java EE平台中的一个重要组成部分,它主要用于构建企业级应用。EJB提供了一种面向服务的方式,允许开发者专注于业务逻辑,而将复杂的...