1. Trang chủ
  2. » Công Nghệ Thông Tin

Java Database Programming Bible- P12

50 326 0
Tài liệu đã được kiểm tra trùng lặp

Đang tải... (xem toàn văn)

Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống

THÔNG TIN TÀI LIỆU

Thông tin cơ bản

Định dạng
Số trang 50
Dung lượng 823,97 KB

Nội dung

Chapter 22:Container -Managed Persistence -551 - * @author: Andrew Yang * @version: 1.0 */ package java_database.YachtEBean; import java.rmi.*; import java.util.*; import javax.ejb.*; public interface YachtHome extends EJBHome { public Yacht create(String yachtName, String builder, String engineType, int capacity, int maxVelocity) throws CreateException, RemoteException; public Yacht findByPrimaryKey(String yachtName) throws FinderException, RemoteException; public Collection findAllYachts() throws FinderException, RemoteException; public Collection findYachtsCapacityMoreThan(int minCapacity) throws FinderException, RemoteException; } Listing 22-2: Remote interface of YachtEJB /** YachtEJB Remote Interface. CMP is used. * @author: Andrew Yang * @version: 1.0 */ package java_database.YachtEBean; import java.rmi.*; import javax.ejb.*; import common.*; import YachtSessionSFBean.*; public interface Yacht extends EJBObject { public YachtSession createYachtSession() throws RemoteException; public String getBuilder() throws RemoteException; public String getEngineType() throws RemoteException; public int getCapacity() throws RemoteException; public int getMaxVelocity() throws RemoteException; } TEAMFLY Team-Fly ® Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. Chapter 22:Container -Managed Persistence -552 - Although multiple create methods can be defined, only one create method is defined in the home interface for simplicity. The create method takes all of the five persistent fields as argument. The remote interface defines the getters for four out of the five persistent fields, except the primary key field. The client can get the primary key field, yachtName, by calling the getPrimaryKey method of the EJBHome class or EntityContext class. Three finder methods are defined in the home interface with different data-retrieval criteria. The findByPrimaryKey is required and returns only one reference to YachtEJB that the primary key identifies. It may return null if no match is found. The other two methods return a collection of references to YachtEJB objects. There are only getters; no setters are defined in the remote interface; therefore the YachtEJB is apparently defined as read only (after created) from the clients' point of view. If the clients also need to modify the persistent state, setters for the persistent fields must be defined in the remote interface. Although getters and setters are defined in the remote interface, you do not need to code their implementations, as you see in the next section. Implementation Class with Minimum Code In EJB 1.1, a persistent field was identified in the deployment descriptor and also identified as a public instance variable of your bean implementation class. In EJB 2.0, this approach has been radically changed. Persistent fields are still identified in the deployment descriptor, but they are not identified as public-instance variables. Instead, they are identified through specialized getters and setters that you must write. For example, you have to write getYachtName, setBuilder, and so on in the YachtEJB implementation class. What is intriguing is that these methods are declared as abstract and are implemented automatically by the EJB container during the deployment phase. That makes the implementation class also abstract; thus, no instance can be instantiated directly for the implementation class. The EJB container uses the information you provide in the deployment descriptor to automatically generate a concrete class with all the database-access implementations. The objects of these container-generated, concrete classes are used at runtime for clients' invocation. The implementation class of the example YachtEJB is shown in Listing 22-3. Listing 22-3: Implementation class of YachtEJB /** YachtEJB Implementation Class. CMP is used. * @author: Andrew Yang * @version: 1.0 */ package java_database.YachtEBean; import java.rmi.*; import java.util.*; import java.sql.*; import javax.ejb.*; import javax.naming.*; import common.*; import YachtSessionSFBean.*; public abstract class YachtBean implements EntityBean { private EntityContext context; Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. Chapter 22:Container -Managed Persistence -553 - private InitialContext ctx; public YachtBean() { try { ctx = new InitialContext(); } catch (Exception e) { System.out.println("Problem getting InitialContext!"); } } public void setEntityContext(EntityContext ctx) { this.context = ctx; } public void unsetEntityContext() { } public void ejbActivate() { } public void ejbPassivate() { } public void ejbLoad() { } public void ejbStore() { } public void ejbRemove() throws RemoveException { // nothing to code } // Container managed fields public abstract String getYachtName(); public abstract String getBuilder(); public abstract String getEngineType(); public abstract int getCapacity(); public abstract int getMaxVelocity(); public abstract void setYachtName(String s); public abstract void setBuilder(String s); public abstract void setEngineType(String s); public abstract void setCapacity(int n); public abstract void setMaxVelocity(int n); public String ejbCreate(String yachtName, String builder, String engineType, int capacity, int maxVelocity) throws CreateException { // You have to call accessor methods here. setYachtName(yachtName); setBuilder(builder); setEngineType(engineType); setCapacity(capacity); setMaxVelocity(maxVelocity); // If int values passed in are zero, pull the value from the constant file. if(capacity <= 0) { setCapacity(YachtConstants.CAPACITY); } if(maxVelocity <= 0) { setMaxVelocity(YachtConstants.MAX_VELOCITY); } Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. Chapter 22:Container -Managed Persistence -554 - // Always return null return null; } public void ejbPostCreate(String yachtName, String builder, String engineType, int capacity, int maxVelocity) { // nothing to code } // Business Methods public YachtSession createYachtSession() { YachtSession session = null; try { YachtSessionHome home = (YachtSessionHome)ctx.lookup( "java:comp/env/ejb/YachtSessionEJB"); // In order to create a YachtSession instance, we must pass // in a reference to this Yacht EJB's remote stub. session = (YachtSession)home.create((Yacht)context.getEJBObject()); } catch (Exception e) { System.out.println("Failed to create YachtSession: " + e); } return session; } } You may be impressed by how little you have to code. Compared with the BMP implementation given in Listing 21-6, the CMP implementation class has much less code. This leads to one of the major advantages of CMP entity bean — a fast development cycle. From Listing 22-3, you see that the implementation classes have defined five abstract getters and five abstract setters for the five persistent fields. The concrete implementation is automatically generated by the EJB container based on the information provided in the deployment descriptor. As an example, the YachtEJB's deployment descriptor for WebLogic Application Server 6.0 is shown in Listing 22-4. If you use another application server, your deployment descriptor files may look slightly different. When your application contains multiple EJBs, and some other components such as servlets, the deployment descriptor can be very long and complex. Therefore, you should never write your deployment descriptors with a text editor. Instead, always use the deployment tool provided by your application server. These XML files should always be generated by your application server, just as all the concrete implementations of the abstract EJB methods are automatically generated by EJB container. Note Do not use a text editor to write a deployment descriptor. Use the deployment tool provided by your application server. Listing 22-4: Deployment descriptor for YachtEJB # First DD File – J2EE Standard Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. Chapter 22:Container -Managed Persistence -555- <!DOCTYPE ejb-jar PUBLIC "-//Sun Microsystems, Inc.//DTD Enterprise JavaBeans 2.0//EN" "http://java.sun.com/j2ee/dtds/ejb-jar_2_0.dtd"> <ejb-jar> <enterprise-beans> <entity> <ejb-name>YachtEJB</ejb-name> <home>YachtEBean.YachtHome</home> <remote>YachtEBean.Yacht</remote> <ejb-class>YachtEBean.YachtBean</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>YachtBean</abstract-schema-name> <primkey-field>yachtName</primkey-field> <cmp-field><field-name>builder</field-name></cmp-field> <cmp-field><field-name>engineType</field-name></cmp-field> <cmp-field><field-name>capacity</field-name></cmp-field> <cmp-field><field-name>maxVelocity</field-name></cmp-field> <ejb-ref> <description>The YachtEJB does a lookup for YachtSession beans.</description> <ejb-ref-name>ejb/YachtSessionEJB</ejb-ref-name> <ejb-ref-type>Session</ejb-ref-type> <home>YachtSessionSFBean.YachtSessionHome</home> <remote>YachtSessionSFBean.YachtSession</remote> </ejb-ref> <query> <query-method> <method-name>findAllYachts</method-name> <method-params></method-params> </query-method> <ejb-ql><![CDATA[WHERE yachtName IS NOT NULL]]></ejb-ql> </query> <query> <query-method> <method-name>findYachtsCapacityMoreThan</method-name> <method-params> <method-param>int</method-param> </method-params> </query-method> <ejb-ql><![CDATA[FROM YachtBean cb WHERE cb.capacity > ?1]]></ejb- ql> Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. Chapter 22:Container -Managed Persistence -556 - </query> </entity> </enterprise-beans> <assembly-descriptor> <security-role> <description>The group of users allowed to access YachtEJBs.</description> <role-name>ValidYachtClubUsers</role-name> </security-role> <container-transaction> <method> <ejb-name>YachtEJB</ejb-name> <method-intf>Remote</method-intf> <method-name>*</method-name> </method> <trans-attribute>Required</trans-attribute> </container-transaction> </assembly-descriptor> </ejb-jar> # Second DD File – Weblogic Specific <!DOCTYPE weblogic-ejb-jar PUBLIC '-//BEA Systems, Inc.//DTD WebLogic 6.0.0 EJB//EN' 'http://www.bea.com/servers/wls60/ejb20/dtd/weblogic-ejb-jar.dtd'> <weblogic-ejb-jar> <weblogic-enterprise-bean> <ejb-name>YachtEJB</ejb-name> <entity-descriptor> <entity-cache> <max-beans-in-cache>150</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> <reference-descriptor> Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. Chapter 22:Container -Managed Persistence -557 - <ejb-reference-description> <ejb-ref-name>ejb/YachtSessionEJB</ejb-ref-name> <jndi-name>YachtSessionEJB</jndi-name> </ejb-reference-description> </reference-descriptor> <jndi-name>YachtEJB</jndi-name> </weblogic-enterprise-bean> <security-role-assignment> <role-name>ValidYachtClubUsers</role-name> <principal-name>system</principal-name> </security-role-assignment> </weblogic-ejb-jar> # Third DD File – Persistent Field Mapping, Weblogic Specific <!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>YachtEJB</ejb-name> <data-source-name>yachtClub-datasource</data-source-name> <table-name>yacht</table-name> <field-map> <cmp-field>yachtName</cmp-field> <dbms-column>yacht_name</dbms-column> </field-map> <field-map> <cmp-field>builder</cmp-field> <dbms-column>builder</dbms-column> </field-map> <field-map> <cmp-field>engineType</cmp-field> <dbms-column>engine_type</dbms-column> </field-map> <field-map> <cmp-field>capacity</cmp-field> <dbms-column>capacity</dbms-column> </field-map> <field-map> <cmp-field>maxVelocity</cmp-field> <dbms-column>max_velocity</dbms-column> </field-map> Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. Chapter 22:Container -Managed Persistence -558- </weblogic-rdbms-bean> </weblogic-rdbms-jar> Recall that the deployment-descriptor files are supposedly read by the EJB container, not by people. I list them here just for the demonstration of some key concepts. Don't try to write or read these files using a text editor. Use the deployment tools instead. As you see from the Listing 22-4, you specify the abstract schema name (YachtBean), the primary key field (yachtName), and all other persistent fields (builder, engineType, capacity and maxVelocity) in the deployment descriptor, as follows: <persistence-type>Container</persistence-type> <abstract-schema-name>YachtBean</abstract-schema-name> <primkey-field>yachtName</primkey-field> <cmp-field><field-name>builder</field-name></cmp-field> <cmp-field><field-name>engineType</field-name></cmp-field> <cmp-field><field-name>capacity</field-name></cmp-field> <cmp-field><field-name>maxVelocity</field-name></cmp-field> You further declare the persistent type as CMP, as shown here: <persistence-type>Container</persistence-type> <persistence-type> <type-identifier>WebLogic_CMP_RDBMS</type-identifier> … … </persistence-type> You then define the mapping between YachtEJB and the underlying persistent store (yachtClub- datasource) by specifying the mapping between each persistent field and its corresponding table- column name (such as yachtName mapped to yacht_name, maxVelocity mapped to max_velocity, and so on), as follows: <ejb-name>YachtEJB</ejb-name> <data-source-name>yachtClub-datasource</data-source-name> <table-name>yacht</table-name> <field-map> <cmp-field>yachtName</cmp-field> <dbms-column>yacht_name</dbms-column> </field-map> <field-map> <cmp-field>builder</cmp-field> <dbms-column>builder</dbms-column> </field-map> … … Such information tells the EJB container to implement the access calls for these persistent fields. Based on the deployment information, the EJB container determines the approperate JDBC implementations (that is, the SQL calls) for the persistent fields and keeps a CMP bean's persistent field synchronized with the state of the database record it represents. After the concrete classes are generated during the Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. Chapter 22:Container -Managed Persistence -559 - deployment phase, the life cycle of these CMP bean instances are same as that of BMP instances discussed in the previous Chapter 21. For each create method defined in the home interface, you need to write a corresponding ejbCreate method. As a bean developer, your job is to assign the persistent fields with their initial values by calling the setters. You may find something weird by looking at the implementation shown in Listing 21-3. Although the return type is supposed to be the primary key, the ejbCreate method actually returns null at the end of the code. This is required by EJB specification. The rationale is that this method will only be called by the EJB container and that the container always knows exactly what the primary key is for each EJB. Note For a BMP bean, you must write code for the ejbRemove method. For a CMP bean, since the database-access logic is implemented by the EJB container, you typically do not need to write any code. In the code shown in Listing 22-3, you do not see even the empty implementation of any finder method defined in the home interface. How does the EJB container generate the implementation for finder methods? For the method findByPrimaryKey, the container knows how to implement it by looking at the primary key class type in the deployment descriptor and the corresponding database column specified. For implanting all other methods, the EJB container follows your orders, given in the form of EJB QL in the deployment descriptor. The EJB QL is discussed in detail later. You still need to implement all the business methods defined in the remote interface, except for the getters and setters. In the YachtBean, you only need to code the business method createYachtSession. You first look up the YachtSessionEJB's home interface from JNDI, then create a remote interface handle. Since this will always be an EJB-to-EJB call, you may want to use YachtSessionEJB's local interface for better performance. To summarize this discussion, Table 22-2 lists major differences between coding a BMP bean implementation class and coding a CMP implementation class. All the database-access calls by bean developers for BMP beans are automatically generated by the EJB container. Since the bean- implementation classes you write contain no implementations, it is important to declare them as abstract. The corresponding concrete classes are automatically generated by EJB container at the deployment phase. Table 22-2: Coding Differences between CMP and BMP Item CMP BMP Class Definition Abstract Not abctract Database access calls Generated by tools Coded by developers Persistent state Represented by virtual persistent fields Coded as instance variables Accessor to persistent and relationship fields Required None Customized finder methods Handled by EJB container (but the developer must define the EJB QL queries) Coded by developers Select Methods (??) Handled by EJB container None Return type of ejbCreate method null Primary key With CM entity bean, no database code is needed. The database access functionality is specified by EJB developers or application assemblers in description descriptor in EJB Query language that is discussed next. Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. Chapter 22:Container -Managed Persistence -560- EJB Query Language The EJB Query Language (EJB QL) is used to define query methods (for example, finder and select methods) for CMP entity beans. EJB QL, which is based on SQL-92, can be compiled automatically by the EJB container to a target language, such as SQL, of a database or other types of persistent stores. This makes CMP entity beans more portable and much easier to deploy. An EJB QL query has these three clauses: § SELECT § FROM § WHERE The SELECT and FROM clauses are required, but the WHERE clause is optional. Here is the high-level BNF syntax of an EJB QL query: EJB QL :: = select_clause from_clause [where_clause] The SELECT clause defines the types of the objects or values that the query returns. A return type is a remote interface, a local interface, or a persistent field. The FROM clause defines the scope of the query by declaring one or more identification variables, which may be referenced in the SELECT and WHERE clauses. An identification variable represents one of the following elements: § The abstract schema name of an entity bean § A member of a collection that is the multiple side of a one-to-many relationship The WHERE clause is a conditional expression that restricts the objects or values retrieved by the query. Although this is optional, most queries have a WHERE clause. You now may have found that the syntax of EJB QL is quite similar to the syntax of SQL. They do have a lot of similarities. However, EJB QL is not like SQL in the following aspects: § SQL deals with tables and rows, but EJB QL deals with objects and instances. § SQL has many built-in functions that EJB QL does not have. § The result of an EJB QL is a remote interface or a collection of remote interfaces. For each method (except the findByPrimaryKey method) in your CMP entity bean, there must be a <query> tag that describes this finder method. In the deployment descriptor, the EJB QL must be wrapped in an expression that looks like this: <!CDATA[expression]]> expression is a valid EJB QL statement. The CDATA statement is not necessary but is recommended because it escapes the reserved characters of XML. Since the object to be selected is obvious for these finder methods, you do not need to put the SELECT clause into the expression. In many cases, if the data is selected from a single entity bean object and there is no relationship that needs to be specified, the FROM clause can be omitted too. Look at the deployment descriptor shown in Listing 22-4. The EJB QL for the findAllYachts method is as follows: <ejb-ql><![CDATA[WHERE yachtName IS NOT NULL]]></ejb-ql> This is translated to the following SQL statement by EJB container at the deployment phase if, for example, an Oracle database is used: SELECT * FROM yacht The EJB QL for the findYachtsCapacityMoreThan method is as follows: <ejb-ql><![CDATA[FROM YachtBean cb WHERE cb.capacity > ?1]]></ejb-ql> It may be translated into a SQL statement like this: Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark. [...]... a Java compiler into bytecode, the Java class files are fed into the JDO enhancer, along with the XML MetaData file The enhancer modifies the bytecode by doing the following: § Making the class implement the javax.jdo.PersistenceCapable interface § Adding implementations of javax.jdo.PersistenceCapable required methods based on the object relationship and underlying database structure § Creating a database. .. persistence of data objects is automatic and that all logic for processing persistent objects is expressed in pure Java language The application programmers do not need to know any database query languages such as SQL The mapping of Java objects and the persisted state of objects stored in the database is achieved behind the scene by the JDO provider implementation and is totally transparent to application... a database It allows an application access to many types of relational databases through a standard API The transaction API ensures concurrency control and therefore allows multiple applications to share persisted data In the previous chapters of this book, you have learned how to use JDBC APIs and have seen what great tools they are The downside is that, as a Java programmer, you must know the database. .. know the database structure and manually map your class attributes to database fields and write all the SQL commands in your Java code In other words, persistence is not transparent In addition, because of the SQL variants among different types of databases (for example, Oracle and Sybase), your code is not 100-percent portable Although Java is a highly object-oriented language, the JDBC uses the relational... CMP beans are used, you enjoy guaranteed portability because all the database- access calls are declared in the deployment descriptor With the so-called "write once, deploy everywhere" approach, you only need to modify the deployment descriptor when the EJBs are deployed to a different database type or to a different database schema The Java code does not need to be modified or recompiled The EJB container... MetaData file for the persistent class Yacht You tell the JDO enhancer that the class java_ database. jdo.Yacht is to be persisted in a data store If you have a complex persistable object model with inheritance and other types... Listing 23-2 You can see from this example that the coding for JDO applications is very simple and straightforward Listing 23-2: A test client for the persistent class Yacht package java_ database. jdo; import java. util.*; import javax.jdo.*; import com.prismt.j2ee.connector.jdbc.ManagedConnectionFactoryImpl; public class TestClient { private final static int SIZE = 4; private PersistenceManagerFactory pmf... model used by relationship databases Typically, object-to-relationship mapping (O/R mapping) must be made, and developers must deal with low-level constructs of the database model, such as rows and columns, and constantly translate them back and forth In the previous chapters of this book, you have learned all the tricks using JDBC APIs to couple your Java objects with underlying database tables It is not... a JDO-aware application, developers do not have to worry about the database type and database schema; but there are some best practices you probably want to follow You should divide the Java classes into two categories: the persistent classes and business classes The persistent classes are those that contain the data managed in the database, and the business classes are those that contain the business... stored in the underlying database, and therefore the objects must be mapped to database entities This mapping is done by the JDO enhancer based on the information provided in the XML MetaData file In many cases, the JDO enhancer also creates a database schema to support the persistence -583 - Please purchase PDF Split-Merge on www.verypdf.com to remove this watermark Chapter 23 :Java Data Objects and . @version: 1.0 */ package java_ database. YachtEBean; import java. rmi.*; import java. util.*; import java. sql.*; import javax.ejb.*; import javax.naming.*; import. Andrew Yang * @version: 1.0 */ package java_ database. YachtEBean; import java. rmi.*; import java. util.*; import javax.ejb.*; public interface YachtHome

Ngày đăng: 24/10/2013, 18:15

TỪ KHÓA LIÊN QUAN