前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >EJB学习一

EJB学习一

作者头像
全栈程序员站长
发布2022-09-27 13:17:01
6950
发布2022-09-27 13:17:01
举报

大家好,又见面了,我是你们的朋友全栈君。

一、一个企业级Bean是由几个文件共同组成: 1、Bean类 SessionBean实现javax.ejb.SessionBean接口; EntityBean实现javax.ejb.EntityBean接口。

2、EJB接口(远程接口或者本地接口)和EJB对象 远程接口继承javax.ejb.EJBObject接口; 本地接口继承javax.ejb.EJBLocalObject接口。

3、Home接口(远程接口或者本地接口)和Home对象 远程接口继承javax.ejb.EJBHome接口; 本地接口继承javax.ejb.EJBLocalHome接口。

4、部署描述文件

5、供应商特有文件

二、企业级Bean的调用: Bean的客户端不直接调用Bean类实例本身,而是通过EJB对象来调用。所以EJB对象必须知道Bean类公开的每个商务方法。 EJB对象就是实现了EJB接口的对象,由容器或容器供应商提供的工具自动生成。

三、客户端如何获得EJB对象的引用: EJB对象的引用通过Home对象来得到。Home对象就是实现了Home接口的对象,也是由EJB容器自动生成。

四、部署描述文件 在部署描述文件中声明对中间件服务的要求,EJB容器检查部署描述符,并完成要求: 1、Bean的管理和生命周期 2、持久性要求(仅限实体Bean) 3、事务处理要求 4、安全性要求 部署描述文件是一个xml文件。

五、供应商特有文件 每个EJB服务器供应商都不尽相同,他们各自都有一些独特的增值特性。 举例: <jboss> <enterprise-beans> <session> <ejb-name>Hello</ejb-name> <jndi-name>Hello</jndi-name> <local-jndi-name>HelloLocal</local-jndi-name> </session> </enterprise-beans> </jboss>

六、客户端调用EJB的步骤: 1、通过JNDI查找EJB对象的位置; 2、调用Home对象的create()方法创建EJB对象; 3、调用EJB对象的商务方法; 4、调用EJB对象的remove()方法。

说明:客户端调用EJB一般使用远程调用,因为WEB服务器和EJB服务器可能位于两台机器; EJB调用EJB一般使用本地调用,因为它们通常都位于同一个EJB容器内。

七、客户端调用EJB代码举例: 1、远程调用例子: public class HelloTestClient1 extends Object { public static void main(String[] args) {

HelloHome helloHome = null; Hello hello = null; java.util.Hashtable JNDIParm = new java.util.Hashtable(); JNDIParm.put(Context.PROVIDER_URL, “localhost”); JNDIParm.put(Context.INITIAL_CONTEXT_FACTORY,”org.jnp.interfaces.NamingContextFactory”); try { javax.naming.Context ctx = new InitialContext(JNDIParm); Object ref = ctx.lookup(“Hello”);

//创建Home对象 helloHome = (HelloHome) PortableRemoteObject.narrow(ref, HelloHome.class); //创建EJB对象 hello = helloHome.create(); //调用EJB对象的商务方法 System.out.println(hello.hello()); //EJB对象使用完毕后,要从内存中将它清除 hello.remove(); } catch (Exception ex) { System.out.println(ex); } } }

2、本地调用例子: //通过调用无参数的构造函数,获得默认的初始化上下文 javax.naming.Context ctx = new InitialContext();

Object ref = ctx.lookup(“java:comp/env/ejb/LocalUser”); //创建Home对象 localUserHome = (LocalUserHome) PortableRemoteObject.narrow(ref, LocalUserHome.class); //创建EJB对象 localUser = localUserHome.create(); System.out.println(localUser.hello()); //EJB使用完毕后,要从内存中将它清除 localUser.remove(); . . . 说明:本地调用必须将下面的内容添加到ejb-jar.xml的部署描述符的 session 元素中,如下所示: <session>

… <ejb-local-ref> <ejb-ref-name>ejb/LocalUser</ejb-ref-name> <ejb-ref-type>Entity</ejb-ref-type> <local-home>com.rickhightower.auth.LocalUserHome</local-home> <local>com.rickhightower.auth.LocalUser</local> <ejb-link>userEntity.jar#UserBean</ejb-link> </ejb-local-ref> … 请注意 ejb-local-ref 定义了对 UserBean 的引用。 八、有状态的session bean 1、一个有状态的session bean始终和一个客户相联系,在众多的方法调用过程中,这个实例代表的客户都保持一定的状态。 有状态的session bean类的实例总是同一个对象联系在一起,并同该对象绑定在一起用来指明一个确切的客户。 虽然web应用定义了http会话的概念,可以将一个业务的处理流程直接嵌入web应用的实现中,但是将业务处理封装在一个会话bean中将更加合适。

2、有状态的session bean的“激活”和“钝化” 容器如果按照有状态会话Bean的设想来实现的话。那么有限的资源如:内存、数据库连接等就会被耗费很多。 容器使用“激活”和“钝化”的方法来解决这一矛盾。

九、实体EJB 1、实体Bean是能够存放在永久性存储空间中的持久对象。这样我们就可以使用实体Bean来对商务中的数据进行建模。

2、一个实体Bean类可以映射一个关系型表的定义。这个类的一个实体将会映射那个表中的一行。实体Bean类提供一些访问数据和操作数据的简单方法。

3、实体Bean的主键类 EJB通过让实体Bean包含一个主键类,提供了定义您的唯一标识的灵活性。主键对象的属性没有必要和持久化主键数据完全一致。 主键类必须是可以序列化的(实现java.io.Serializable接口)。

4、并发访问问题 EJB规定只有一个线程可以不断的运行在一个Bean实例当中。会话Bean、实体Bean都是单线程的。 对于多客户端访问同一数据,容器实例化同一个实体Bean类的多个实例,每个实例都代表同一个底层实体数据。 容器根据事务来在适当的时候调用ejbLoad()和ejbStore()方法。同步数据。 从客户端的角度,它认为它在处理单个的实体Bean的实例。

十、从连接池获得JDBC连接 public Connection getConnection() throws Exception { try {

Context ctx = new InitialContext(); DataSource ds = (DataSource) ctx.lookup(“java:/MySQLDB”); return ds.getConnection(); } catch (Exception e) { System.out.println(“没有取得数据源”); e.printStackTrace(); throw e; } }

十一、容器管理的持久实体Bean(CMP) 1、用容器管理的持久化,不用再在实体Bean自身中实现任何持久逻辑(如,JDBC/SQL),而是由容器为您执行存储空间的操作。

2、数据库无关的Bean 如果我们要开发一个可重用的组件,我们很可能不知道Bean的使用者将要使用什么样的数据库存储。在CMP中,实体Bean和它的持久化表现完全分开。

3、容器的作用 不能在CMP实体Bean中编写任何JDBC和其他持久化逻辑。容器通过继承实体Bean类来生成JDBC代码。

4、所有的CMP实体Bean类被分解为两个类:一个类是超类,这个类需要自己编写,它包含实体Bean的数据逻辑。 另外一个是子类,这个类由容器生成,它包含持久化逻辑。所以实际的CMP实体Bean类是一个超类和一个子类的组合。

十二、EJB-QL 1、EJB-QL是一种语法类似于SQL、面向对象、用于查询实体Bean的查询语言。 举例: SELECT OBJECT(a) FROM Product AS a WHERE a.name = ?

十三、开发一个CMP的步骤 1、构建CMP实体Bean类

2、设计抽象持久化模型(关于持久化的部署描述,称为“抽象持久化模式”)

3、编写EJB-QL

十四、实体Bean 的增、删、改、查 1、新增 如下所示: LocalUser user = userHome.create(email, password); 提示:我们并没有在 home 接口中定义新增方法,该方法是从 javax.ejb.EJBLocalHome 接口继承的,由 EJB 容器实现。

2、删除 如下所示: userHome.remove(email); 由于电子邮件地址是主键,因此它可以用来唯一地标识实体,用 home 接口的删除方法来删除它。 提示:我们并没有在 home 接口中定义删除方法,该方法是从 javax.ejb.EJBLocalHome 接口继承的,由 EJB 容器实现。

3、修改 如下所示: LocalUser user = userHome.findByPrimaryKey(email); user.setName(“SWANGOOSE”); 使用 LocalUserHome 的 findByPrimaryKey() 方法来查找与 email 主键相关联的 UserBean 实例,然后修改。

4、查询 有了 EJB 2.0 CMP,您只需使用 EJB-QL 在部署描述符中定义查找程序方法的定义。 您仍然还必须在 home 接口中声明这个查找程序方法。 请注意查找程序方法 public Collection findAll() throws FinderException 是在 home 中声明的。 举例如下: public interface LocalUserHome extends EJBLocalHome { public Collection findAll() throws FinderException; } <entity> <display-name>UserBean</display-name> <ejb-name>UserBean</ejb-name>

<query> <description></description> <query-method> <method-name>findAll</method-name> <method-params /> </query-method> <ejb-ql> <![CDATA[select Object(theUser) from UserBean as theUser]]> </ejb-ql> </query>

</entity>

十五、使用简单的EJB-QL命令 1、简单查询许多实体 例如:为了返回系统中所有的 Group,您要使用下列 EJB-QL: SELECT OBJECT(g) FROM UserGroup g 您将模式名用于 abstract-schema-name 元素定义的实体 bean,而不是用 FROM 子句中的表或视图。

为了定义 findAll() 方法,您要做以下的工作: 1、1 在 home 接口中定义一个 findAll() 方法; 1、2 为查找程序定义包含 EJB-QL 的查询元素。

返回多个实体的 findAll() 查找程序方法看上去就像这样: public Collection findAll() throws javax.ejb.FinderException;

请注意,返回多个实体的查找程序方法必须返回 java.util.Collection 或 java.util.Set。 (确保返回 java.util.Set 的查找程序方法在 Set 中仅返回一次实体。)还要注意,必须声明所有的查找程序方法都抛出 javax.ejb.FinderException。

query 元素由 query-method、result-type-mapping 和 ejb-ql 元素组成,如下所示:

<query> <query-method> <method-name>findAll</method-name> <method-params> </method-params> </query-method> <result-type-mapping>Local</result-type-mapping> <ejb-ql><![CDATA[ SELECT OBJECT(g) FROM UserGroup g ]]></ejb-ql> </query>

result-type-mapping 元素指出查找程序方法返回的是实体 bean 的本地接口还是远程接口。在这个例子中,您将返回本地接口。 ejb-ql 元素是定义用于查询的 EJB-QL 的地方。 请注意,FROM 子句使用 Group 实体 bean 的模式名 UserGroup。还要注意 OBJECT 关键字的使用,它必须用于返回实体 bean。上面的查询返回系统中所有的 Group。

2、简单查询单独的实体 我们来假设您想创建一个查询,来查找组名等于某一个您感兴趣的名称的组。您要使用下列 EJB-QL: SELECT OBJECT(g) FROM UserGroup g WHERE g.name = ?1

?1 指的是方法的第一个参数。如果有两个参数,那么 ?2 指的是传递给查找程序方法的第二个参数,依此类推。

上面示例的 home 接口的查找程序方法如下:

public GroupLocal findByGroupName(String name) throws javax.ejb.FinderException; 请注意,这个查找程序方法还说明了一个查找程序,该查找程序期望用一个单独的实体作为结果,因为它返回 GroupLocal 而不是 Collection。事实上,如果查询返回不止一个结果,将抛出 FinderException。

因为这个方法只用了一个参数,所以必须在部署描述符中用 method-param 元素声明这个参数,如下所示: <query> <query-method> <method-name>findByGroupName</method-name> <method-params> <method-param>java.lang.String</method-param> </method-params> </query-method> … </query>

请注意,WHERE 子句(和 g.name 中一样)中使用的 name 是一个 CMP 字段。

SELECT OBJECT(g) FROM UserGroup g WHERE g.name = ?1

因此,CMP 字段可以用在 EJB-QL 查询中。

3、高级 EJB-QL,包括:

比较操作符,包括 LIKE 选择方法 逻辑操作符 BETWEEN 子句 IS NULL

比如: SELECT DISTINCT OBJECT(user) FROM User user WHERE user.group.name IN (‘engineering’,’IT’)

(其他,详见资料或书籍)

十六、容器管理的关系(CMR) 1、关系类型,如下所示: 一对一 一对多 多对多

这些关系在 XML 部署描述符中定义。

2、举例说明 有四个截然不同的实体:User、Group、Role 以及 UserInfo。这些实体中的每一个都有下面这三种关系: 多个 User 与多个 Role 相关联(多对多) 一个 User 有一个 UserInfo(一对一) 一个 Group 包含多个 User(一对多)

请注意下面的代码:

public abstract LocalUser getUser(); public abstract void setUser(LocalUser user);

在 UserInfoBean 的本地接口和实现中都有。这个 setter 和 getter 方法定义这个双向关系的 CMR 字段。 因为这个关系是双向的,所以 UserInfo 和 UserInfoBean 都必须有引用对方的 CMR 字段。

3、UserInfoBean 的部署描述符 请注意,一个关系中所涉及的实体必须在同一个部署描述符中定义;这样,必须在同一个 .jar 文件中打包这些实体。 UserBean 和 UserInfoBean 一起在同一个 EJB .jar 文件中打包,并且一起在同一个部署描述符中定义。

4、在部署描述符中定义一对一关系: 关系在 <enterprise-beans> 元素之外定义。当您指定关系时,您必须指定关系中所涉及的两个实体 bean。 关系在 <ejb-relation> 元素中定义。关系中的每个角色在 <ejb-relationship-role> 元素中定义。

比如: <relationships> <ejb-relation> <ejb-relation-name>UserHasUserInfo</ejb-relation-name>

<ejb-relationship-role> <ejb-relationship-role-name> UserHasUserInfo </ejb-relationship-role-name> <multiplicity>One</multiplicity> <relationship-role-source> <ejb-name>UserBean</ejb-name> </relationship-role-source> <cmr-field> <cmr-field-name>userInfo</cmr-field-name> </cmr-field> </ejb-relationship-role>

<ejb-relationship-role> <ejb-relationship-role-name> UserInfoPartOfUser </ejb-relationship-role-name> <multiplicity>One</multiplicity> <cascade-delete /> <relationship-role-source> <ejb-name>UserInfoBean</ejb-name> </relationship-role-source> <cmr-field> <cmr-field-name>user</cmr-field-name> </cmr-field> </ejb-relationship-role>

</ejb-relation> </relationships>

<ejb-relationship-role> 有名称、多样性、源以及可选的 CMR 字段,分别由下面这些元素定义: 分别是 <ejb-relationship-role-name>、<multiplicity>、带有 <ejb-name> 子元素的 <relationship-role-source> 以及带有 <cmr-field-name> 子元素的 <cmr-field>。

现在说明一下: <ejb-relationship-role-name> 元素体可以是您所希望的任何名称。请尽量使它对于您所描述的关系具有描述性。 另外,请尽量使它在部署描述符的上下文中是唯一的。

<relationship-role-source>/<ejb-name> 体必须设置为由 <enterprise-beans> 元素中的实体 /<ejb-name> 定义的 ejb-bean 名。

<cmr-field>/<cmr-field-name> 体必须设置为这一屏中定义的 CMR 字段名。 如果 <cmr-field> 由本地接口中的getUserInfo()和setUserInfo()定义,那么它将由 <cmr-field-name> 中的 userInfo 定义,如下所示: <cmr-field> <cmr-field-name>userInfo</cmr-field-name> </cmr-field> </ejb-relationship-role>

5、多对多关系 多对多关系听起来极其难以实现。实际上,它和一对一关系一样容易实现。EJB 容器替您做了所有最难做的工作。

对于这个示例,您将添加用户可能处于的不同角色。单个用户可能处于多个角色。并且一个角色可以与多个用户相关联。

在部署描述符中定义多对多关系: 添加多对多关系的 XML 元素和技术与添加一对一关系的 XML 元素和技术基本相同。唯一的关键的不同之处是多样性。 RoleBean 的 <ejb-relationship-role> 没有 CMR 字段元素,因为从 UserBean 到 RoleBean 的关系是单向的。 RoleBean 不知道 UserBean。下面列出了 <ejb-relation> 元素:

<ejb-relation> <ejb-relation-name>UserAssociateWithRoles</ejb-relation-name>

<ejb-relationship-role> <ejb-relationship-role-name>UserBeanToRoleBean</ejb-relationship-role-name> <multiplicity>Many</multiplicity> <relationship-role-source> <ejb-name>UserBean</ejb-name> </relationship-role-source> <cmr-field> <cmr-field-name>roles</cmr-field-name> <cmr-field-type>java.util.Collection</cmr-field-type> </cmr-field> </ejb-relationship-role>

<ejb-relationship-role> <ejb-relationship-role-name>RoleBeanToUserBean</ejb-relationship-role-name> <multiplicity>Many</multiplicity> <relationship-role-source> <ejb-name>RoleBean</ejb-name> </relationship-role-source> </ejb-relationship-role>

</ejb-relation>

请注意,UserBeanToRoleBean 的 <multiplicity> 为 Many,而且 UserBeanToRoleBean 的 <cmr-field> 有一个子元素 <cmr-field-type>。<cmr-field-type> 元素用值为 Many 的 <multiplicity> 的关系定义了 Java 代码类型。 请注意,两种可能是 java.util.Collection 和 java.util.Set。因为您选择了 java.util.Collection 以及 CMR 字段名是 roles,那么您可以料到会在返回和设置 java.util.Collection 的 UserBean 的本地接口中看到一个叫做 roles 的 CMR 字段(setter 和 getter 方法对)。

6、一对多关系 和第一个关系示例中的 UserInfoBean 一样,GroupBean 有一个引用 UserBean 的 <cmr-field>。和 UserInfoBean 不同,GroupBean 中的 <cmr-field> 的用户是 UserBean 的集合。

在部署描述符中定义一对多关系: 用来添加一对多关系的 xml 元素和技术与添加一对一和多对多关系的 xml 元素和技术几乎相同。唯一的关键的不同之处是多样性。 GroupBean 的 <ejb-relationship-role> 有一个 CMR 字段元素,因为从 UserBean 到 GroupBean 的关系是双向的。 GroupBean 有一个名为 users 的 CMR 字段。UserBean 有一个名为 group 的 CMR 字段。下面列出了 <ejb-relation> 元素:

<ejb-relation>

<ejb-relation-name>GroupsHaveUsers</ejb-relation-name>

<ejb-relationship-role> <ejb-relationship-role-name>GroupHasUsers</ejb-relationship-role-name> <multiplicity>One</multiplicity>

<relationship-role-source> <ejb-name>GroupBean</ejb-name> </relationship-role-source>

<cmr-field> <cmr-field-name>users</cmr-field-name> <cmr-field-type>java.util.Collection</cmr-field-type> </cmr-field>

</ejb-relationship-role>

<ejb-relationship-role>

<ejb-relationship-role-name>UsersInGroup</ejb-relationship-role-name> <multiplicity>Many</multiplicity>

<relationship-role-source> <ejb-name>UserBean</ejb-name> </relationship-role-source>

<cmr-field> <cmr-field-name>group</cmr-field-name> </cmr-field>

</ejb-relationship-role>

</ejb-relation>

请注意,GroupHasUsers 的 multiplicity 为 One,因为在这个关系中有一个组,并且和上一个示例 GroupHasUsers 的 <cmr-field> 一样,有一个子元素 <cmr-field-type>,如下所示:

<cmr-field> <cmr-field-name>users</cmr-field-name> <cmr-field-type>java.util.Collection</cmr-field-type> </cmr-field>

字段关系的类型是 java.util.Collection,CMR 字段名是 users。

关系的另一方 UsersInGroup 的 <multiplicity> 为 Many,因为这个组里有很多用户。另请注意将 <cmr-field> 设置为 group。

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/188486.html原文链接:https://javaforall.cn

本文参与?腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客?前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与?腾讯云自媒体同步曝光计划? ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
http://www.vxiaotou.com