JSP, EJB und Oracle?

Hallo!

In einem kleinen Projekt an der FH arbeiten wir mit JSP, EJB (Sun J2EE Reference Implementation als Application Server) und Oracle 8i als Datenbank. Wir sind dabei auf die folgenden zwei Probleme gestossen, fuer die wir bis jetzt in der Doku und im Web keine Loesung gefunden haben.

  1. Mit JSP EJB-ResultSet selektieren

Wir nutzen für die EJB container-managed persistence. Wie kann ich jetzt mittels JSP ein ResultSet von Objekten mit bestimmten Attributen selektieren? Wir haben bereits verschiedene EJB entwickelt (Hotel, Reservierung,…) und ich moechte nun mit JSP z. B. alle Hotels ausgeben, in denen noch ein Zimmer mit Bad frei ist. Mir ist schon klar, dass ich die Entity Beans nur ueber das Home-/Remote-Interface ansprechen kann, aber von den Methoden im Home-Interface (ejbFindByPrimaryKey(), ejbLoad(), ejbStore(),…) erscheint mir keine geeignet, denn ich weiss ja den PrimaryKey zum Zeitpunkt der Abfrage ueberhaupt nicht. Wie macht man das richtig? Am meisten wuerde mir ein kleiner Schnipsel Beispiel-Code helfen.

  1. Verbindung des EJB-Containers zu Oracle

Wenn wir Cloudscape (die DB vom J2EE Server) benutzen, lassen sich die EJB ohne Probleme hot-deployen, aber Oracle wird nicht als EJB-Container erkannt. Fehlermeldung: „No suitable driver“. Wir haben jedoch auf jeden Fall den richtigen JDBC-Thin-Treiber installiert, mit einer normalen Java-Applikation laesst sich Oracle damit ansprechen. JNDI-Name, User und Passwort haben wir laut Doku beim Deployment (mit dem Sun J2EE Deployment Tool) eingetragen. Wo koennte hier der Fehler liegen?

Gruesse, Tanja

Hallo Tanja.

  1. Mit JSP EJB-ResultSet selektieren

Ein EJB macht genau ein Java-Objekt persistent.
Wenn du also mehrere Objekte haben willst gibt es zwei Moeglichtkeiten:

  1. Man iteriert auf der Client-Seite, d.h. in der JSP ueber alle Objekte. Das ist natuerlich nicht sehr performant.
  2. Man schreib eine Session-Bean, die die entsprechenden Datenbankabfrage durchfuehrt und eine Menge von Objekten als Ergebnis liefert (z. B. eine Liste). Diese Menge wird dann in der JSP angezeigt. Hat man ein bestimmtes Object ausgewaehlt, dann greift man ueber die Entity-Bean darauf zu.
    Das ist nicht sehr schoen, aber es funktioniert.

Mehr zum Thema EJB’s unter www.theserverside.com.
Vor allem die Patterns sind ganz interessant.

  1. Verbindung des EJB-Containers zu Oracle

Da kann ich dir leider auch keinen Tip geben.

Gruesse

Armin

Hallo Armin!

Danke für Deine Antwort!

  1. Mit JSP EJB-ResultSet selektieren

Man schreib eine Session-Bean, die die entsprechenden
Datenbankabfrage durchfuehrt und eine Menge von Objekten als
Ergebnis liefert (z. B. eine Liste). Diese Menge wird dann in
der JSP angezeigt. Hat man ein bestimmtes Object ausgewaehlt,
dann greift man ueber die Entity-Bean darauf zu.

Mmh. Also, ich habe das so verstanden, daß ich für jeden Typ einer Suchanfrage eine Finder-Methode im Home-Interface der Bean (also eine Session-Bean?) brauche.

Dann erzeuge ich in der JSP-Seite ein Objekt mit den gesuchten Attributen und übergebe es dieser Methode. Bei container-managed persistence erzeugt der EJB-Container (ohne Implementierung der Finder-Methode???) die notwendigen SQL-Statements und gibt mir eine Menge von Objekten zurück. Ist das so einigermaßen richtig?

Was mir aber jetzt noch unklar ist, wir haben beispielsweise ein Hotel-EJB mit dem Preis für ein Zimmer als Attribut (als int gespeichert). Wie macht man das jetzt, wenn jemand alle Hotels in der Preisklasse von 200 - 300 DM sucht? Muß ich jetzt der Finder-Methode 100 Objekte mit fortlaufenden Preisen übergeben, oder wie funktioniert das?

Mehr zum Thema EJB’s unter www.theserverside.com.
Vor allem die Patterns sind ganz interessant.

Nette Seite.

  1. Verbindung des EJB-Containers zu Oracle

Macht nichts, notfalls nehmen wir halt Cloudscape.

Grüße, Tanja

Hallo Tanja.

Mmh. Also, ich habe das so verstanden, daß ich für jeden Typ
einer Suchanfrage eine Finder-Methode im Home-Interface der
Bean (also eine Session-Bean?) brauche.

Dann erzeuge ich in der JSP-Seite ein Objekt mit den gesuchten
Attributen und übergebe es dieser Methode. Bei
container-managed persistence erzeugt der EJB-Container (ohne
Implementierung der Finder-Methode???) die notwendigen
SQL-Statements und gibt mir eine Menge von Objekten zurück.
Ist das so einigermaßen richtig?

Nicht ganz.
Die Session-Bean enthaelt das SQL-Statement fuer die Suchanfrage.
Dieses Statement muss von Hand erstellt werden.
Man erstellt also ein Select-Statement und setzt es ueber JDBC direct auf die Datenbank ab ohne Umweg ueber die Entity-Beans.
Die Ergebnise werden dann in eine Datenstruktur (z. B. Liste) geschrieben. Diese Liste wird dann von der JSP genutzt.
Da es sich nur um lesende Zugriffe handelt, stellt dies kein Problem hinsichtlich der Datenkonsistenz dar.
Problematisch wird die Sache natuerlich, wenn sich das Datenbankschema aendert. Das SQL-Statements in der Session-Bean wird nicht automatisch angepasst, also Vorsicht.
Die Entity-Beans kommen erst ins Spiel, wenn mit den einzelnen Objekten operiert wird (z. B. eine Attribut-Aenderung).
Die Verwendung der Finder-Methode ist recht teuer und sollte daher so selten wie moeglich erfolgen.

Ist es so klar genug. Ansonsten frag einfach noch mal nach.

Armin

Hallo Armin!

Sorry, jetzt muß ich noch mal nerven! :wink:

Die Session-Bean enthaelt das SQL-Statement fuer die
Suchanfrage. Dieses Statement muss von Hand erstellt werden.
Man erstellt also ein Select-Statement und setzt es ueber JDBC
direct auf die Datenbank ab ohne Umweg ueber die Entity-Beans.
Die Ergebnise werden dann in eine Datenstruktur (z. B. Liste)
geschrieben. Diese Liste wird dann von der JSP genutzt.

Wenn wir unsere EJB deployen, erstellt uns unser Application auf jeden Fall die notwendigen SQL-Statements! Das ist doch gerade der Vorteil von container-managed-persistence im Vergleich zu bean-managed-persistence, daß der Application Server die Datenbankzugriffe vornimmt und die Statements generiert, oder? Man muß nur den WHERE-Teil des Statments selbst schreiben:

"The Finder Methods

The ProductHome interface defines the following finder methods:

public Product findByPrimaryKey(String productId) 
throws FinderException, RemoteException;

public Collection findByDescription(String description)
throws FinderException, RemoteException;

public Collection findInRange(double low, double high)
throws FinderException, RemoteException;

Because the ProductEJB class uses container-managed persistence, it does not implement these finder methods. The Application Deployment tool implements the findByPrimaryKey method, including the SQL select statement that retrieves the row from the database.

The tool also implements the customized finder methods (findByDescription and findInRange), but you must specify the where clauses for their select statements. Because the ProductEJB class uses container-managed persistence, it does not implement these finder methods."

Quelle: http://developer.iplanet.com/appserver/samples/j2eeg…

Was mir aber jetzt noch unklar ist, wir haben beispielsweise
ein Hotel-EJB mit dem Preis für ein Zimmer als Attribut (als
int gespeichert). Wie macht man das jetzt, wenn jemand alle
Hotels in der Preisklasse von 200 - 300 DM sucht?

Die oben beschriebene Methode findInRange() wäre dann die Lösung dazu.

Grüße, Tanja

Hallo Tanja.

Sorry, jetzt muß ich noch mal nerven! :wink:

Kein Problem.

Alles richtig, aber der Zugriff auf ein Objekt ueber EntityBeans ist sehr teuer, da jedesmal ein RMI-Aufruf abgesetzt wird.
Verwendet man dagegen eine SessionBean, wie von mir beschrieben, wird die gesamte Ergebnismenge ueber einen einzigen RMI-Aufruf zurueckgeliefert.
Ausserdem wird fuer jede EntityBean Severseitig eine neue Instanz erzeugt, was natuerlich auch sehr teuer ist.

Probier einfach beides aus und nimm die Loesung, die dir am besten erscheint.

Lass mich wissen, wie du es letztendlich realisiert hast.

Viele Gruesse

Armin