📄 bmp3.html
字号:
<a name="wp80061"> </a><p class="pBody"></p><div align="left"><img src="images/Fig152.gif" height="143" width="391" alt="One-to-Many Relationship: Order and Line Items" border="0" hspace="0" vspace="0"/></div><p class="pBody"></p><p> <a name="80063"> </a><strong><font >Figure 21-2 One-to-Many Relationship: Order and Line Items</font></strong></p><a name="wp80064"> </a><p class="pBody">Not only does a line item belong to an order, it also does not exist without the order. Therefore, the <code class="cCode">lineitems</code> table should be represented with a helper class and not with an entity bean. Using a helper class in this case is not required, but doing so might improve performance because a helper class uses fewer system resources than an entity bean.</p><a name="wp80065"> </a><p class="pBody">The source code for the following example is in this directory:</p><div class="pPreformattedRelative"><pre class="pPreformattedRelative"><INSTALL>/j2eetutorial14/examples/ejb/order/src/<a name="wp81002"> </a></pre></div><a name="wp80066"> </a><p class="pBody">The <code class="cCode">LineItem</code> and <code class="cCode">OrderBean</code> classes show how to implement a one-to-many relationship with a helper class (<code class="cCode">LineItem</code>). The instance variables in the <code class="cCode">LineItem</code> class correspond to the columns in the <code class="cCode">lineitems</code> table. The <code class="cCode">itemNo</code> variable matches the primary key for the <code class="cCode">lineitems</code> table, and the <code class="cCode">orderId</code> variable represents the table's foreign key. Here is the source code for the <code class="cCode">LineItem</code> class:</p><div class="pPreformattedRelative"><pre class="pPreformattedRelative">public class LineItem implements java.io.Serializable { String productId; int quantity; double unitPrice; int itemNo; String orderId; public LineItem(String productId, int quantity, double unitPrice, int itemNo, String orderId) { this.productId = productId; this.quantity = quantity; this.unitPrice = unitPrice; this.itemNo = itemNo; this.orderId = orderId; } public String getProductId() { return productId; } public int getQuantity() { return quantity; } public double getUnitPrice() { return unitPrice; } public int getItemNo() { return itemNo; } public String getOrderId() { return orderId; }}<a name="wp80068"> </a></pre></div><a name="wp80069"> </a><p class="pBody">The <code class="cCode">OrderBean</code> class contains an <code class="cCode">ArrayList</code> variable named <code class="cCode">lineItems</code>. Each element in the <code class="cCode">lineItems</code> variable is a <code class="cCode">LineItem</code> object. The <code class="cCode">lineItems</code> variable is passed to the <code class="cCode">OrderBean</code> class in the <code class="cCode">ejbCreate</code> method. For every <code class="cCode">LineItem</code> object in the <code class="cCode">lineItems</code> variable, the <code class="cCode">ejbCreate</code> method inserts a row into the <code class="cCode">lineitems</code> table. It also inserts a single row into the <code class="cCode">orders</code> table. The code for the <code class="cCode">ejbCreate</code> method follows:</p><div class="pPreformattedRelative"><pre class="pPreformattedRelative">public String ejbCreate(String orderId, String customerId, String status, double totalPrice, ArrayList lineItems) throws CreateException { try { insertOrder(orderId, customerId, status, totalPrice); for (int i = 0; i < lineItems.size(); i++) { LineItem item = (LineItem)lineItems.get(i); insertItem(item); } } catch (Exception ex) { throw new EJBException("ejbCreate: " + ex.getMessage()); } this.orderId = orderId; this.customerId = customerId; this.status = status; this.totalPrice = totalPrice; this.lineItems = lineItems ; return orderId;}<a name="wp80071"> </a></pre></div><a name="wp80072"> </a><p class="pBody">The <code class="cCode">OrderClient</code> program creates and loads an <code class="cCode">ArrayList</code> of <code class="cCode">LineItem</code> objects. The program passes this <code class="cCode">ArrayList</code> to the entity bean when it invokes the <code class="cCode">create</code> method:</p><div class="pPreformattedRelative"><pre class="pPreformattedRelative">ArrayList lineItems = new ArrayList();lineItems.add(new LineItem("p23", 13, 12.00, 1, "123"));lineItems.add(new LineItem("p67", 47, 89.00, 2, "123"));lineItems.add(new LineItem("p11", 28, 41.00, 3, "123"));...Order duke = home.create("123", "c44", "open", totalItems(lineItems), lineItems);<a name="wp80074"> </a></pre></div><a name="wp80075"> </a><p class="pBody">Other methods in the <code class="cCode">OrderBean</code> class also access both database tables. The <code class="cCode">ejbRemove</code> method, for example, not only deletes a row from the <code class="cCode">orders</code> table, but also deletes all corresponding rows in the <code class="cCode">lineitems</code> table. The <code class="cCode">ejbLoad</code> and <code class="cCode">ejbStore</code> methods synchronize the state of an <code class="cCode">OrderEJB</code> instance, including the <code class="cCode">lineItems</code> <code class="cCode">ArrayList</code>, with the <code class="cCode">orders</code> and <code class="cCode">lineitems</code> tables.</p><a name="wp80076"> </a><p class="pBody">The <code class="cCode">ejbFindByProductId</code> method enables clients to locate all orders that have a particular product. This method queries the <code class="cCode">lineitems</code> table for all rows with a specific <code class="cCode">productId</code>. The method returns a <code class="cCode">Collection</code> of <code class="cCode">Order</code> objects. The <code class="cCode">OrderClient</code> program iterates through the <code class="cCode">Collection</code> and prints the primary key of each order:</p><div class="pPreformattedRelative"><pre class="pPreformattedRelative">Collection c = home.findByProductId("p67");Iterator i=c.iterator();while (i.hasNext()) { Order order = (Order)i.next(); String id = (String)order.getPrimaryKey(); System.out.println(id);}<a name="wp80079"> </a></pre></div><a name="wp80080"> </a><h4 class="pHeading3">Running the OrderEJB Example</h4><div class="pSmartList1"><ol type="1" class="pSmartList1"><a name="wp81161"> </a><div class="pSmartList1"><li>Create the <code class="cCode">order</code> database table.</li></div><div class="pSmartList2"><ol type="a" class="pSmartList2"><a name="wp81162"> </a><div class="pSmartList2"><li>In a terminal window, go to this directory:</li></div><a name="wp81163"> </a><p class="pBodyRelative"><code class="cCode"><INSTALL>/j2eetutorial14/examples/ejb/order/</code></p><a name="wp81164"> </a><div class="pSmartList2"><li>Type this command:</li></div><a name="wp81227"> </a><p class="pBodyRelative"><code class="cCode">asant create-db_common</code></p></ol></div><a name="wp81166"> </a><div class="pSmartList1"><li>In <code class="cCode">deploytool</code>, deploy the <code class="cCode">OrderApp.ear</code> file, which is in this directory:</li></div><a name="wp81167"> </a><p class="pBodyRelative"><code class="cCode"><INSTALL>/j2eetutorial14/examples/ejb/provided-ears/</code></p><a name="wp81168"> </a><div class="pSmartList1"><li>Run the client.</li></div><div class="pSmartList2"><ol type="a" class="pSmartList2"><a name="wp81169"> </a><div class="pSmartList2"><li>In a terminal window, go to this directory:</li></div><a name="wp81170"> </a><p class="pBodyRelative"><code class="cCode"><INSTALL>/j2eetutorial14/examples/ejb/order/</code></p><a name="wp81171"> </a><div class="pSmartList2"><li>Type the following command on a single line:</li></div><a name="wp81172"> </a><p class="pBodyRelative"><code class="cCode">appclient -client OrderAppClient.jar</code></p><a name="wp81173"> </a><div class="pSmartList2"><li>The client should display the following lines:</li></div><a name="wp81174"> </a><p class="pBodyRelative"><code class="cCode">. . .<br />123 1 p23 12.0<br />123 2 p67 89.0<br />123 3 p11 41.0<br /></code>. . .</p></ol></div></ol></div><a name="wp80092"> </a><h4 class="pHeading3">An Entity Bean for the Child Table</h4><a name="wp80093"> </a><p class="pBody">You should consider building an entity bean for a child table under the following conditions:</p><div class="pSmartList1"><ul class="pSmartList1"><a name="wp80094"> </a><div class="pSmartList1"><li>The information in the child table is not dependent on the parent table.</li></div><a name="wp80095"> </a><div class="pSmartList1"><li>The business entity of the child table could exist without that of the parent table.</li></div><a name="wp80096"> </a><div class="pSmartList1"><li>The child table might be accessed by another application that does not access the parent table.</li></div></ul></div><a name="wp80097"> </a><p class="pBody">These conditions exist in the following scenario. Suppose that each sales representative in a company has multiple customers and that each customer has only one sales representative. The company tracks its sales force with a database application. In the database, each row in the <code class="cCode">salesrep</code> table (parent) matches multiple rows in the <code class="cCode">customer</code> table (child). <a href="BMP3.html#wp80106">Figure 21-3</a> illustrates this relationship.</p><a name="wp80104"> </a><p class="pBody"></p><div align="left"><img src="images/Fig163.gif" height="142" width="395" alt="One-to-Many Relationships: Sales Representatives and Customers" border="0" hspace="0" vspace="0"/></div><p class="pBody"></p><p> <a name="80106"> </a><strong><font >Figure 21-3 One-to-Many Relationship: Sales Representative and Customers</font></strong></p><a name="wp80107"> </a><p class="pBody">The <code class="cCode">SalesRepBean</code> and <code class="cCode">CustomerBean</code> entity bean classes implement the one-to-many relationship of the <code class="cCode">sales</code> and <code class="cCode">customer</code> tables.</p><a name="wp80108"> </a><p class="pBody">The source code for this example is in this directory:</p><div class="pPreformattedRelative"><pre class="pPreformattedRelative"><INSTALL>/j2eetutorial14/examples/ejb/salesrep/src/<a name="wp81014"> </a></pre></div><a name="wp80109"> </a><p class="pBody">The <code class="cCode">SalesRepBean</code> class contains a variable named <code class="cCode">customerIds</code>, which is an <code class="cCode">ArrayList</code> of <code class="cCode">String</code> elements. These <code class="cCode">String</code> elements identify which customers belong to the sales representative. Because the <code class="cCode">customerIds</code> variable reflects this relationship, the <code class="cCode">SalesRepBean</code> class must keep the variable up to date.</p><a name="wp80110"> </a><p class="pBody">The <code class="cCode">SalesRepBean</code> class instantiates the <code class="cCode">customerIds</code> variable in the <code class="cCode">setEntityContext</code> method, not in <code class="cCode">ejbCreate</code>. The container invokes <code class="cCode">setEntityContext</code> just once--when it creates the bean instance--ensuring that <code class="cCode">customerIds</code> is instantiated just once. Because the same bean instance can assume different identities during its life cycle, instantiating <code class="cCode">customerIds</code> in <code class="cCode">ejbCreate</code> might cause multiple and unnecessary instantiations. Therefore, the <code class="cCode">SalesRepBean</code> class instantiates the <code class="cCode">customerIds</code> variable in <code class="cCode">setEntityContext</code>:</p><div class="pPreformattedRelative"><pre class="pPreformattedRelative">public void setEntityContext(EntityContext context) { this.context = context; customerIds = new ArrayList(); try { Context initial = new InitialContext(); Object objref = initial.lookup("java:comp/env/ejb/Customer"); customerHome = (CustomerHome)PortableRemoteObject.narrow(objref, CustomerHome.class); } catch (Exception ex) { throw new EJBException("setEntityContext: " + ex.getMessage()); }}<a name="wp80112"> </a></pre></div><a name="wp80114"> </a><p class="pBody">Invoked by the <code class="cCode">ejbLoad</code> method, <code class="cCode">loadCustomerIds</code> is a private method that refreshes the <code class="cCode">customerIds</code> variable. There are two approaches when coding a method such as <code class="cCode">loadCustomerIds</code>: fetch the identifiers from the <code class="cCode">customer</code> database table or get them from the <code class="cCode">CustomerEJB</code> entity bean. Fetching the identifiers from the database might be faster, but exposes the code in the <code class="cCode">SalesRepBean</code> class to the <code class="cCode">CustomerEJB </code>bean's underlying database table. In the future, if you were to change the <code class="cCode">CustomerEJB</code> bean's table (or move the bean to a different J2EE server), you might need to change the <code class="cCode">SalesRepBean</code> code. But if the <code class="cCode">SalesRepBean</code> class gets the identifiers from the <code class="cCode">CustomerEJB</code> entity bean, no coding changes would be required. The two approaches present a trade-off: performance versus flexibility. The <code class="cCode">SalesRepEJB</code> example opts for flexibility, loading the <code class="cCode">customerIds</code> variable by calling the <code class="cCode">findBySalesRep</code> and <code class="cCode">getPrimaryKey</code> methods of <code class="cCode">CustomerEJB</code>. Here is the code for the <code class="cCode">loadCustomerIds</code> method:</p><div class="pPreformattedRelative"><pre class="pPreformattedRelative">private void loadCustomerIds() { customerIds.clear(); try { Collection c = customerHome.findBySalesRep(salesRepId); Iterator i=c.iterator();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -