EJB 3.0 Database Persistence with Oracle Fusion Middleware 11g
上QQ阅读APP看书,第一时间看更新

Converting the entity class

The EJB 3.0 entity class is a non-abstract POJO class with implementations for the getter/setter methods, in comparison to the EJB 2.0 entity bean class, which is abstract with abstract getter/setter methods. EJB 3.0 does not require component and home interfaces. The entity bean class may implement a business interface, though is not required to.

In the EJB 3.0 specification, the EntityManager class is used to create, find, and update an entity bean instance. In EJB 3.0, deployment descriptors are not required and are replaced with metadata annotations. When deployment descriptors are supplied, their values override annotations. An entity bean is specified with the @Entity annotation. The table name, column name, and primary key column properties are specified with the metadata annotations listed in the following table:

Annotatio           Descriptio           Annotation Elements

@Table           Specifies the table used for entity bean persistence.           Name (if the name element is not specified, the EJB class name is used as the table name).

@Column           Specifies a column corresponding to an entity bean property.           Name, nullable, length, updatable, and unique.

@Id           Specifies a primary key column property.

@Transient           Specifies a property that is not persistent.

EJB Query Language (QL) queries in the EJB 2.0 specification are specified with the <query/> element in the ejb-jar.xml deployment descriptor. EJB QL queries in EJB 3.0 are specified with the metadata annotations @NamedQuery and @NamedQueries, which are listed in the following table:

Annotatio           Descriptio           Annotation Elements

@NamedQueries           Specifies a group of EJB QL queries

@NamedQuery           Specifies an EJB QL query           name="query name" query="SQL query"

The entity bean container-managed relationship (CMR) relationships in EJB 2.0 are specified with the <ejb-relation/> elements in the ejb-jar.xml deployment descriptor, and the entity bean CMR relationships in EJB 3.0 are specified in the bean class. The metadata annotations used to specify the entity bean CMR relationships are listed in the following table:

Annotatio           Description

@OneToMany           One-to-many entity bean CMR relationship.

@OneToOne           One-to-one entity bean CMR relationship.

@ManyToOne           Many-to-one entity bean CMR relationship.

@ManyToMany           Many-to-many entity bean CMR relationship.

The EJB 2.0 entity

The EJB 2.0 entity class being migrated to EJB 3.0 in this chapter is as shown next:

import javax.ejb.*;
abstract public class CatalogBean implements EntityBean {
private EntityContext ctx;
public CatalogBean() {
};
public void setEntityContext(EntityContext ctx) {
this.ctx = ctx;
}
public void unsetEntityContext() {
this.ctx = null;
}
abstract public String getCatalogId();
abstract public void setCatalogId(String catalogId);
abstract public String getJournal();
abstract public void setJournal(java.lang.String journal);
abstract public String getPublisher();
abstract public void setPublisher(String publisher);
public void ejbActivate() {
}
public void ejbPassivate() {
}
public void ejbLoad() {
}
public void ejbStore() {
}
public void ejbRemove() throws RemoveException {
}
public String ejbCreate(String catalogId, String journal,
String publisher)
throws CreateException {
setCatalogId(catalogId);
setJournal(journal);
setPublisher(publisher);
return null;
}
public void ejbPostCreate(String catalogId, String journal,
String publisher) {
}
}

The chapter is about converting an EJB 2 entity to EJB 3.0. We are not migrating, which would have involved taking sections of the EJB 2 entity and creating the corresponding EJB 3 entity. We are converting using an XSLT transformation and we need to modify slightly the starting deployment descriptor ejb-jar.xml. The EJB 2.0 entity ejb-jar.xml deployment descriptor does not include enough information to generate an EJB 3.0 entity from. Modify the ejb-jar.xml deployment descriptor for the example entity to include elements for the table name, field type, and EJB QL query collection type for multi-entity return values. Add the <table-name/>, <field-type/>, and <collection-type/> elements to ejb-jar.xml. The modified ejb-jar.xml deployment descriptor for the example entity bean is as follows:

<?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>
<table-name>Catalog</table-name>
<ejb-name>Catalog</ejb-name>
<local-home>CatalogHome</local-home>
<local>Catalog</local>
<ejb-class>CatalogBean</ejb-class>
<persistence-type>Container</persistence-type>
<prim-key-class>CatalogPK</prim-key-class>
<reentrant>False</reentrant>
<cmp-version>2.x</cmp-version>
<abstract-schema-name>CatalogBean</abstract-schema-name>
<cmp-field>
<field-name>catalogId</field-name>
<field-type>String</field-type>
</cmp-field>
<cmp-field>
<field-name>journal</field-name>
<field-type>String</field-type>
</cmp-field>
<cmp-field>
<field-name>publisher</field-name>
<field-type>String</field-type>
</cmp-field>
<primkey-field>catalogId</primkey-field>
<query>
<query-method>
<method-name>findByCatalogId</method-name>
<method-params>
<method-param>java.lang.String</method-param>
</method-params>
</query-method>
<ejb-ql>
<![CDATA[SELECT OBJECT(a) FROM CatalogBean AS a WHERE a.catalogId = ?1
</ejb-ql>
</query>
<query>
<query-method>
<method-name>findByJournal</method-name>
<method-params>
<method-param>java.lang.String</method-param>
</method-params>
</query-method>
<ejb-ql>
<![CDATA[SELECT OBJECT(a) FROM CatalogBean AS a WHERE a.journal= ?1
</ejb-ql>
<collection-type>java.util.Collection</collection-type>
</query>
</entity>
</enterprise-beans>
</ejb-jar>

Copy the modified deployment descriptor to the ejb-jar-modified.xml file in JDeveloper.

The XSLT stylesheet

Next, convert the modified ejb-jar.xml to an EJB 3.0 entity bean with an XSLT stylesheet. The EJB 3.0 entity bean class is generated using the built-in XSLT transformation tool in JDeveloper. The XSLT stylesheet entity-bean.xsl used to generate the EJB 3.0 entity is listed next:

<?xml version="1.0" encoding="UTF-8"?>
<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:output encoding="ISO-8859-1" omit-xml-declaration="yes"
method="text" />
<xsl:template match="/">
<xsl:apply-templates select="ejb-jar/enterprise-beans/entity" />
<xsl:apply-templates select="ejb-jar/relationships/ejb-relation" />
}
</xsl:template>
<xsl:variable name="lcletters">
abcdefghijklmnopqrstuvwxyz
</xsl:variable>
<xsl:variable name="ucletters">
ABCDEFGHIJKLMNOPQRSTUVWXYZ
</xsl:variable>
<xsl:template match="cmp-field">
<xsl:param name="varDecl" />
<xsl:param name="beanMethods" />
<xsl:param name="pkFields" />
<xsl:param name="constructorFields" />
<xsl:param name="constructor" />
<xsl:param name="constructorPK" />
<xsl:param name="primKeyField" />
<xsl:param name="fieldName" select="field-name" />

Create a constructor with primary key field as parameter:

<xsl:if test="$constructor='constructor'">
<xsl:if test="$primKeyField=$fieldName">
this.
<xsl:value-of
select="translate((substring(field-name,
1,1)),$ucletters,$lcletters)" />
<xsl:value-of select="substring(field-name,2)" />
=
<xsl:value-of
select="translate((substring(field-name, 1,1)),
$ucletters,$lcletters)" />
<xsl:value-of select="substring(field-name,2)" />
;
</xsl:if>
</xsl:if>
<xsl:if test="$varDecl='varDecl'">
private
<xsl:value-of select="field-type" />
<xsl:text> </xsl:text>
<xsl:value-of select="field-name" />
;
<xsl:text disable-output-escaping="yes">
</xsl:text>
</xsl:if>
<xsl:if test="$constructorFields='constructorFields'">
<xsl:if test="$primKeyField=$fieldName">
<xsl:value-of select="field-type" />
<xsl:text> </xsl:text>
<xsl:value-of
select="translate((substring(field-name, 1,1)),
$ucletters,$lcletters)" />
<xsl:value-of select="substring(field-name,2)" />
</xsl:if>
</xsl:if>

Create getter and setter methods for the primary key field:

<xsl:if test="$beanMethods='beanMethods'">
<xsl:if test="$primKeyField=$fieldName">
<xsl:text disable-output-escaping="yes">@Id</xsl:text>
<xsl:text disable-output-escaping="yes">
</xsl:text>
<xsl:text disable-output-escaping="yes">@Column(name="</xsl:text>
<xsl:value-of
select="translate((substring(field-name, 1)),
$lcletters,$ucletters)" />
<xsl:text disable-output-escaping="yes">", unique=true)</xsl:text>
</xsl:if>
public
<xsl:value-of select="field-type" />
get
<xsl:value-of
select="translate((substring(field-name, 1,1)),
$lcletters,$ucletters)" />
<xsl:value-of select="substring(field-name,2)" />
() {return
<xsl:value-of
select="translate((substring(field-name, 1,1)),
$ucletters,$lcletters)" />
<xsl:value-of select="substring(field-name,2)" />
;}
<xsl:text> </xsl:text>
public void set
<xsl:value-of
select="translate((substring(field-name, 1,1)),
$lcletters,$ucletters)" />
<xsl:value-of select="substring(field-name,2)" />
(
<xsl:value-of select="field-type" />
<xsl:text> </xsl:text>
<xsl:value-of
select="translate((substring(field-name, 1,1)),
$ucletters,$lcletters)" />
<xsl:value-of select="substring(field-name,2)" />
){this.
<xsl:value-of
select="translate((substring(field-name, 1,1)),
$ucletters,$lcletters)" />
<xsl:value-of select="substring(field-name,2)" />
=
<xsl:value-of
select="translate((substring(field-name, 1,1)),
$ucletters,$lcletters)" />
<xsl:value-of select="substring(field-name,2)" />
;}
</xsl:if>
</xsl:template>

Create getter and setter methods for entity relationships:

<xsl:template match="ejb-relation">
<xsl:variable name="src1"
select="ejb-relationship-role[position()=1]/
relationship-role-source/ejb-name" />
<xsl:variable name="src2"
select="ejb-relationship-role[position()=2]/
relationship-role-source/ejb-name" />
<xsl:variable name="multiplicity1"
select="ejb-relationship-role[position()=1]/multiplicity" />
<xsl:variable name="multiplicity2"
select="ejb-relationship-role[position()=2]/multiplicity" />
<xsl:variable name="cmr1"
select="ejb-relationship-role[position()=1]/cmr-field/cmr-field-name" />
<xsl:variable name="cmrType1"
select="ejb-relationship-role[position()=1]/cmr-field/cmr-field-type" />
<xsl:variable name="cmr2"
select="ejb-relationship-role[position()=2]/cmr-field/cmr-field-name" />
<xsl:if test="$multiplicity2='Many'">
private
<xsl:value-of select="$cmrType1" />
<xsl:text disable-output-escaping="yes">&lt;</xsl:text>
<xsl:value-of select="$src2" />
<xsl:text disable-output-escaping="yes">&gt; </xsl:text>
<xsl:value-of select="$cmr1"/>
;
</xsl:if>
<xsl:if test="$multiplicity2='One'">
private
<xsl:value-of select="$src2"/>
<xsl:text> </xsl:text>
<xsl:value-of select="$cmr1"/>
;
</xsl:if>
<xsl:if test="$multiplicity1='One' and $multiplicity2='Many'">
<xsl:text disable-output-escaping="yes">@OneToMany</xsl:text>
<xsl:text> </xsl:text>
public
<xsl:value-of select="$cmrType1"/>
<xsl:text disable-output-escaping="yes">&lt;</xsl:text>
<xsl:value-of select="$src2"/>
<xsl:text disable-output-escaping="yes">&gt; </xsl:text>
get
<xsl:value-of select="translate((substring($cmr1, 1, 1)),
$lcletters,$ucletters)"/>
<xsl:value-of select="substring($cmr1,2)"/>
(){return
<xsl:value-of select="$cmr1"/>
;} public void set
<xsl:value-of select="translate((substring($cmr1, 1, 1)),
$lcletters,$ucletters)"/>
<xsl:value-of select="substring($cmr1,2)"/>
(
<xsl:value-of select="$cmrType1"/>
<xsl:text disable-output-escaping="yes">&lt;</xsl:text>
<xsl:value-of select="$src2"/>
<xsl:text disable-output-escaping="yes">&gt; </xsl:text>
<xsl:text> </xsl:text>
<xsl:value-of select="$cmr1"/>
){ this.
<xsl:value-of select="$cmr1"/>
=
<xsl:value-of select="$cmr1"/>
; }
</xsl:if>
<xsl:if test="$multiplicity1='One' and $multiplicity2='One'">
<xsl:text disable-output-escaping="yes">@OneToOne</xsl:text>
<xsl:text> </xsl:text>
public
<xsl:text disable-output-escaping="yes">&lt;</xsl:text>
<xsl:value-of select="$src2"/>
<xsl:text disable-output-escaping="yes">&gt; </xsl:text>
get
<xsl:value-of select="translate((substring($cmr1, 1, 1)),
$lcletters,$ucletters)"/>
<xsl:value-of select="substring($cmr1,2)"/>
(){return
<xsl:value-of select="$cmr1"/>
;} public void set
<xsl:value-of select="translate((substring($cmr1, 1, 1)),
$lcletters,$ucletters)"/>
<xsl:value-of select="substring($cmr1,2)"/>
(
<xsl:value-of select="$src2"/>
<xsl:text> </xsl:text>
<xsl:value-of select="$cmr1"/>
){ this.
<xsl:value-of select="$cmr1"/>
=
<xsl:value-of select="$cmr1"/>
EJB 2.0 entity to EJB 3.0 entity, conversionEJB 2.0 entity to EJB 3.0 entity, conversionXSLT stylesheet; }
</xsl:if>
<xsl:if test="$multiplicity1='Many' and $multiplicity2='One'">
<xsl:text disable-output-escaping="yes">@ManyToOne</xsl:text>
<xsl:text> </xsl:text>
public
<xsl:value-of select="$src2"/>
get
<xsl:value-of select="translate((substring($cmr1, 1, 1)),
$lcletters,$ucletters)"/>
<xsl:value-of select="substring($cmr1,2)"/>
(){return
<xsl:value-of select="$cmr1"/>
;} public void set
<xsl:value-of select="translate((substring($cmr1, 1, 1)),
$lcletters,$ucletters)"/>
<xsl:value-of select="substring($cmr1,2)"/>
(
<xsl:value-of select="$src2"/>
<xsl:text> </xsl:text>
<xsl:value-of select="$cmr1"/>
){ this.
<xsl:value-of select="$cmr1"/>
=
<xsl:value-of select="$cmr1"/>
; }
</xsl:if>
<xsl:if test="$multiplicity1='Many' and $multiplicity2='Many'">
<xsl:text disable-output-escaping="yes">@ManyToMany</xsl:text>
<xsl:text> </xsl:text>
public
<xsl:value-of select="$cmrType1"/>
<xsl:text disable-output-escaping="yes">&lt;</xsl:text>
<xsl:value-of select="$src2"/>
<xsl:text disable-output-escaping="yes">&gt; </xsl:text>
get
<xsl:value-of select="translate((substring($cmr1, 1, 1)),
$lcletters,$ucletters)"/>
<xsl:value-of select="substring($cmr1,2)"/>
(){return
<xsl:value-of select="$cmr1"/>
;} public void set
<xsl:value-of select="translate((substring($cmr1, 1, 1)),
$lcletters,$ucletters)"/>
<xsl:value-of select="substring($cmr1,2)"/>
(
<xsl:value-of select="$cmrType1"/>
<xsl:text disable-output-escaping="yes">&lt;</xsl:text>
<xsl:value-of select="$src2"/>
<xsl:text disable-output-escaping="yes">&gt; </xsl:text>
<xsl:text> </xsl:text>
<xsl:value-of select="$cmr1"/>
){ this.
<xsl:value-of select="$cmr1"/>
=
<xsl:value-of select="$cmr1"/>
; }
</xsl:if>
</xsl:template>

Add import statements:

<xsl:template match="entity">
import javax.persistence.Entity; import javax.persistence.Id; import
javax.persistence.Column; import javax.persistence.NamedQueries; import
javax.persistence.NamedQuery;
import javax.persistence.OneToMany; import javax.persistence.OneToOne; import
javax.persistence.ManyToOne; import javax.persistence.ManyToMany; import
javax.persistence.Table;

Add annotations for the entity and entity table:

<xsl:text disable-output-escaping="yes">@Entity</xsl:text>
<xsl:text disable-output-escaping="yes">
</xsl:text>
<xsl:text disable-output-escaping="yes">@Table(name="</xsl:text>
<xsl:value-of select="table-name"/>
<xsl:text disable-output-escaping="yes">")</xsl:text>
<xsl:text disable-output-escaping="yes">
</xsl:text>

Add annotation for named queries:

<xsl:if test="query">
<xsl:text disable-output-escaping="yes">@NamedQueries({</xsl:text>
<xsl:apply-templates select="query"/>
<xsl:text disable-output-escaping="yes">})</xsl:text>
</xsl:if>

Add a class declaration and class constructor:

public class
<xsl:value-of select="ejb-class"/>
implements java.io.Serializable { public
<xsl:value-of select="ejb-class"/>
(){} public
<xsl:value-of select="ejb-class"/>
(
<xsl:apply-templates select="cmp-field">
<xsl:with-param name="constructorFields" select="'constructorFields'"/>
<xsl:with-param name="primKeyField" select="primkey-field"/>
</xsl:apply-templates>
){
<xsl:apply-templates select="cmp-field">
<xsl:with-param name="constructor" select="'constructor'"/>
<xsl:with-param name="primKeyField" select="primkey-field"/>
</xsl:apply-templates>
}
<xsl:apply-templates select="cmp-field">
<xsl:with-param name="varDecl" select="'varDecl'"/>
</xsl:apply-templates>
<xsl:text disable-output-escaping="yes">
</xsl:text>
<xsl:apply-templates select="cmp-field">
<xsl:with-param name="beanMethods" select="'beanMethods'"/>
<xsl:with-param name="primKeyField" select="primkey-field"/>
</xsl:apply-templates>
</xsl:template>

Add named queries:

<xsl:template match="query">
<xsl:text disable-output-escaping="yes">@NamedQuery(name="</xsl:text>
<xsl:value-of select="translate((substring(query-method/method-name,
1,1)),$lcletters,$ucletters)"/>
<xsl:value-of select="substring(query-method/method-name,2)"/>
<xsl:text disable-output-escaping="yes">",query="</xsl:text>
<xsl:value-of select="ejb-ql"/>
<xsl:text disable-output-escaping="yes">")</xsl:text>
<xsl:if test="position() != last()">,</xsl:if>
<xsl:text disable-output-escaping="yes">
</xsl:text>
</xsl:template>
</xsl:stylesheet>

Copy the stylesheet to the entity-bean.xsl file in JDeveloper.

Generating the EJB 3.0 entity

To transform the modified deployment descriptor (ejb-jar-modified.xml) to an EJB 3.0 entity bean class, right-click on entity-bean.xsl and select Run.

Generating the EJB 3.0 entity

In the XSLT Settings window select Input XML File as ejb-jar-modified.xml and specify Output File as CatalogBean.java. Click on OK.

Generating the EJB 3.0 entity

The XSLT Settings wizard is displayed only the first time an XSLT stylesheet is run. For subsequent runs of the stylesheet or running other stylesheets, the input XML document and the output file are required to be configured in the Project Properties window. Select Run/Debug/Profile in Project Properties, select the Run Configuration | Default, and click on Edit.

Generating the EJB 3.0 entity

In the Edit Run Configuration window, select Launch Settings | XSLT. Specify the Input XML File and the Output File and click on OK.

Generating the EJB 3.0 entity

Using either method to set the input XML file and the output file, generate the output file CatalogBean.java. Add the output file to the project with View | Refresh. Alternatively, import the generated file with File | Import. In the Import window, select Java Source and click on OK.

Generating the EJB 3.0 entity

In Choose Directory, select the public_html directory. In the Java Source window, the Java source file and the to directory gets specified. Click on OK.

Generating the EJB 3.0 entity

The CatalogBean.java gets added to the project:

Generating the EJB 3.0 entity

The EJB 3.0 entity bean generated from the EJB 2.0 entity bean is listed below. First, the import statements are specified.

import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Column;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.OneToMany;
import javax.persistence.OneToOne;
import javax.persistence.ManyToOne;
import javax.persistence.ManyToMany;
import javax.persistence.Table;

The @Entity annotation specifies the class to be an entity class. And, the @Table annotation specifies the table name.

@Entity
@Table(name="Catalog")

The named queries are grouped with the @NamedQueries annotation and each named query is specified with the @NamedQuery annotation. The name attribute specifies the named query name that may be used with EntityManager when creating query objects. The query attribute specifies the query string in the Java Persistence query language.

@NamedQueries({@NamedQuery(name="FindByCatalogId", query="SELECT OBJECT(a) FROM CatalogBean AS a WHERE a.catalogId = ?1"),
@NamedQuery(name="FindByJournal", query= "SELECT OBJECT(a) FROM CatalogBean AS a WHERE a.journal= ?1 ")
})

The entity class declaration and the properties declarations are specified next.

public class
CatalogBean implements java.io.Serializable {
public CatalogBean(){} public CatalogBean
(
String catalogId
){
this.catalogId=catalogId;
}
private String catalogId;
private String journal;
private String publisher;

The id property is specified with the @Id annotation and the column is specified with the @Column annotation. The getter/setter methods for the id property are also specified.

@Id
@Column(name="CATALOGID", unique=true)
public String getCatalogId() {return catalogId;}
public void setCatalogId(String catalogId){this.catalogId=catalogId;}

The getter/setter methods for the entity properties are specified next.

public String getJournal() {return journal;}
public void setJournal
(
String journal
){this.journal=journal;}
public String getPublisher() {return publisher;}
public void setPublisher(String publisher){
this.publisher=publisher;}
}

The XSL transformation generated entity class may require some reformatting or/and debugging depending on the complexity of the initial EJB 2.0 entity. The EJB 3.0 entity generated in this chapter requires only slight reformatting. The EJB 3.0 entity class has the import statements for the javax.persistence package classes. The @Entity annotation specifies the class as an entity EJB class. The @Table annotation specifies the database table name for the entity EJB, the @NamedQueries annotation specifies the named queries, the @Id annotation specifies the identifier property/primary key field, and the @Column annotation specifies the database column corresponding to the identifier property. The EJB 2.0-to-EJB 3.0 conversion XSLT also includes the conversion of entity bean CMR relationships.