Oracle Containers for J2EE Enterprise JavaBeans開発者ガイド 10g(10.1.3.1.0) B31852-03 |
|
この章では、次のようなEJB 2.1エンティティBeanの実装方法を説明します。
詳細は、次を参照してください。
表13-1に、コンテナ管理の永続性を備えたEJB 2.1エンティティBeanの重要な構成要素をまとめ、次の手順でこれらの構成要素の実装方法を説明します。一般的な実装は、「Javaの使用方法」を参照してください。詳細は、「コンテナ管理の永続性を備えたEJB 2.1エンティティBeanとは」を参照してください。
リモート・ホーム・インタフェースは、クライアントがBeanをインスタンス化するためにリモートで起動できるcreate
およびfinder
メソッドを定義します。ローカル・ホーム・インタフェースは、Beanをインスタンス化するために同一JVM上のBeanがローカルで起動できるcreate
およびfinder
メソッドを定義します。
finderの詳細は、「finderメソッドについて」を参照してください。
javax.ejb.EJBHome
を拡張します(「リモート・ホーム・インタフェースの実装」を参照)。
javax.ejb.EJBLocalHome
を拡張します(「ローカル・ホーム・インタフェースの実装」を参照)。
リモート・コンポーネント・インタフェースは、クライアントがリモートで起動できるビジネス・メソッドを宣言します。ローカル・インタフェースは、同一JVM上のBeanがローカルで起動できるビジネス・メソッドを宣言します。
javax.ejb.EJBObject
を拡張します(「リモート・コンポーネント・インタフェースの実装」を参照)。
javax.ejb.EJBLocalObject
を拡張します(「ローカル・コンポーネント・インタフェースの実装」を参照)。
主キーはシリアライズ可能なクラスで、各エンティティBeanインスタンスを識別します。単純なデータ型クラス(java.lang.String
など)を使用したり、複合クラス(主キーのコンポーネントとして複数のオブジェクトを持つクラスなど)を定義できます。
コンテナ管理の永続性を備えたエンティティBeanの場合、コンテナが実装を行うため、getterおよびsetterメソッドはpublic abstract
です。
RemoteException
をスローしない場合を除き、リモートまたはローカル・インタフェースのシグネチャに一致している必要があります。ローカル・インタフェースおよびリモート・インタフェースはBean実装を使用するため、Bean実装ではRemoteException
をスローできません。エンティティBeanの場合、これらのメソッドはセッションBeanに委任されることがあります(「セッションBeanとは」を参照)。
create
メソッドに対応するejbCreate
メソッドを実装します。クライアントがcreate
メソッドを起動すると、コンテナによって対応するejbCreate
メソッドが起動されます。すべてのebjCreate
メソッドの戻り型は、Beanの主キーの型です。
コンテナ管理の永続性を備えたエンティティBeanの場合は、コンテナがデータベースに維持する値をクライアントが渡せるようにするcreateメソッドを提供します。
javax.ejb.EntityBean
インタフェース・コンテナのコールバック・メソッドの空の実装を提供します。詳細は、「コンテナ管理の永続性を備えたEJB 2.1エンティティBeanのライフ・サイクル・コールバック・メソッドの構成」を参照してください。
EntityContext
のインスタンスを受け取る)setEntityContext
メソッドおよびunsetEntityContext
メソッドを実装します(「setEntityContextおよびunsetEntityContextメソッドの実装」を参照)。
public
abstract
のselectメソッド(「selectメソッドについて」を参照)を定義します。
コンテナ管理の永続性を備えたエンティティBeanの場合は、永続性属性をデータベースに格納する方法を指定するか、表の作成を管理するようにコンテナを構成できます。
詳細は、次を参照してください。
data-sources.xml
ファイルで定義されているデータソースを参照するようにejb-jar.xml
ファイルを構成します(「デプロイXMLの使用方法」を参照)。
例13-1に、コンテナ管理の永続性を備えたEJB 2.1エンティティBeanの一般的な実装を示します。例13-2では対応するリモート・ホーム・インタフェースを示し、例13-3では対応するリモート・コンポーネント・インタフェースを示します。
package cmpapp;
import javax.ejb.*;
import java.rmi.*;
public abstract class EmployeeBean implements EntityBean {
private EntityContext ctx;
// container-managed persistent fields accessors
public abstract Integer getEmpNo();
public abstract void setEmpNo(Integer empNo);
public abstract String getEmpName();
public abstract void setEmpName(String empName);
public abstract Float getSalary();
public abstract void setSalary(Float salary);
public void EmployeeBean() {
// Empty constructor, don't initialize here but in the create().
// passivate() may destroy these attributes in the case of pooling
}
public EmployeePK ejbCreate(Integer empNo, String empName, Float salary)
throws CreateException {
setEmpNo(empNo);
setEmpName(empName);
setSalary(salary);
return new EmployeePK(empNo);
}
public void ejbPostCreate(Integer empNo, String empName, Float salary)
throws CreateException {
// when just after bean created
}
public void ejbStore() {
// when bean persisted
}
public void ejbLoad() {
// when bean loaded
}
public void ejbRemove() {
// when bean removed
}
public void ejbActivate() {
// when bean activated
}
public void ejbPassivate() {
// when bean deactivated
}
public void setEntityContext(EntityContext ctx) {
this.ctx = ctx;
}
public void unsetEntityContext() {
this.ctx = null;
}
}
例13-2 EJB 2.1 CMPリモート・ホーム・インタフェース
package cmpapp;
import java.rmi.*;
import java.util.*;
import javax.ejb.*;
public interface EmployeeHome extends EJBHome {
public Employee create(Integer empNo, String empName, Float salary)
throws CreateException, RemoteException;
public Employee findByPrimaryKey(EmployeePK pk)
throws FinderException, RemoteException;
public Collection findByName(String empName)
throws FinderException, RemoteException;
public Collection findAll()
throws FinderException, RemoteException;
}
例13-3 EJB 2.1 CMPリモート・コンポーネント・インタフェース
package cmpapp;
import javax.ejb.*;
import java.rmi.*;
public interface Employee extends EJBObject {
// container-managed persistent fields accessors
public Integer getEmpNo() throws RemoteException;
public void setEmpNo(Integer empNo) throws RemoteException;
public String getEmpName() throws RemoteException;
public void setEmpName(String empName) throws RemoteException;
public Float getSalary() throws RemoteException;
public void setSalary(Float salary) throws RemoteException;
}
例13-4に、例13-1に示したコンテナ管理の永続性を備えたエンティティBeanに対応するejb-jar.xml
ファイルのentity
要素を示します。
...
<enterprise-beans>
<entity>
<description>no description</description>
<display-name>EmployeeBean</display-name>
<ejb-name>EmployeeBean</ejb-name>
<home>cmpapp.EmployeeHome</home>
<remote>cmpapp.Employee</remote>
<ejb-class>cmpapp.EmployeeBean</ejb-class>
<persistence-type>Container</persistence-type>
<cmp-version>2.x</cmp-version>
<abstract-schema-name>EmployeeBean</abstract-schema-name>
<prim-key-class>cmpapp.EmployeePK</prim-key-class>
<reentrant>False</reentrant>
<cmp-field><field-name>empNo</field-name></cmp-field>
<cmp-field><field-name>empName</field-name></cmp-field>
<cmp-field><field-name>salary</field-name></cmp-field>
<query>
<description></description>
<query-method>
<method-name>findAll</method-name>
<method-params/>
</query-method>
<ejb-ql>Select OBJECT(e) From EmployeeBean e</ejb-ql>
</query>
<query>
<description></description>
<query-method>
<method-name>findByName</method-name>
<method-params>
<method-param>java.lang.String</method-param>
</method-params>
</query-method>
<ejb-ql>Select OBJECT(e) From EmployeeBean e where e.empName = ?1</ejb-ql>
</query>
</entity>
</enterprise-beans>
...
表13-2に、Bean管理の永続性を備えたEJB 2.1エンティティBeanの重要な構成要素をまとめます。次の手順では、これらの構成要素の実装方法を説明します。一般的な実装は、「Javaの使用方法」を参照してください。詳細は、「Bean管理の永続性を備えたEJB 2.1エンティティBeanとは」を参照してください。
リモート・ホーム・インタフェースは、クライアントがBeanをインスタンス化するためにリモートで起動できるcreate
メソッドを定義します。ローカル・ホーム・インタフェースは、Beanをインスタンス化するために同一JVM上のBeanがローカルで起動できるcreate
メソッドを定義します。
javax.ejb.EJBHome
を拡張します(「リモート・ホーム・インタフェースの実装」を参照)。
javax.ejb.EJBLocalHome
を拡張します(「ローカル・ホーム・インタフェースの実装」を参照)。
リモート・コンポーネント・インタフェースは、クライアントがリモートで起動できるビジネス・メソッドを宣言します。ローカル・インタフェースは、同一JVM上のBeanがローカルで起動できるビジネス・メソッドを宣言します。
javax.ejb.EJBObject
を拡張します(「リモート・コンポーネント・インタフェースの実装」を参照)。
javax.ejb.EJBLocalObject
を拡張します(「ローカル・コンポーネント・インタフェースの実装」を参照)。
主キーはシリアライズ可能なクラスで、各エンティティBeanインスタンスを識別します。単純なデータ型クラス(java.lang.String
など)を使用したり、複合クラス(主キーのコンポーネントとして複数のオブジェクトを持つクラスなど)を定義できます。
Bean管理の永続性を備えたエンティティBeanの場合、ユーザーが実装を行うため、getterおよびsetterメソッドはpublicです。
RemoteException
をスローしない場合を除き、リモートまたはローカル・インタフェースのシグネチャに一致している必要があります。ローカル・インタフェースおよびリモート・インタフェースはBean実装を使用するため、Bean実装ではRemoteException
をスローできません。エンティティBeanの場合、これらのメソッドはセッションBeanに委任されることがあります(「セッションBeanとは」を参照)。
create
メソッドに対応するejbCreate
メソッドを実装します。クライアントがcreate
メソッドを起動すると、コンテナによって対応するejbCreate
メソッドが起動されます。すべてのebjCreate
メソッドの戻り型は、Beanの主キーの型です。
Bean管理の永続性を備えたエンティティBeanの場合は、コンテナがデータベースに維持する値をクライアントが渡せるようにするcreateメソッドを提供します。データベースのインスタンスを作成するためにデータベースと(通常は直接JDBCコールを通じて)対話する実装をユーザーが提供します。
詳細は、「Bean管理の永続性を備えたEJB 2.1エンティティBeanのejbCreateメソッドの実装」を参照してください。
javax.ejb.EntityBean
インタフェース・コンテナのコールバック・メソッドの完全な実装を提供します(「Bean管理の永続性を備えたEJB 2.1エンティティBeanのライフ・サイクル・コールバック・メソッドの構成」を参照)。Bean管理の永続性を備えたエンティティBeanの場合は、データベースの永続性を管理するためにデータベースと(通常は直接JDBCコールを通じて)対話するこれらの各メソッドの実装をユーザーが提供します。
EntityContext
のインスタンスを受け取るsetEntityContext
メソッドおよびunsetEntityContext
メソッドを実装します(「setEntityContextおよびunsetEntityContextメソッドの実装」を参照)。
findByPrimaryKey
finderメソッドを実装し、オプションで他のfinderを実装します(「Bean管理の永続性を備えたEJB 2.1エンティティBeanの問合せの構成」を参照)。
Bean管理の永続性を備えたエンティティBeanの場合は、アプリケーションがBean管理の永続性を備えたエンティティBeanのインスタンスの作成を試行する前に、ユーザーが(data-sources.xml
ファイルで定義されている)データベースにこのスキーマを作成します。
data-sources.xml
ファイルで定義されているデータソースを参照するようにejb-jar.xml
ファイルを構成します(「デプロイXMLの使用方法」を参照)。
例13-5に、Bean管理の永続性を備えたEJB 2.1エンティティBeanの一般的な実装を示します。例13-7では対応するホーム・インタフェースを示し、例13-6では対応するリモート・インタフェースを示します。
package bmpapp;
import java.util.*;
import java.rmi.*;
import java.sql.*;
import javax.sql.*;
import javax.naming.*;
import javax.ejb.*;
public class EmployeeBean implements EntityBean {
public Integer empNo;
public EntityContext ctx;
private Connection conn = null;
private PreparedStatement ps = null;
private EmployeePK pk;
private static final String dsName = "jdbc/OracleDS";
private static final String insertStatement =
"INSERT INTO EMP (EMPNO, ENAME, SAL) VALUES (?, ?, ?)";
private static final String updateStatement =
"UPDATE EMP SET ENAME=?, SAL=? WHERE EMPNO=?";
private static final String deleteStatement =
"DELETE FROM EMP WHERE EMPNO=?";
private static final String findAllStatement =
"SELECT EMPNO, ENAME, SAL FROM EMP";
private static final String findByPKStatement =
"SELECT EMPNO, ENAME, SAL FROM EMP WHERE EMPNO = ?";
private static final String findByNameStatement =
"SELECT EMPNO, ENAME, SAL FROM EMP WHERE ENAME = ?";
// or you can define a variable specific to orion to implement finder-method:
// or use <finder-method/> in orion-ejb-jar.xml
public static final String findByNameQuery="full: " +
"SELECT EMPNO, ENAME, SAL FROM EMP WHERE ENAME = $1";
public EmployeeBean() {
// Empty constructor, don't initialize here but in the create().
// passivate() may destroy these attributes in the case of pooling
}
public EmployeePK ejbCreate(Integer empNo, String empName, Float salary)
throws CreateException {
try {
pk = new EmployeePK(empNo, empName, salary);
conn = getConnection(dsName);
ps = conn.prepareStatement(insertStatement);
ps.setInt(1, empNo.intValue());
ps.setString(2, empName);
ps.setFloat(3, salary.floatValue());
ps.executeUpdate();
return pk;
}
catch (SQLException e) {
System.out.println("Caught an exception 1 " + e.getMessage() );
throw new CreateException(e.getMessage());
}
catch (NamingException e) {
System.out.println("Caught an exception 1 " + e.getMessage() );
throw new EJBException(e.getMessage());
}
finally {
try {
ps.close();
conn.close();
} catch (SQLException e) {
throw new EJBException(e.getMessage());
}
}
}
public void ejbPostCreate(Integer empNo, String empName, Float salary)
throws CreateException {
}
public EmployeePK ejbFindByPrimaryKey(EmployeePK pk)
throws FinderException {
if (pk == null || pk.empNo == null) {
throw new FinderException("Primary key cannot be null");
}
try {
conn = getConnection(dsName);
ps = conn.prepareStatement(findByPKStatement);
ps.setInt(1, pk.empNo.intValue());
ps.executeQuery();
ResultSet rs = ps.getResultSet();
if (rs.next()) {
pk.empNo = new Integer(rs.getInt(1));
pk.empName = new String(rs.getString(2));
pk.salary = new Float(rs.getFloat(3));
}
else {
throw new FinderException("Failed to select this PK");
}
}
catch (SQLException e) {
throw new FinderException(e.getMessage());
}
catch (NamingException e) {
System.out.println("Caught an exception 1 " + e.getMessage() );
throw new EJBException(e.getMessage());
}
finally {
try {
ps.close();
conn.close();
}
catch (SQLException e) {
throw new EJBException(e.getMessage());
}
}
return pk;
}
public Collection ejbFindAll() throws FinderException {
//System.out.println("EmployeeBean.ejbFindAll(): begin");
Vector recs = new Vector();
try {
conn = getConnection(dsName);
ps = conn.prepareStatement(findAllStatement);
ps.executeQuery();
ResultSet rs = ps.getResultSet();
int i = 0;
while (rs.next()) {
pk = new EmployeePK();
pk.empNo = new Integer(rs.getInt(1));
pk.empName = new String(rs.getString(2));
pk.salary = new Float(rs.getFloat(3));
recs.add(pk);
}
}
catch (SQLException e) {
throw new FinderException(e.getMessage());
}
catch (NamingException e) {
System.out.println("Caught an exception 1 " + e.getMessage() );
throw new EJBException(e.getMessage());
}
finally {
try {
ps.close();
conn.close();
}
catch (SQLException e) {
throw new EJBException(e.getMessage());
}
}
return recs;
}
public Collection ejbFindByName(String empName)
throws FinderException {
//System.out.println("EmployeeBean.ejbFindByName(): begin");
if (empName == null) {
throw new FinderException("Name cannot be null");
}
Vector recs = new Vector();
try {
conn = getConnection(dsName);
ps = conn.prepareStatement(findByNameStatement);
ps.setString(1, empName);
ps.executeQuery();
ResultSet rs = ps.getResultSet();
int i = 0;
while (rs.next()) {
pk = new EmployeePK();
pk.empNo = new Integer(rs.getInt(1));
pk.empName = new String(rs.getString(2));
pk.salary = new Float(rs.getFloat(3));
recs.add(pk);
}
}
catch (SQLException e) {
throw new FinderException(e.getMessage());
}
catch (NamingException e) {
System.out.println("Caught an exception 1 " + e.getMessage() );
throw new EJBException(e.getMessage());
}
finally {
try {
ps.close();
conn.close();
}
catch (SQLException e) {
throw new EJBException(e.getMessage());
}
}
return recs;
}
public void ejbLoad() throws EJBException {
//Container invokes this method to instruct the instance to
//synchronize its state by loading it from the underlying database
//System.out.println("EmployeeBean.ejbLoad(): begin");
try {
pk = (EmployeePK) ctx.getPrimaryKey();
ejbFindByPrimaryKey(pk);
}
catch (FinderException e) {
throw new EJBException (e.getMessage());
}
}
public void ejbStore() throws EJBException {
//Container invokes this method to instruct the instance to
//synchronize its state by storing it to the underlying database
//System.out.println("EmployeeBean.ejbStore(): begin");
try {
pk = (EmployeePK) ctx.getPrimaryKey();
conn = getConnection(dsName);
ps = conn.prepareStatement(updateStatement);
ps.setString(1, pk.empName);
ps.setFloat(2, pk.salary.floatValue());
ps.setInt(3, pk.empNo.intValue());
if (ps.executeUpdate() != 1) {
throw new EJBException("Failed to update record");
}
}
catch (SQLException e) {
throw new EJBException(e.getMessage());
}
catch (NamingException e) {
System.out.println("Caught an exception 1 " + e.getMessage() );
throw new EJBException(e.getMessage());
}
finally {
try {
ps.close();
conn.close();
}
catch (SQLException e) {
throw new EJBException(e.getMessage());
}
}
}
public void ejbRemove() throws RemoveException {
//Container invokes this method befor it removes the EJB object
//that is currently associated with the instance
//System.out.println("EmployeeBean.ejbRemove(): begin");
try {
pk = (EmployeePK) ctx.getPrimaryKey();
conn = getConnection(dsName);
ps = conn.prepareStatement(deleteStatement);
ps.setInt(1, pk.empNo.intValue());
if (ps.executeUpdate() != 1) {
throw new RemoveException("Failed to delete record");
}
}
catch (SQLException e) {
throw new RemoveException(e.getMessage());
}
catch (NamingException e) {
System.out.println("Caught an exception 1 " + e.getMessage() );
throw new EJBException(e.getMessage());
}
finally {
try {
ps.close();
conn.close();
}
catch (SQLException e) {
throw new EJBException(e.getMessage());
}
}
}
public void ejbActivate() {
// Container invokes this method when the instance is taken out
// of the pool of available instances to become associated with
// a specific EJB object
//System.out.println("EmployeeBean.ejbActivate(): begin");
}
public void ejbPassivate() {
// Container invokes this method on an instance before the instance
// becomes disassociated with a specific EJB object
//System.out.println("EmployeeBean.ejbPassivate(): begin");
}
public void setEntityContext(EntityContext ctx) {
//Set the associated entity context
//System.out.println("EmployeeBean.setEntityContext(): begin");
this.ctx = ctx;
}
public void unsetEntityContext() {
//Unset the associated entity context
//System.out.println("EmployeeBean.unsetEntityContext(): begin");
this.ctx = null;
}
/**
* methods inherited from EJBObject
*/
public Integer getEmpNo() {
pk = (EmployeePK) ctx.getPrimaryKey();
return pk.empNo;
}
public String getEmpName() {
pk = (EmployeePK) ctx.getPrimaryKey();
return pk.empName;
}
public Float getSalary() {
pk = (EmployeePK) ctx.getPrimaryKey();
return pk.salary;
}
public void setEmpNo(Integer empNo) {
pk = (EmployeePK) ctx.getPrimaryKey();
pk.empNo = empNo;
}
public void setEmpName(String empName) {
pk = (EmployeePK) ctx.getPrimaryKey();
pk.empName = empName;
}
public void setSalary(Float salary) {
pk = (EmployeePK) ctx.getPrimaryKey();
pk.salary = salary;
}
public EJBHome getEJBHome() {
return ctx.getEJBHome();
}
public Handle getHandle() throws RemoteException {
return ctx.getEJBObject().getHandle();
}
public Object getPrimaryKey() throws RemoteException {
return ctx.getEJBObject().getPrimaryKey();
}
public boolean isIdentical(EJBObject remote) throws RemoteException {
return ctx.getEJBObject().isIdentical(remote);
}
public void remove() throws RemoveException, RemoteException{
ctx.getEJBObject().remove();
}
/**
* Private methods
*/
private Connection getConnection(String dsName)
throws SQLException, NamingException {
DataSource ds = getDataSource(dsName);
return ds.getConnection();
}
private DataSource getDataSource(String dsName) throws NamingException {
DataSource ds = null;
Context ic = new InitialContext();
ds = (DataSource) ic.lookup(dsName);
return ds;
}
}
例13-6 EJB 2.1 BMPリモート・ホーム・インタフェース
package bmpapp;
import java.rmi.*;
import java.util.*;
import javax.ejb.*;
public interface EmployeeHome extends EJBHome {
public Employee create(Integer empNo, String empName, Float salary)
throws CreateException, RemoteException;
public Employee findByPrimaryKey(EmployeePK pk)
throws FinderException, RemoteException;
public Collection findByName(String empName)
throws FinderException, RemoteException;
public Collection findAll()
throws FinderException, RemoteException;
}
例13-7 EJB 2.1 BMPリモート・コンポーネント・インタフェース
package bmpapp;
import java.rmi.*;
import javax.ejb.*;
public interface Employee extends EJBObject {
// getter remote methods
public Integer getEmpNo() throws RemoteException;
public String getEmpName() throws RemoteException;
public Float getSalary() throws RemoteException;
// setter remote methods
public void setEmpNo(Integer empNo) throws RemoteException;
public void setEmpName(String empName) throws RemoteException;
public void setSalary(Float salary) throws RemoteException;
}
例13-8に、例13-5に示したBean管理の永続性を備えたエンティティBeanに対応するejb-jar.xml
エンティティ要素を示します。
...
<enterprise-beans>
<entity>
<description>no description</description>
<display-name>EmployeeBean</display-name>
<ejb-name>EmployeeBean</ejb-name>
<home>bmpapp.EmployeeHome</home>
<remote>bmpapp.Employee</remote>
<ejb-class>bmpapp.EmployeeBean</ejb-class>
<persistence-type>Bean</persistence-type>
<prim-key-class>bmpapp.EmployeePK</prim-key-class>
<reentrant>False</reentrant>
<resource-ref>
<res-ref-name>jdbc/OracleDS</res-ref-name>
<res-type>javax.sql.DataSource</res-type>
<res-auth>Application</res-auth>
</resource-ref>
</entity>
</enterprise-beans>
...
例13-9に、例13-8で示したejb-jar.xml
ファイルで使用したres-ref-name
(jdbc/OracleDS
)を指定するdata-sources.xml
ファイルのdata-source
要素のejb-location
属性を示します。
<connection-pool name="Example Connection Pool">
<!-- This is an example of a connection factory that emulates XA behavior. -->
<connection-factory factory-class="oracle.jdbc.pool.OracleDataSource"
user="scott"
password="tiger"
url="jdbc:oracle:thin:@//localhost:1521/oracle.regress.rdbms.dev.us.oracle.com">
</connection-factory>
</connection-pool>
<managed-data-source name="OracleDS"
connection-pool-name="Example Connection Pool"
jndi-name="jdbc/OracleDS"/>
ejbCreate
メソッドは、主に主キーの作成を実行します。次のものが含まれます。
コンテナにより、キーがエンティティBeanの参照にマッピングされます。
次の例では、employeeの例のejbCreate
メソッドを示します。このメソッドは、主キーであるempNo
を初期化します。これは、本来なら、自動的に、次に使用可能な従業員番号である主キーを生成します。ただし、ここでは例を簡単にするために、このejbCreate
メソッドはユーザーに一意の従業員番号を入力するよう求めます。
さらに、従業員の全データがこのメソッドで提供されるため、データはこのインスタンスのコンテキスト変数内に格納されます。初期化後、このキーがコンテナに返されます。
// The create methods takes care of generating a new empNo and returns // its primary key to the container public Integer ejbCreate (Integer empNo, String empName, Float salary) throws CreateException { // in this implementation, the client gives the employee number, // so only need to assign it, not create it this.empNo = empNo; this.empName = empName; this.salary = salary; // insert employee into database conn = getConnection(dsName); ps = conn.prepareStatement("INSERT INTO EMPLOYEEBEAN (EmpNo, EmpName, SAL) VALUES ( "+this.empNo.intValue()+", "+this.empName+"," + this.salary.floatValue()+")"); ps.executeUpdate(); ps.close(); // return the new primary key return (empNo); }
このデプロイメント・ディスクリプタでは、<prim-key-class>
要素内で、主キー・クラスのみ定義します。Beanがデータを保存するため、デプロイメント・ディスクリプタには、永続データの定義は存在しません。ただし、デプロイメント・ディスクリプタの<resource-ref>
要素で、Beanが使用するデータベースを定義します。データベース構成の詳細は、「デプロイXMLの使用方法」を参照してください。
<enterprise-beans> <entity> <display-name>EmployeeBean</display-name> <ejb-name>EmployeeBean</ejb-name> <local-home>employee.EmployeeLocalHome</local-home> <local>employee.EmployeeLocal</local> <ejb-class>employee.EmployeeBean</ejb-class> <persistence-type>Bean</persistence-type> <prim-key-class>java.lang.Integer</prim-key-class> <reentrant>False</reentrant> <resource-ref> <res-ref-name>jdbc/OracleDS</res-ref-name> <res-type>javax.sql.DataSource</res-type> <res-auth>Application</res-auth> </resource-ref> </entity> </enterprise-beans>
または、複数のデータ型に基づいた複合主キーを作成可能です。複合主キーは、次のように、そのクラス内で定義します。
package employee; import java.io.*; java.io.Serializable; ... public class EmployeePK implements java.io.Serializable { public Integer empNo; public String empName; public Float salary; public EmployeePK(Integer empNo) { this.empNo = empNo; this.empName = null; this.salary = null; } public EmployeePK(Integer empNo, String empName, Float salary) { this.empNo = empNo; this.empName = empName; this.salary = salary; } }
主キー・クラスの場合、クラスを<prim-key-class>
要素で定義します。これは、単純な主キー定義と同じです。
<enterprise-beans> <entity> <display-name>EmployeeBean</display-name> <ejb-name>EmployeeBean</ejb-name> <local-home>employee.EmployeeLocalHome</local-home> <local>employee.EmployeeLocal</local> <ejb-class>employee.EmployeeBean</ejb-class> <persistence-type>Bean</persistence-type> <prim-key-class>employee.EmployeePK</prim-key-class> <reentrant>False</reentrant> <resource-ref> <res-ref-name>jdbc/OracleDS</res-ref-name> <res-type>javax.sql.DataSource</res-type> <res-auth>Application</res-auth> </resource-ref> </entity> </enterprise-beans>
employeeの例では、ユーザーが従業員番号をBeanに対して指定する必要があります。別の手段としては、次に使用可能な従業員番号を計算し、この番号を従業員の名前および勤務地と組み合せて従業員番号を生成する方法があります。
複合主キー・クラスの定義後、次のように、ejbCreate
メソッド内で主キーを作成します。
public EmployeePK ejbCreate(Integer empNo, String empName, Float salary) throws CreateException { pk = new EmployeePK(empNo, empName, salary); ... }
ejbCreate
(またはejbPostCreate
)が処理する作業には、他に、Beanの存続期間中に必要なリソースの割当てがあります。この例では、すでに従業員情報が存在するため、ejbCreate
は次の処理を実行します。
ejbPassivate
およびejbRemove
で解放し、ejbActivate
で再割当てを行います。
これは、次のように実行されます。
public EmployeePK ejbCreate(Integer empNo, String empName, Float salary) throws CreateException { pk = new EmployeePK(empNo, empName, salary); conn = getConnection(dsName); ps = conn.prepareStatement("INSERT INTO EMPLOYEEBEAN (EmpNo, EmpName, SAL) VALUES ( "+this.empNo.intValue()+", "+this.empName+"," + this.salary.floatValue()+")"); ps.executeUpdate(); ps.close(); return pk; }
ホーム・インタフェースは、クライアントがエンティティBeanインスタンスの作成または取得に使用するメソッドを指定するために使用します。
ホーム・インタフェースには、クライアントがBeanのインスタンスを作成するために起動するcreate
メソッドが含まれている必要があります。エンティティBeanには、それぞれ定義されたパラメータを持つ0(ゼロ)以上のcreate
メソッドを使用できます。各create
メソッドにつき、対応するejbCreate
メソッドをBean実装で定義します。
すべてのエンティティBeanで、1つ以上のfinderメソッドをホーム・インタフェースに定義する必要があります。そのうちの1つ以上はfindByPrimaryKey
メソッドである必要があります。オプションで、事前定義およびデフォルトのfinderを含む他のfinderメソッドを定義できます。これらには、find<
name
>
のように名前を付けます。詳細は、「finderメソッドについて」を参照してください。
メソッドの作成および取得に加えて、ホーム・インタフェース内でホーム・インタフェースのビジネス・メソッドを提供できます。このメソッドの機能では、特定のエンティティ・オブジェクトのデータにアクセスできません。このメソッドは、単一のエンティティBeanインスタンスに関連がない情報を取得するために使用します。クライアントがホーム・インタフェースの任意のビジネス・メソッドを起動すると、エンティティBeanはプールから移動され、リクエストを処理します。したがって、このメソッドを使用すると、Beanに関連する一般的な情報に関する操作を実行できます。
たとえば、employeeアプリケーションでは、ローカル・ホーム・インタフェースにcreate
、findByPrimaryKey
、findAll
およびcalcSalary
メソッドを提供できます。calcSalary
メソッドは、全従業員の給与合計を計算する、ホーム・インタフェースのビジネス・メソッドです。このメソッドは特定の従業員の情報にはアクセスしませんが、全従業員のデータベースに対してSQL問合せを実行します。
ホーム・インタフェースには次の2種類があります。
javax.ejb.EJBHome
を拡張します(「リモート・ホーム・インタフェースの実装」を参照)。
javax.ejb.EJBLocalHome
を拡張します
リモート・クライアントは、リモート・インタフェースを介してEJBを起動します。クライアントは、リモート・ホーム・インタフェースで宣言されたcreate
メソッドを起動します。コンテナは、Bean実装内の、適切なパラメータ・シグネチャを持つejbCreate
メソッドにクライアント・コールを渡します。リモート・ホーム・インタフェースを開発するための要件は次のとおりです。
例13-2に、例13-1のコンテナ管理の永続性を備えたEJB 2.1エンティティBeanに対応するリモート・ホーム・インタフェースを示します。例13-6に、例13-5のBean管理の永続性を備えたEJB 2.1エンティティBeanに対応するリモート・ホーム・インタフェースを示します。
EJBは、同じコンテナに存在するクライアントからローカルでコールできます。したがって、同一JVM上のBean、JSPまたはサーブレットは、ローカル・ホーム・インタフェースで宣言されたcreate
メソッドを起動します。コンテナは、Bean実装内の、適切なパラメータ・シグネチャを持つejbCreate
メソッドにクライアント・コールを渡します。ローカル・ホーム・インタフェースを開発するための要件は、次のとおりです。
コンポーネント・インタフェースでは、クライアントから起動可能なBeanのビジネス・メソッドを定義します。
エンティティBeanコンポーネント・インタフェースは、クライアントがそのメソッドを起動できるインタフェースです。コンポーネント・インタフェースは、エンティティBeanインスタンスのビジネス・ロジック・メソッドを定義します。
コンポーネント・インタフェースには次の2種類があります。
javax.ejb.EJBObject
を拡張します(「リモート・コンポーネント・インタフェースの実装」を参照)。
javax.ejb.EJBLocalObject
を拡張します(「ローカル・コンポーネント・インタフェースの実装」を参照)。
リモート・インタフェースでは、リモート・クライアントによって起動可能なビジネス・メソッドを定義します。リモート・コンポーネント・インタフェースを開発するための要件は、次のとおりです。
javax.ejb.EJBObject
インタフェースを拡張する必要があり、そのメソッドはjava.rmi.RemoteException
例外をスローする必要があります。
public
として宣言する必要があります。
EJBException
およびRemoteException
を含めた実行時例外は、リモート実行時例外としてクライアントに転送されます。
例13-3に、例13-1のコンテナ管理の永続性を備えたEJB 2.1エンティティBeanに対応するリモート・コンポーネント・インタフェースを示します。例13-7に、例13-5のBean管理の永続性を備えたEJB 2.1エンティティBeanに対応するリモート・コンポーネント・インタフェースを示します。
ローカル・コンポーネント・インタフェースでは、ローカル(同一JVM上の)クライアントから起動可能なBeanのビジネス・メソッドを定義します。ローカル・コンポーネント・インタフェースを開発するための要件は、次のとおりです。
javax.ejb.EJBLocalObject
インタフェースを拡張する必要があります。
public
として宣言します。
エンティティBeanのインスタンスは、このメソッドを使用して、コンテキストへの参照を維持します。エンティティBeanには、コンテナによって維持され、Beanから使用可能なコンテキストが存在します。エンティティ・コンテキスト内のメソッドを使用して、セキュリティおよびトランザクションのロールなどのBeanに関する情報の取得が、Beanによって行われる場合があります。Beanに関してコンテキストから取得可能なすべての情報は、Sun社のEJB仕様を参照してください。
コンテナは、Beanをインスタンス化すると、setEntityContext
メソッドを起動して、Beanからコンテキストを取得できるようにします。コンテナは、トランザクション・コンテキストからはこのメソッドをコールしません。この時点でBeanがコンテキストを保存しなかった場合、Beanは二度とコンテキストにアクセスできなくなります。
コンテナはこのメソッドをコールする際、EntityContext
オブジェクトの参照をBeanに渡します。Beanは、この参照を後の使用のために格納できます。次の例では、Beanがコンテキストをthis.ctx
変数に格納するところを示します。
このメソッドを使用して、Beanのコンテキストの参照を取得します。エンティティBeanには、コンテナによって維持され、Beanから使用可能なエンティティ・コンテキストが存在します。Beanは、エンティティ・コンテキスト内のメソッドを使用して、コンテナへのコールバック・リクエストを送信できます。
例13-10に、セッション・コンテキストをentityctx
変数に格納するエンティティBeanを示します。
import javax.ejb.*; public class MyBean implements EnityBean { EntityContext entityctx; public void setEntityContext(EntityContext ctx) { entityctx = ctx; // entity context is stored in instance variable } public void unsetEntityContext() { entityctx = null; } // other methods in the bean }
|
Copyright © 2002, 2008 Oracle Corporation. All Rights Reserved. |
|