Topic: (原创)建立并运行一个简单的CMP的全过程(WEBLOGIC7.0) |
Print this page |
1.(原创)建立并运行一个简单的CMP的全过程(WEBLOGIC7.0) | Copy to clipboard |
Posted by: struggle Posted on: 2003-06-14 11:43 偶用WEBLOGIC7.0+MYSQL没有用IDE。(附件中的代码是我成功运行后的代码).这是《精通EJB第二版》 第七章的例子。由于源码有些问题,偶走了些弯路。另外,偶发现现在许多人学习时都不是很踏实, 比如《精通EJB第二版》这本书,很多人都看过,但偶问他们此章的关于“TXDataSource”问题时,许多 的回答却是不知TXDataSource为何物,很少有人能回答出个所以然来。这样怎么能算是看过《精通EJB》? (后来幸好遇到一个高手,才得以解决,但由于匆忙,至于为什么CMP中要用TXDataSource而不用 DataSource偶也只知是事务方面的原因,究竟详细的原因如何,希望哪位大侠能写出来让大家分享) 偶将自己学习这一章的过程写出来,希望走同样路的人少走弯路。偶将源码中的英文注释改为中文 注释。希望能对了解CMP的流程有帮助。并且尽量保证程序中没有一个错误!附件中的代码是偶运行 成功的代码! 此CMP设计的是一家计算机硬件公司,提供内存、硬盘和处理器等。通过此CMP来进行简单的查询等操作。 步骤: 1. 首先建立数据库表: mysql> use test; mysql> create table products (productId varchar(64), name varchar(64), basePrice numeric(18), description varchar(64)); mysql> insert into products values ('1', 'Pentium III', 2000, 'Intel brand, 256k Level2 cache'); mysql>insert into products values ('2', 'Celeron', 800, 'Low-end mainstream machine'); mysql>insert into products values ('3', 'Pentium I', 500, 'Refurbished machine'); mysql>insert into products values ('4', 'Mac', 2500, 'Color iMac'); mysql>insert into products values ('5', 'Pentium II', 500, 'Mid-level machine'); mysql>insert into products values ('6', 'Athlon', 3500, 'AMD Flagship'); 2. 下载驱动程序mm.mysql-2.0.14-bin.jar (本人在附件中附带有此驱动),将其拷贝到Weblogic_Home/weblogic700/server/lib中,修改启动脚本比如 F:\bea\weblogic700\server\bin\startWLS.cmd, 在Classpath中添加%WL_HOME%\server\lib\mm.mysql-2.0.7-bin.jar;。注意添加到 weblogic.jar;之前,因为驱动要在服务启动之前加载。 3. 建立数据连接池: a. 打开WEBLOGIC服务,在Console的菜单即(http://192.168.139.58:7001/console其中192.168.139.58是我的机器IP, 也可写自己的机器名。如果不行就写localhost试试。)中选择,Services/JDBC/Connection Pools b. 点击Configure a new JDBC Connection Pool... c. Configuration/General Tab: Name:myPool(此名字可随便取) URL:jdbc:mysql://localhost/test Driver Classname:org.gjt.mm.mysql.Driver Properties(key=value):user=root password=111111 (这里的user和password分别是MYSQL的用户名和密码) d. 点击Create e. Configuration/Connections Tab: Initial Capacity:1 Maximum Capacity:5 其余默认,点击Apply f. Targets/Servers Tab: 选择Available中的myserver,点击右箭头使其到右边的Chosen中,然后点击Apply!如果没有报错,即证明创建连接池成功! 4. 建立TXDataSource: 注意这里和BMP不一样,这主要是基于事务方面的原因。 a. 在Console的菜单中选择,Services/jdbc/Tx Data Sources b. 点击Configure a new JDBC Tx Data Source... c. Configuration Tab: Name:MyTxDataSource(可随便取) JNDI Name: cmpPool(这个很重要,不能写错) Pool Name: myPool(要和上面建立连接池时的名字一样!) 点击Create d. Targets/Services Tab: 选择Available中的myserver,点击右箭头使其到右边的Chosen中,然后点击Apply!,如果没有报错,即证明创建数据源成功! 5. 写代码及相关部署文件。 远程接口(Product.java) package examples; import javax.ejb.*; import java.rmi.RemoteException; import java.util.*; /** * 这些是ProductBean的公共的商务方法. * * 在远程客户端程序与Bean交互时,这个接口就是它们 * 所要操作的。EJB容器将实现这个接口,实现的对象实例 * 叫做EJB对象,它委托给ProductBean类的实例调用。 */ public interface Product extends EJBObject { // Getter/setter 方法 public String getName() throws RemoteException; public void setName(String name) throws RemoteException; public String getDescription() throws RemoteException; public void setDescription(String description) throws RemoteException; public double getBasePrice() throws RemoteException; public void setBasePrice(double basePrice) throws RemoteException; public String getProductId() throws RemoteException; } HOME接口(ProductHome.java) package examples; import javax.ejb.*; import java.rmi.RemoteException; import java.util.Collection; /** * 这是Product的Home接口. * EJB服务器的代码粘合工具实现这个接口。 * 实现的对象叫做Home对象,并作为一个制造 * EJB对象的生成库提供服务。 * * Home接口中有一个create() 方法,对应于ProductBean * 的ejbCreat()方法。 */ public interface ProductHome extends EJBHome { /* * 生成一个产品 * * @param productID 产品的号码(唯一的) * @param name 产品的名称 * @param description 产品的描述 * @param basePrice 产品的基础价格 * * @return 新创建的EJB对象 */ public Product create(String productID, String name, String description, double basePrice) throws CreateException, RemoteException; // 定位器方法(Finder methods)。容器实现这些方法。 // 你可以利用EJB容器的工具和EJB-QL来自定义这些方法的功能。 public Collection findByName(String name) throws FinderException, RemoteException; public Collection findByDescription(String description) throws FinderException, RemoteException; public Collection findByBasePrice(double basePrice) throws FinderException, RemoteException; public Collection findExpensiveProducts(double minPrice) throws FinderException, RemoteException; public Collection findCheapProducts(double maxPrice) throws FinderException, RemoteException; public Collection findAllProducts() throws FinderException, RemoteException; public Product findByPrimaryKey(ProductPK pk) throws FinderException, RemoteException; } 主键类(ProductPK.java) package examples; import java.io.Serializable; /** * 'Product' Container-Managed Entity Bean的主键类 */ public class ProductPK implements java.io.Serializable { /* * 注意:主键域必须是CMP实体Bean的域的一个子集。在Bean * 中标识为容器管理的域是productID, name, desc, 和basePrice. * 因此,主键域需要来自于这个集合。 */ public String productId; public ProductPK() { } public ProductPK(String productId) { this.productId = productId; } public boolean equals(Object obj) { if (obj != null) { if (this.getClass().equals(obj.getClass())) { ProductPK that = (ProductPK) obj; return (((this.productId == null) && (that.productId == null)) || (this.productId != null && this.productId.equals(that.productId))); } } return false; } public int hashCode() { return productId.hashCode(); } public String toString() { return productId.toString(); } } CMP的BEAN实现类(ProductBean.java) package examples; import javax.ejb.*; /** * Entity Bean示范Container-Managed persistence. * * 这是一个产品,它是持久的。它有一个ID #, 一个 name, * 一个description, 和一个 base price. */ abstract public class ProductBean implements EntityBean { protected EntityContext ctx; public ProductBean() { } //---------------------------------------------------------------- // 开始抽象的 get/set 方法 //---------------------------------------------------------------- public abstract String getName(); public abstract void setName(String name); public abstract String getDescription(); public abstract void setDescription(String description); public abstract double getBasePrice(); public abstract void setBasePrice(double basePrice); public abstract String getProductId(); public abstract void setProductId(String productId); //---------------------------------------------------------------- // 结束抽象的 get/set 方法 //---------------------------------------------------------------- //---------------------------------------------------------------- // 开始EJB必需的方法,方法由容器调用, // 不是由客户端调用。 //---------------------------------------------------------------- /** * 由容器调用。 * 执行时可获得需要的资源。 */ public void ejbActivate() { System.out.println("ejbActivate() called."); } /** * EJB容器恰好在它从数据库中删除实体Bean之前调用这个方法。 * 当客户端调用home.remove()方法时,这个方法与之对应。 */ public void ejbRemove() { System.out.println("ejbRemove() called."); } /** * 由容器调用。 * 释放占有的资源。 */ public void ejbPassivate() { System.out.println("ejbPassivate () called."); } /** * 由容器调用。 更新实体Bean实例反映存储在数据库中的当前值。 * 因为我们正在使用容器管理的持久,所以可以让此方法空着。 * EJB容器将自动为我们装载。 */ public void ejbLoad() { System.out.println("ejbLoad() called."); } /** * 由容器调用。 更新数据库反映这个内存中的实体Bean实例代表的当前值。 * 因为我们正在使用容器管理的持久,所以可以让此方法空着。 * EJB容器将自动为我们保存到子类中。 */ public void ejbStore() { System.out.println("ejbStore() called."); } /** * 由容器调用。 把这个Bean实例和一个特定的环境对象关联起来。一旦这么做, * 我们可以查询环境对象得到环境信息,例如Bean通过特性自定义的信息。 */ public void setEntityContext(EntityContext ctx) { System.out.println("setEntityContext called"); this.ctx = ctx; } /** * 由容器调用。把这个Bean实例与一个特定的环境对象分离。 */ public void unsetEntityContext() { System.out.println("unsetEntityContext called"); this.ctx = null; } /** * ejbCreate()调用之后调用。现在,Bean可以从它的环境中提取它的EJB对象。 * 并当作一个“this”参数传递给它。 */ public void ejbPostCreate(String productID, String name, String description, double basePrice) { System.out.println("ejbPostCreate() called"); } /** * 这是对应Home接口的create()方法的初始化方法。 * * 在客户端调用Home对象的create()方法时,Home对象然后调用 * 这个ejbCreate()方法。 * * 注意: 因为我们使用Container-Managed Persistence, * 所以该方法返回void. 用Bean-Managed Persistence, * 则返回 PK. 这是因为我们的Bean有责任处理主键和访问数据库。 * 现在我们让容器来管理持久,容器产生主键。 * * 我们仍然需要用从客户端传递的参数初始化我们的Bean的域, * 好让容器可以检查我们的Bean并创建相应的数据库条目。 */ public ProductPK ejbCreate(String productID, String name, String description, double basePrice) { System.out.println("ejbCreate() called"); setProductId(productID); setName(name); setDescription(description); setBasePrice(basePrice); return new ProductPK(productID); } // 没有定位器方法 - 它们由容器实现 //---------------------------------------------------------------- // 结束EJB必需的方法。 //---------------------------------------------------------------- } 部署描述文件(ejb-jar.xml): 这个文件很重要,容器怎么知道用户怎样操作一些资源比如JDBC呢, 就是通过这个文件来使容器做许多工作。 <?xml version="1.0"?> <!DOCTYPE ejb-jar PUBLIC "-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 2.0//EN" "http://java.sun.com/dtd/ejb-jar_2_0.dtd"> <ejb-jar> <enterprise-beans> <entity> <ejb-name>Product</ejb-name> <home>examples.ProductHome</home> <remote>examples.Product</remote> <ejb-class>examples.ProductBean</ejb-class> <persistence-type>Container</persistence-type> <prim-key-class>java.lang.String</prim-key-class> <reentrant>False</reentrant> <cmp-version>2.x</cmp-version> <abstract-schema-name>ProductBean</abstract-schema-name> <cmp-field> <field-name>productID</field-name> </cmp-field> <cmp-field> <field-name>name</field-name> </cmp-field> <cmp-field> <field-name>description</field-name> </cmp-field> <cmp-field> <field-name>basePrice</field-name> </cmp-field> <primkey-field>productID</primkey-field> <query> <query-method> <method-name>findByName</method-name> <method-params> <method-param>java.lang.String</method-param> </method-params> </query-method> <ejb-ql> <![CDATA[SELECT OBJECT(a) FROM ProductBean AS a WHERE a.name = ?1]]> </ejb-ql> </query> <query> <query-method> <method-name>findByDescription</method-name> <method-params> <method-param>java.lang.String</method-param> </method-params> </query-method> <ejb-ql> <![CDATA[SELECT OBJECT(a) FROM ProductBean AS a WHERE a.description = ?1]]> </ejb-ql> </query> <query> <query-method> <method-name>findByBasePrice</method-name> <method-params> <method-param>double</method-param> </method-params> </query-method> <ejb-ql> <![CDATA[SELECT OBJECT(a) FROM ProductBean AS a WHERE a.basePrice = ?1]]> </ejb-ql> </query> <query> <query-method> <method-name>findExpensiveProducts</method-name> <method-params> <method-param>double</method-param> </method-params> </query-method> <ejb-ql> <![CDATA[SELECT OBJECT(a) FROM ProductBean AS a WHERE a.basePrice > ?1]]> </ejb-ql> </query> <query> <query-method> <method-name>findCheapProducts</method-name> <method-params> <method-param>double</method-param> </method-params> </query-method> <ejb-ql> <![CDATA[SELECT OBJECT(a) FROM ProductBean AS a WHERE a.basePrice < ?1]]> </ejb-ql> </query> <query> <query-method> <method-name>findAllProducts</method-name> <method-params> </method-params> </query-method> <ejb-ql> <![CDATA[SELECT OBJECT(a) FROM ProductBean AS a WHERE a.productID IS NOT NULL]]> </ejb-ql> </query> </entity> </enterprise-beans> <assembly-descriptor> <container-transaction> <method> <ejb-name>Product</ejb-name> <method-intf>Remote</method-intf> <method-name>*</method-name> </method> <trans-attribute>Required</trans-attribute> </container-transaction> </assembly-descriptor> </ejb-jar> weblogic-cmp-rdbms-jar.xml: 注意下面的<data-source-name>就是要建立TXDataSource要用到的。<table-name>是数据库表名。 <!DOCTYPE weblogic-rdbms-jar PUBLIC '-//BEA Systems, Inc.//DTD WebLogic 6.0.0 EJB RDBMS Persistence//EN' 'http://www.bea.com/servers/wls600/dtd/weblogic-rdbms20-persistence-600.dtd'> <weblogic-rdbms-jar> <weblogic-rdbms-bean> <ejb-name>Product</ejb-name> <data-source-name>cmpPool</data-source-name> <table-name>Products</table-name> <field-map> <cmp-field>name</cmp-field> <dbms-column>name</dbms-column> </field-map> <field-map> <cmp-field>productID</cmp-field> <dbms-column>productid</dbms-column> </field-map> <field-map> <cmp-field>description</cmp-field> <dbms-column>description</dbms-column> </field-map> <field-map> <cmp-field>basePrice</cmp-field> <dbms-column>basePrice</dbms-column> </field-map> </weblogic-rdbms-bean> </weblogic-rdbms-jar> weblogic-ejb-jar.xml: <?xml version="1.0"?> <!DOCTYPE weblogic-ejb-jar PUBLIC "-//BEA Systems, Inc.//DTD WebLogic 6.0.0 EJB//EN" "http://www.bea.com/servers/wls600/dtd/weblogic-ejb-jar.dtd" > <weblogic-ejb-jar> <weblogic-enterprise-bean> <ejb-name>Product</ejb-name> <entity-descriptor> <entity-cache> <max-beans-in-cache>1000</max-beans-in-cache> </entity-cache> <persistence> <persistence-type> <type-identifier>WebLogic_CMP_RDBMS</type-identifier> <type-version>6.0</type-version> <type-storage>META-INF/weblogic-cmp-rdbms-jar.xml</type-storage> </persistence-type> <persistence-use> <type-identifier>WebLogic_CMP_RDBMS</type-identifier> <type-version>6.0</type-version> </persistence-use> </persistence> </entity-descriptor> <jndi-name>RemoteProductHome</jndi-name> </weblogic-enterprise-bean> </weblogic-ejb-jar> 客户端程序(ProductClient.java): //这只是一个测试程序 package examples; import javax.ejb.*; import javax.naming.*; import java.rmi.*; import java.util.*; /** * Container-Managed Entity Bean, Product的客户端测试应用程序。 */ public class ProductClient { public static void main(String[] args) throws Exception { ProductHome home = null; try { Context ctx = null; String url = "t3://localhost:7001"; try { /* * 获得系统属性,为JNDI初始化做准备 */ Properties properties = new Properties(); properties.put(Context.INITIAL_CONTEXT_FACTORY,"weblogic.jndi.WLInitialContextFactory"); properties.put(Context.PROVIDER_URL,url); ctx = new InitialContext(properties); } catch(NamingException e) { e.printStackTrace(); } /* * 得到一个Product Home对象的引用 - 制造产品EJB对象的生成库。 */ home = (ProductHome) javax.rmi.PortableRemoteObject.narrow(ctx.lookup("ProductRemote"), ProductHome.class); /* * 用生成库创建产品EJB对象。 */ home.create("123-456-7890", "P5-350", "350 Mhz Pentium", 200); home.create("123-456-7891", "P5-400", "400 Mhz Pentium", 300); home.create("123-456-7892", "P5-450", "450 Mhz Pentium", 400); home.create("123-456-7893", "SD-64", "64 MB SDRAM", 50); home.create("123-456-7894", "SD-128", "128 MB SDRAM", 100); home.create("123-456-7895", "SD-256", "256 MB SDRAM", 200); /* * 查找一个产品, 并打印输出它的产品描述。 */ Iterator i = home.findByName("SD-64").iterator(); System.out.println("The following product descriptions match the product name SD-64:"); while (i.hasNext()) { Product prod = (Product) javax.rmi.PortableRemoteObject.narrow(i.next(), Product.class); System.out.println(prod.getDescription()); } /* * 查找所有价值$200的产品 */ System.out.println("Calling finder to find all products that cost $200"); i = home.findByBasePrice(200).iterator(); while (i.hasNext()) { Product prod = (Product) javax.rmi.PortableRemoteObject.narrow(i.next(), Product.class); System.out.println(prod.getDescription()); } } catch (Exception e) { e.printStackTrace(); } finally { if (home != null) { System.out.println("Destroying products.."); /* * 删除所有的产品 */ Iterator i = home.findAllProducts().iterator(); while (i.hasNext()) { try { Product prod = (Product) javax.rmi.PortableRemoteObject.narrow(i.next(), Product.class); if (prod.getProductId().startsWith("123")) { prod.remove(); } } catch (Exception e) { e.printStackTrace(); } } } } } } 6. 编译源文件得到相应的class文件 ,此步省略。然后生成jar文件。进入classes目录(即我提供代码的目录)用命令: jar vcf cmpEJB.jar * 就可生成cmpEJB.jar文件。 7. 部署上面生成的jar文件: a. 在console页面左面点击:Deployments/EJB,然后在右面点击Configure a new EJB… b. 点击upload it through your browser 链接 c. 点击“浏览…”按钮,选择刚才建立的EJB.jar文件。 d. 点击Upload按钮。然后点击右边页面下面的EJB.jar对应的[select]链接。 e. 将Available Servers下面的myserver选择到右边的框中,点击Configure and Deploy按钮。如果成功,会看到相应的true及Completed状态。 8. 运行 在存放ProductClient.class的目录下,比如我的机器这样: I:\mytest\111 将附带的examples目录放在I:\mytest\111 要注意的是此目录(I:\mytest\111)一定要加在CLASSPATH中,否则会出现如下异常: Exception in thread "main" java.lang.NoClassDefFoundError examples.HelloClient 打开WEBLOGIC服务器,在DOS窗口中的I:\mytest\111目录下用命令: java -Djava.naming.factory.initial=weblogic.jndi.WLInitialContextFactory -Djava.naming.provider.url=t3://localhost:7001 examples.ProductClient 注意“localhost”的写法,可能要写机器的IP。这依赖于当初如何配置WEBLOGIC服务的。 最后输出为: 客户端: The following product descriptions match the product name SD-64: 64 MB SDRAM Calling finder to find all products that cost $200 350 Mhz Pentium 256 MB SDRAM Destroying products.. 服务器端: setEntityContext called ejbCreate() called ejbPostCreate() called ejbStore() called. setEntityContext called ejbCreate() called ejbPostCreate() called ejbStore() called. setEntityContext called ejbCreate() called ejbPostCreate() called ejbStore() called. setEntityContext called ejbCreate() called ejbPostCreate() called ejbStore() called. setEntityContext called ejbCreate() called ejbPostCreate() called ejbStore() called. setEntityContext called ejbCreate() called ejbPostCreate() called ejbStore() called. setEntityContext called setEntityContext called ejbLoad() called. ejbStore() called. ejbLoad() called. ejbStore() called. setEntityContext called ejbLoad() called. ejbLoad() called. ejbStore() called. ejbStore() called. ejbLoad() called. ejbStore() called. ejbLoad() called. ejbStore() called. setEntityContext called setEntityContext called setEntityContext called setEntityContext called setEntityContext called setEntityContext called setEntityContext called setEntityContext called setEntityContext called setEntityContext called ejbActivate() called. ejbLoad() called. ejbActivate() called. ejbLoad() called. ejbActivate() called. ejbLoad() called. ejbActivate() called. ejbLoad() called. ejbActivate() called. ejbLoad() called. ejbActivate() called. ejbLoad() called. ejbLoad() called. ejbLoad() called. ejbLoad() called. ejbLoad() called. ejbLoad() called. ejbLoad() called. ejbStore() called. ejbStore() called. ejbStore() called. ejbStore() called. ejbStore() called. ejbStore() called. ejbStore() called. ejbStore() called. ejbStore() called. ejbStore() called. ejbStore() called. ejbStore() called. ejbLoad() called. ejbStore() called. ejbLoad() called. ejbStore() called. ejbLoad() called. ejbStore() called. ejbLoad() called. ejbStore() called. ejbLoad() called. ejbStore() called. ejbLoad() called. ejbStore() called. ejbLoad() called. ejbStore() called. ejbLoad() called. ejbRemove() called. ejbLoad() called. ejbStore() called. ejbLoad() called. ejbRemove() called. ejbLoad() called. ejbStore() called. ejbLoad() called. ejbRemove() called. ejbLoad() called. ejbStore() called. ejbLoad() called. ejbRemove() called. ejbLoad() called. ejbStore() called. ejbLoad() called. ejbRemove() called. ejbLoad() called. ejbStore() called. ejbLoad() called. ejbRemove() called. 注意程序的注释,再结合客户端和服务器端输出就可琢磨出CMP容器在什么时间都作了些什么。CMP和BMP的 生命周期差不多,除了调用客户端调用的方法外,EJB容器会交叉调用几次ejbStore()和ejbLoad()方法来保持 与数据库的同步。 产品例子.rar (129.59k) |
2.Re:(原创)建立并运行一个简单的CMP的全过程(中文注释) [Re: struggle] | Copy to clipboard |
Posted by: 牛老板 Posted on: 2003-06-14 16:52 听来的: TXDataSource 和 DataSource 的区别就是在于,一个可以支持分布式(两阶提交),一个不支持。 |
3.Re:(原创)建立并运行一个简单的CMP的全过程(中文注释) [Re: struggle] | Copy to clipboard |
Posted by: struggle Posted on: 2003-06-17 12:37 牛老板真厉害!偶是拼起老命才四分啊! |
4.Re:(原创)建立并运行一个简单的CMP的全过程(中文注释) [Re: 牛老板] | Copy to clipboard |
Posted by: FinalFantasy Posted on: 2003-06-18 00:43 牛老板 wrote: 说的不错,,主要区别就是这个。 还有一个区别就是,txdatasource不会每次执行sql语句都commit,至少cmp中会有这个问题。 |
5.Re:(原创)建立并运行一个简单的CMP的全过程(WEBLOGIC7.0) [Re: struggle] | Copy to clipboard |
Posted by: mojialin100 Posted on: 2003-06-18 18:46 不过ejb要求TXDataSource |
6.Re:(原创)建立并运行一个简单的CMP的全过程(WEBLOGIC7.0) [Re: struggle] | Copy to clipboard |
Posted by: jameszhang Posted on: 2003-06-18 20:21 cmp我认为在ejb2.0规范里必须配置txdatasource,bmp如果不需要支持事务可能无需配置txdatasource(个人观点) |
7.Re:(原创)建立并运行一个简单的CMP的全过程(WEBLOGIC7.0) [Re: struggle] | Copy to clipboard |
Posted by: why Posted on: 2003-06-27 20:35 struggle 大侠:您在 Application Server 版发了一篇姐妹作━━(原创)在JBOSS3.0.7下的一个CMP实现的全过程(源码中文注释),小的想把它转到 J2EE 版,有没有异议? 对啦,struggle大侠想找一找两三个表关联的CMP、BMP例子看看, 又希望给他介绍一两个国外网站,可以下载到关于CMP、BMP实例的地方。 请各位大侠指教指教啦! |
8.Re:(原创)建立并运行一个简单的CMP的全过程(WEBLOGIC7.0) [Re: struggle] | Copy to clipboard |
Posted by: struggle Posted on: 2003-06-29 10:43 当然没有异议! 谢谢WHY的帮忙! 最后:叫我大侠实在不敢当! |
9.Re:(原创)建立并运行一个简单的CMP的全过程(WEBLOGIC7.0) [Re: struggle] | Copy to clipboard |
Posted by: mengzhihai Posted on: 2003-07-03 17:31 不是说建实体bean的时侯,建数据库表必段有一个"主键"吗!上面好像建表时没有设"主"键... |
10.Re:(原创)建立并运行一个简单的CMP的全过程(WEBLOGIC7.0) [Re: struggle] | Copy to clipboard |
Posted by: struggle Posted on: 2003-07-03 18:27 关于CMP的主键问题,有两种选择,一种是用自定义主键,就是楼顶的 贴子上所写的那种。另一种是使用容器管理的一个域来作为主键类。比如 楼顶附件中所带的源代码就是将productId这个域作为主键类。 Mastering Enterprise JavaBeans的作者Ed Romam建议避免使用域作为主键类, 原因是主键类的封装器可以使程序员不必关心怎样在底层数据存储中惟一的 表示自己。 |
11.Re:(原创)建立并运行一个简单的CMP的全过程(WEBLOGIC7.0) [Re: struggle] | Copy to clipboard |
Posted by: bruce Posted on: 2003-07-04 09:34 struggle, 非常感谢你的大作! 前几天我试了一下Hibernate,不错!因为我用EJB时是在2000年,那时用的是EJB1.0, 也用RMI开发过程序。 不过现在几年不玩EJB了, 拿着你的例子试了一下,基本没问题,你写的非常清楚。 但我还是存在一个问题, 尽管程序运行正常,客户端和服务器端都没有报错, 但程序运行完后, 我到数据库时检查, 却没有看到我creat出来的数据. 于是我将客户端程序再运行一次, 程序报错,说已有数据存在。这说明数据已经存在。 于是我真的糊涂了。不知如何是好?请问你有办法吗? |
12.Re:(原创)建立并运行一个简单的CMP的全过程(WEBLOGIC7.0) [Re: struggle] | Copy to clipboard |
Posted by: struggle Posted on: 2003-07-04 09:48 TO:bruce 请您详细描述一下您的环境和过程。 |
13.Re:(原创)建立并运行一个简单的CMP的全过程(WEBLOGIC7.0) [Re: struggle] | Copy to clipboard |
Posted by: bruce Posted on: 2003-07-04 10:01 对了,程序如下:try { //get naming context Context context = getJBossInitialContext(); //look up jndi name Object ref = context.lookup("CmptableRemote"); //look up jndi name and cast to Home interface cmptableRemoteHome = (CmptableRemoteHome) PortableRemoteObject.narrow(ref, CmptableRemoteHome.class); cmptableRemoteHome.create("11111", "cat"); Iterator i = cmptableRemoteHome.findByName("cat").iterator(); System.out.println("These name match the name cat:"); while (i.hasNext()) { CmptableRemote prod = (CmptableRemote) PortableRemoteObject.narrow(i.next(), CmptableRemote.class); System.out.println("name:"+prod.getName()); System.out.println("id:"+prod.getId()); } /* 我把以下的代码注掉了,所以在数据库中应可以看到新增数据的 Iterator ii = cmptableRemoteHome.findAll().iterator(); while (ii.hasNext()) { CmptableRemote prod1 = (CmptableRemote) PortableRemoteObject.narrow(ii.next(), CmptableRemote.class); System.out.println("delete" + prod1.getName()); prod1.remove(); } */ } catch(Exception e) { e.printStackTrace(); } |
14.Re:(原创)建立并运行一个简单的CMP的全过程(WEBLOGIC7.0) [Re: struggle] | Copy to clipboard |
Posted by: struggle Posted on: 2003-07-04 10:18 /* 我把以下的代码注掉了,所以在数据库中应可以看到新增数据的 Iterator ii = cmptableRemoteHome.findAll().iterator(); while (ii.hasNext()) { CmptableRemote prod1 = (CmptableRemote) PortableRemoteObject.narrow(ii.next(), CmptableRemote.class); System.out.println("delete" + prod1.getName()); prod1.remove(); } */ 这些代码不用注释掉,因为是删除创建的EJB对象,这样才完整啊。就象 连接数据库最后要断开数据库连接一样。和数据库中的数据没有关系。在 此之前容器就已将程序中创建的相关数据写入数据库了。 不知您数据库环境怎么样,我想是出现了如下情况:程序已经正常运行, 但由于某种原因(比如数据库表不可写等)数据写不进数据库,但内存 中有。程序再运行一次当然就报错,说已有数据存在。 对了,您的数据库可支持事务? |
15.Re:(原创)建立并运行一个简单的CMP的全过程(WEBLOGIC7.0) [Re: struggle] | Copy to clipboard |
Posted by: bruce Posted on: 2003-07-04 10:20 环境: JBoss+MySQL ejb-jar.xml 如下 <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE ejb-jar PUBLIC "-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 2.0//EN" "http://java.sun.com/dtd/ejb-jar_2_0.dtd"> <ejb-jar> <enterprise-beans> <entity> <display-name>Cmptable</display-name> <ejb-name>Cmptable</ejb-name> <home>cmp.CmptableRemoteHome</home> <remote>cmp.CmptableRemote</remote> <local-home>cmp.CmptableHome</local-home> <local>cmp.Cmptable</local> <ejb-class>cmp.CmptableBean</ejb-class> <persistence-type>Container</persistence-type> <prim-key-class>cmp.CmptablePK</prim-key-class> <reentrant>False</reentrant> <cmp-version>2.x</cmp-version> <abstract-schema-name>Cmptable</abstract-schema-name> <cmp-field> <field-name>id</field-name> </cmp-field> <cmp-field> <field-name>name</field-name> </cmp-field> <query> <query-method> <method-name>findByName</method-name> <method-params> <method-param>java.lang.String</method-param> </method-params> </query-method> <ejb-ql>SELECT OBJECT FROM Cmptable AS p WHERE p.name=?1</ejb-ql> </query> <query> <query-method> <method-name>findAll</method-name> <method-params /> </query-method> <ejb-ql>SELECT OBJECT FROM Cmptable AS p WHERE p.id IS NOT NULL</ejb-ql> </query> </entity> </enterprise-beans> <assembly-descriptor> <container-transaction> <method> <ejb-name>Cmptable</ejb-name> <method-name>*</method-name> </method> <trans-attribute>Required</trans-attribute> </container-transaction> </assembly-descriptor> </ejb-jar> ***************************************** Jboss.xml <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE jboss PUBLIC '-//JBoss//DTD JBOSS 3.0//EN' 'http://www.jboss.org/j2ee/dtd/jboss_3_0.dtd'> <jboss> <enterprise-beans> <entity> <ejb-name>Cmptable</ejb-name> <jndi-name>CmptableRemote</jndi-name> <local-jndi-name>Cmptable</local-jndi-name> </entity> </enterprise-beans> </jboss> ******************************************* Jbosscmp-jdbc.xml <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE jbosscmp-jdbc PUBLIC '-//JBoss//DTD JBOSSCMP-JDBC 3.0//EN' 'http://www.jboss.org/j2ee/dtd/jbosscmp-jdbc_3_0.dtd'> <jbosscmp-jdbc> <enterprise-beans> <entity> <ejb-name>Cmptable</ejb-name> <table-name>cmptable</table-name> <cmp-field> <field-name>id</field-name> <column-name>id</column-name> </cmp-field> <cmp-field> <field-name>name</field-name> <column-name>name</column-name> </cmp-field> </entity> </enterprise-beans> </jbosscmp-jdbc> *********************************** 服务器那边跟你写的是一样的,只不过少几个方法。 对了,程序在运行时,从Jboss端可以看到提示 setEntityContext called ejbCreate() called ejbPostCreate() called ejbStore() called. setEntityContext called ejbCreate() called ejbPostCreate() called ejbStore() called. setEntityContext called ejbCreate() called ........ |
16.Re:(原创)建立并运行一个简单的CMP的全过程(WEBLOGIC7.0) [Re: struggle] | Copy to clipboard |
Posted by: struggle Posted on: 2003-07-04 10:25 既然您用的是JBOSS+MYSQL可以看这篇文章: http://www.cjsdn.com/post/view?bid=2&id=34190&sty=1 提醒一句,如果您用的是JBOSS3.2那么源代码中有一句要 改一下,如果用的是JBOSS3.0.X就无所谓了。 |
17.Re:(原创)建立并运行一个简单的CMP的全过程(WEBLOGIC7.0) [Re: struggle] | Copy to clipboard |
Posted by: bruce Posted on: 2003-07-04 10:52 struggle, 非常感谢您如此快速的回复 我用的是Jboss3.2.1. 正在找问题的原因, 不过你说的 >>如果您用的是JBOSS3.2那么源代码中有一句要 >>改一下,如果用的是JBOSS3.0.X就无所谓了 能再说详细一点吗? |
18.Re:(原创)建立并运行一个简单的CMP的全过程(WEBLOGIC7.0) [Re: struggle] | Copy to clipboard |
Posted by: struggle Posted on: 2003-07-04 11:10 在JBOSS3.2.X下,文件ProductBean.java中的ejbCreate方法必须抛出 createException异常。JBOSS3.0.X下则不一定必须抛出此异常。 现在我就去改源码,让它能够在JBOSS3.2.X和3.0.X下都能运行。 |
19.Re:(原创)建立并运行一个简单的CMP的全过程(WEBLOGIC7.0) [Re: struggle] | Copy to clipboard |
Posted by: bruce Posted on: 2003-07-04 11:40 struggle, 感谢你热心的帮助! 不过EJB的CMP已经是让很多程序员不满, 我最近正在琢磨Hibernate, 一个非常好的O-R Maping 工具, 有时间你也可以试试。 你所说的多表之间的复杂关系在Hibernate中可以很轻松的实现。 由于有事,我只能晚上再来了, |
20.Re:(原创)建立并运行一个简单的CMP的全过程(WEBLOGIC7.0) [Re: struggle] | Copy to clipboard |
Posted by: mengzhihai Posted on: 2003-07-04 15:37 stuggle帮我看看...在jb中编译时提示如下错误..... "Products.ejbgrpx": ERROR: Error from ejbc: "Products.ejbgrpx": In EJB Products, the ejbCreate method: ejbCreate(java.lang.String,java.lang.String,java.lang.String,double) must return the primary key type. "Products.ejbgrpx": ERROR: ejbc found errors 总是提示返回值的问题:起初是本地接口中,然后我把productsPK改成Object... 就又提示ejbCreate方法了.... 代码如下:多谢了!!! ProductsBean.java package product; import javax.ejb.*; abstract public class ProductsBean implements EntityBean { EntityContext entityContext; public ProductsPK ejbCreate(String productID, String name, String description, double basePrice) throws CreateException { System.out.println("ejbCreate() called"); setProductId(productID); setName(name); setDescription(description); setBasePrice(basePrice); return new ProductsPK(productID); } public void ejbPostCreate(String productID, String name, String description, double basePrice) throws CreateException { System.out.println("ejbPostCreate() called"); } public void ejbRemove() throws RemoveException { System.out.println("ejbRemove() called."); } public abstract void setProductId(java.lang.String productId); public abstract void setName(java.lang.String name); public abstract void setBasePrice(double basePrice); public abstract void setDescription(java.lang.String description); public abstract java.lang.String getProductId(); public abstract java.lang.String getName(); public abstract double getBasePrice(); public abstract java.lang.String getDescription(); public void ejbLoad() { System.out.println("ejbLoad() called."); } public void ejbStore() { System.out.println("ejbStore() called."); } public void ejbActivate() { System.out.println("ejbActivate() called."); } public void ejbPassivate() { System.out.println("ejbPassivate() called."); } public void unsetEntityContext() { System.out.println("unsetEntiryContext called"); this.entityContext = null; } public void setEntityContext(EntityContext entityContext) { System.out.println("setEntiryContext called"); this.entityContext = entityContext; } } ProductsPK.java package product; import java.io.Serializable; public class ProductsPK implements Serializable { public String productId; public ProductsPK(){ } public ProductsPK (String productId){ this.productId=productId; } public boolean equals(Object obj){ if(obj!=null){ if(this.getClass().equals(obj.getClass())){ ProductsPK that=(ProductsPK)obj; return(((this.productId==null)&&(that.productId==null))||(this.productId!=null&&this.productId.equals(that.productId))); } } return false; } public int hashCode(){ return productId.hashCode(); } public String toString(){ return productId.toString(); } } ProductsRemote.java package product; import javax.ejb.*; import java.util.*; import java.rmi.*; import java.math.*; public interface ProductsRemote extends javax.ejb.EJBObject { //public void setProductId(String productId) throws RemoteException; public String getProductId() throws RemoteException; public void setName(String name) throws RemoteException; public String getName() throws RemoteException; public void setBasePrice(double basePrice) throws RemoteException; public double getBasePrice() throws RemoteException; public void setDescription(String description) throws RemoteException; public String getDescription() throws RemoteException; } ProductsRemoteHome.java package product; import javax.ejb.*; import java.util.*; import java.rmi.*; public interface ProductsRemoteHome extends javax.ejb.EJBHome { public ProductsRemote create(String productID, String name, String description, double basePrice) throws CreateException, RemoteException; public Collection findByName(String name) throws FinderException, RemoteException; public Collection findByDexcription(String description) throws FinderException, RemoteException; public Collection findByBasePrice(double basePrice) throws FinderException, RemoteException; public Collection findExpensiveProducts(double minPrice) throws FinderException, RemoteException; public Collection findCheapProducts(double maxPrice) throws FinderException, RemoteException; public Collection findAllProducts() throws FinderException, RemoteException; public ProductsRemote findByPrimaryKey(Object pk) throws FinderException,RemoteException; } 我把上面的findByPrimaryKey中参数的类型换成主键类类型,提示如下错误: "Products.ejbgrpx": ERROR: Error from ejbc: In EJB Products, the home interface's findByPrimaryKey methods parameter must be the primary key type or java.lang.Object: {1} "Products.ejbgrpx": ERROR: ejbc found errors 改成object后提示上面错误.... 多谢!!!! |
21.Re:(原创)建立并运行一个简单的CMP的全过程(WEBLOGIC7.0) [Re: struggle] | Copy to clipboard |
Posted by: struggle Posted on: 2003-07-04 16:01 你在JB里建立的时候前后要一致。指定主键类的话,代码中一定要反应出来。 如果没指定主键类,ejbCreate()就要返回String。 你的代码肯定有问题。这两天我想写一篇JB7+JBOSS3.0下的两个表的CMP,并 用四个JSP文件来调用,到时敬请关注. |
Powered by Jute Powerful Forum® Version Jute 1.5.6 Ent Copyright © 2002-2021 Cjsdn Team. All Righits Reserved. 闽ICP备05005120号-1 客服电话 18559299278 客服信箱 714923@qq.com 客服QQ 714923 |