twinlj77
发贴: 4
积分: 0
|
于 2006-03-30 09:55
昨天一直在调试productBean.以前也作过的,是使用使用持久化域中的productID字符串域作为主键使用, Ed Roman 的精通EJB (第三版)中 虽然提供了ProductPK 类,但在productBean 和 部署描述符 ejb-jar.xml中 却使用的是productID做主建, 前几天也看过不少文章介绍做productBean但是都没有用到ProductPK 类
实体bean可以自定义主键类,这次就用自定义(Ed Roman's)的ProductPK主键类 调试ProductBean ProductPK.java package examples.cmp;
import java.io.Serializable;
public class ProductPK implements Serializable { /* * Note that the primary key fields must be a * subset of the the container-managed Bean fields. * The fields we are marking as container-managed in * our Bean are productID, name, desc, and basePrice. * Therefore our PK fields need to be from that set. */ public String productID;
public ProductPK(String productID) { this.productID = productID; }
public ProductPK() { }
public String toString() { return productID.toString(); }
public int hashCode() { return productID.hashCode(); }
public boolean equals(Object prod) { return ((ProductPK)prod).productID.equals(productID); } }
下面给出ProductBean的代码: 呵呵 ,因为是在JBossIDE下调试, 添加了xdoclet标记! 其他product接口,product home 接口 和 部署描述符 自动生成;
package examples.cmp;
import java.rmi.RemoteException;
import javax.ejb.EJBException; import javax.ejb.EntityBean; import javax.ejb.EntityContext; import javax.ejb.RemoveException;
/** * @ejb.bean name="Product" * display-name="Name for Product" * description="Description for Product" * jndi-name="ejb/Product" * type="CMP" * cmp-version="2.x" * view-type="remote" * * *@ejb.finder signature="java.util.Collection findAllProducts()" * query="SELECT DISTINCT OBJECTFROM products p WHERE p.productID IS NOT NULL" * *@ejb.finder signature="java.util.Collection findByName(java.lang.String name)" * query="SELECT DISTINCT OBJECT FROM products p WHERE p.name = ?1" * *@ejb.finder signature="java.util.Collection findByDescription(java.lang.String description)" * query="SELECT DISTINCT OBJECT FROM products p WHERE p.description = ?1" * *@ejb.finder signature="java.util.Collection findByBasePrice(double basePrice)" * query="SELECT DISTINCT OBJECT FROM products p WHERE p.basePrice =?1" * */ public abstract class ProductBean implements EntityBean { protected EntityContext ctx; public ProductBean() { super(); // TODO Auto-generated constructor stub }
public void ejbActivate() throws EJBException, RemoteException { System.out.println("ejbActivate() called"); }
public void ejbLoad() throws EJBException, RemoteException { // TODO Auto-generated method stub System.out.println("ejbLoad() called"); }
public void ejbPassivate() throws EJBException, RemoteException { // TODO Auto-generated method stub System.out.println("ejbPassivate() called"); }
public void ejbRemove() throws RemoveException, EJBException, RemoteException { // TODO Auto-generated method stub System.out.println("ejbRemove() called"); }
public void ejbStore() throws EJBException, RemoteException { // TODO Auto-generated method stub System.out.println("ejbStore() called"); }
public void setEntityContext(EntityContext ctx) throws EJBException, RemoteException { // TODO Auto-generated method stub System.out.println("setEntityContext called called"); this.ctx = ctx; }
public void unsetEntityContext() throws EJBException, RemoteException { // TODO Auto-generated method stub System.out.println("unsetEntityContext called called"); this.ctx = null; }
/** * Getter for CMP Field name * * * @ejb.persistent-field * @ejb.interface-method view-type="remote" */ public abstract String getName();
/** * Setter for CMP Field name * * @ejb.interface-method view-type="remote" */ public abstract void setName(String value);
/** * Getter for CMP Field description * * * @ejb.persistent-field * @ejb.interface-method view-type="remote" */ public abstract String getDescription();
/** * Setter for CMP Field description * * @ejb.interface-method view-type="remote" */ public abstract void setDescription(String value);
/** * Getter for CMP Field basePrice * * * @ejb.persistent-field * @ejb.interface-method view-type="remote" */ public abstract double getBasePrice();
/** * Setter for CMP Field basePrice * * @ejb.interface-method view-type="remote" */ public abstract void setBasePrice(double basePrice);
/** * Create method * @ejb.create-method view-type = "remote" */ public ProductPK ejbCreate( String productID, String name, String description, double basePrice) throws javax.ejb.CreateException { System.out.println("ejbCreate() called");
setName(name); setDescription(description); setBasePrice(basePrice); setProductID(productID); return new ProductPK(productID); } /** * Post Create method */ public void ejbPostCreate( String productID, String name, String description, double basePrice) throws javax.ejb.CreateException { // TODO Auto-generated method stub }
/** * Getter for CMP Field productID * * * @ejb.persistent-field * @ejb.interface-method view-type="remote" */ public abstract String getProductID();
/** * Setter for CMP Field productID * * @ejb.interface-method view-type="remote" */ public abstract void setProductID(String value);
}
执行 Xdoclet Configuration 后 生成的ProductHome中 public examples.interfaces.Product findByPrimaryKey(examples.interfaces.ProductPK pk) throws javax.ejb.FinderException,java.rmi.RemoteException; 提示有错误: 将examples.interfaces.ProductPK 改为 examples.cmp.ProductPK 即可 自动生成的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 >
<description><![CDATA[No Description.]]></description> <display-name>Generated by XDoclet</display-name>
<enterprise-beans>
<!-- Session Beans --> <!-- To add session beans that you have deployment descriptor info for, add a file to your XDoclet merge directory called session-beans.xml that contains the <session></session> markup for those beans. -->
<!-- Entity Beans --> <entity > <description><![CDATA[Description for Product]]></description> <display-name>Name for Product</display-name>
<ejb-name>Product</ejb-name>
<home>examples.interfaces.ProductHome</home> <remote>examples.interfaces.Product</remote>
<ejb-class>examples.cmp.ProductBean</ejb-class> <persistence-type>Container</persistence-type> <prim-key-class>examples.interfaces.ProductPK</prim-key-class> <reentrant>False</reentrant> <cmp-version>2.x</cmp-version> <abstract-schema-name>Product</abstract-schema-name> <cmp-field > <description><![CDATA[Getter for CMP Field name]]></description> <field-name>name</field-name> </cmp-field> <cmp-field > <description><![CDATA[Getter for CMP Field description]]></description> <field-name>description</field-name> </cmp-field> <cmp-field > <description><![CDATA[Getter for CMP Field basePrice]]></description> <field-name>basePrice</field-name> </cmp-field> <cmp-field > <description><![CDATA[Getter for CMP Field productID]]></description> <field-name>productID</field-name> </cmp-field>
<query> <query-method> <method-name>findAllProducts</method-name> <method-params> </method-params> </query-method> <ejb-ql><![CDATA[SELECT DISTINCT OBJECTFROM products p WHERE p.productID IS NOT NULL]]></ejb-ql> </query> <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 DISTINCT OBJECT FROM products p WHERE p.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 DISTINCT OBJECT FROM products p WHERE p.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 DISTINCT OBJECT FROM products p WHERE p.basePrice =?1]]></ejb-ql> </query> <!-- Write a file named ejb-finders-ProductBean.xml if you want to define extra finders. -->
</entity>
<!-- To add entity beans that you have deployment descriptor info for, add a file to your XDoclet merge directory called entity-beans.xml that contains the <entity></entity> markup for those beans. -->
<!-- Message Driven Beans --> <!-- To add message driven beans that you have deployment descriptor info for, add a file to your XDoclet merge directory called message-driven-beans.xml that contains the <message-driven></message-driven> markup for those beans. -->
</enterprise-beans>
<!-- Relationships -->
<!-- Assembly Descriptor --> <!-- To specify your own assembly descriptor info here, add a file to your XDoclet merge directory called assembly-descriptor.xml that contains the <assembly-descriptor></assembly-descriptor> markup. -->
<assembly-descriptor > <!-- To specify additional security-role elements, add a file in the merge directory called ejb-security-roles.xml that contains them. -->
<!-- method permissions --> <!-- To specify additional method-permission elements, add a file in the merge directory called ejb-method-permissions.ent that contains them. -->
<!-- transactions --> <!-- To specify additional container-transaction elements, add a file in the merge directory called ejb-container-transactions.ent that contains them. -->
<!-- finder transactions -->
<!-- message destinations --> <!-- To specify additional message-destination elements, add a file in the merge directory called ejb-message-destinations.ent that contains them. -->
<!-- exclude list --> <!-- To specify an exclude-list element, add a file in the merge directory called ejb-exclude-list.xml that contains it. --> </assembly-descriptor>
</ejb-jar> jboss.xml 和jbosscmp-jdbc.xml 在此略去
注意 ,在此应略作修改.此时prim-key-class为: <prim-key-class>examples.interfaces.ProductPK</prim-key-class> 将它改为:<prim-key-class>examples.cmp.ProductPK</prim-key-class>
还有将<abstract-schema-name>Product</abstract-schema-name> 改为 <abstract-schema-name>products</abstract-schema-name> 因为在abstract-schema-name应全是大写或小写字母 products 与 我们在xdoclet标记 query="SELECT DISTINCT OBJECTFROM products p WHERE p.productID IS NOT NULL" 中的表相对应
打包相关文件,并部署.
client测试程序如下: package examples.cmp;
import java.util.Iterator; import java.util.Properties;
import javax.naming.Context; import javax.naming.InitialContext;
import examples.interfaces.Product; import examples.interfaces.ProductHome;
public class ProductClient {
public static void main(String[] args) throws Exception {
ProductHome home = null; Context ctx=null; try { /* * Get a reference to the Product Home Object - the * factory for Product EJB Objects */ try{ Properties p = new Properties(); p.put(Context.INITIAL_CONTEXT_FACTORY, "org.jnp.interfaces.NamingContextFactory"); p.put(Context.URL_PKG_PREFIXES, "jboss.naming:org.jnp.interfaces"); p.put(Context.PROVIDER_URL, "localhost:1099"); ctx = new InitialContext; }catch(Exception e){ System.out.println("Cannot get initial context: " + e.getMessage()); System.exit(1); } home = (ProductHome) javax.rmi.PortableRemoteObject.narrow(ctx.lookup("ejb/Product"), ProductHome.class);
/* * Use the factory to create the Product EJB Object */ 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);
/* * Find a Product, and print out it's description */ 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()); }
/* * Find all products that cost $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..");
/* * Find all the 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(); } } } } } }
运行成功;~! 进入http://localhost:8080/jmx-console 点击jboss项下的 database=localDB,service=Hypersonic involke void startDatabaseManager()方法 会出现一个小的数据库管理系统 Hypersonic 可以看到有个表product已经生成!
有一个的疑问!!!!? 我们是让容器自动生成表的,但是我们定义的表是products 但是容器却自动生成了product,而且程序运行通过了!!!
我想<abstract-schema-name>products</abstract-schema-name> 和 query="SELECT DISTINCT OBJECTFROM products p WHERE p.productID IS NOT NULL" 中的表名必须一致! 但都只是表product的一个别名 容器默认的为entitybean自动生成的表为product与ejb-name相同! <Jboss Adiminstration and Development> <Jboss管理开发核心技术中>有关于如何设置实体映射的实例 可以将实体bean映射为数据库中自定义的表名!
|