Ausnahmen beim Datenzugriff
Alle CMP-Beans (Container-managed Persistence) einer Enterprise-Bean empfangen gemäß Spezifikation Enterprise JavaBeans (EJB) 2.x beim Scheitern einer Operation eine EJB-Standardausnahme. JDBC-Anwendungen (Java™ Database Connectivity) empfangen beim Scheitern einer JDBC-Operation eine SQL-Standardausnahme. Das Programm stellt spezielle Ausnahmen für seinen relationalen Ressourcenadapter (RRA, Relational Resource Adapter) bereit, die anzeigen, dass die derzeit gehaltene Verbindung nicht mehr gültig ist.
- Die Ausnahme aufgrund der Wartezeitüberschreitung
zeigt an, dass die Anwendung zwar das definierte Verbindungszeitlimit
(in Sekunden) abgewartet, aber keine Verbindung erhalten hat. Dieser Fall kann eintreten, wenn die maximale Poolgröße erreicht ist und alle
Verbindungen während der gesamten Wartezeit von anderen Anwendungen genutzt werden. Darüber hinaus ist keine der derzeit im Gebrauch befindlichen
Verbindungen für die gemeinsame Benutzung freigegeben, weil die Verbindungseigenschaften nicht übereinstimmen oder
die Verbindungen in einer anderen Transaktion ausgeführt werden.
Für eine Datenquelle der Version 4.0 erstellt das Objekt "ConnectionWaitTimeout" eine Ausnahme, die von der Klasse "com.ibm.ejs.cm.pool.ConnectionWaitTimeoutException" instanziiert wird.
Für J2C-Verbindungsfactorys (Java 2 Connector) generiert das Objekt "ConnectionWaitTimeout" eine Ressourcenausnahme der Klasse "com.ibm.websphere.ce.j2c.ConnectionWaitTimeoutException".
Wenn das Fehlererkennungsmodell für die Ausnahmezuordnung konfiguriert ist, geben spätere Versionen der Datenquellen eine SQL-Ausnahme der Unterklasse "com.ibm.websphere.ce.cm.ConnectionWaitTimeoutException" aus. Wenn das Fehlererkennungsmodell für die Ausnahmeprüfung konfiguriert ist, geben spätere Versionen der Datenquellen eine SQL-Ausnahme der Klasse "java.sql.SQLTransientConnectionException" mit einer verketteten Ausnahme der Klasse "com.ibm.websphere.ce.cm.ConnectionWaitTimeoutException" aus.
- Wenn das Fehlererkennungsmodell für die Ausnahmezuordnung konfiguriert ist, zeigt die Ausnahme für veraltete Verbindungen an, dass die Verbindung nicht mehr gültig ist. Wenn das Fehlererkennungsmodell für die Ausnahmeprüfung konfiguriert ist, löst der JDBC-Treiber eine JDBC-4.0-Ausnahme wie z. B. "java.sql.SQLRecoverableException" oder "java.sql.SQLNonTransientConnectionException" aus, oder der JDBC-Treiber gibt einen geeigneten SQLState an, um anzuzeigen, dass die Verbindung nicht mehr gültig ist. Weitere Informationen zu diesem Ausnahmetyp finden Sie im Artikel "Veraltete Verbindungen".
- Die Einträge werden durch das Zeichen ; (Semikolon) begrenzt.
- Jeder Eintrag besteht aus einem Schlüssel und einem Wert, wobei der Schlüssel ein Fehlercode (numerischer Wert) oder SQLState ist, d. h., ein in Anführungszeichen eingeschlossener Text.
- Schlüssel und Werte sind durch = (Gleichheitszeichen) getrennt.
"S1000"=;1062=com.ibm.websphere.ce.cm.DuplicateKeyException;"08004"=com.ibm.websphere.ce.cm.StaleConnectionException
"userDefinedErrorMap" kann in der Administrationskonsole definiert werden, indem die Datenquelle ausgewählt und die
angepassten Eigenschaften konfiguriert werden.- Veraltete Verbindungen
- Beispiel: Behandlung von Ausnahmen beim Datenzugriff - Veraltete Verbindung
- Veraltete Verbindung auf Linux-Systemen
- Beispiel: Behandlung von Ausnahmen der Servlet-JDBC-Verbindung
- Beispiel: Behandlung von Verbindungsausnahmen für Session-Beans in containergesteuerten Datenbanktransaktionen
- Beispiel: Behandlung von Verbindungsausnahmen für Session-Beans in Bean-gesteuerten Datenbanktransaktionen
- Beispiel: Behandlung von Verbindungsausnahmen für BMP-Beans in containergesteuerten Datenbanktransaktionen
- Beispiel: Behandlung von Ausnahmen beim Datenzugriff - ConnectionWaitTimeoutException (für die JDBC-API)
- Beispiel: Behandlung von Ausnahmen beim Datenzugriff - ConnectionWaitTimeoutException (für Java EE Connector Architecture)
- Beispiel: Behandlung von Ausnahmen beim Datenzugriff - Fehlerzuordnung in DataStoreHelper
- Datenbank-Deadlocks und Konflikte bei Fremdschlüsseln
Veraltete Verbindungen
Das Produkt stellt die spezielle Unterklasse "java.sql.SQLException" für die Verwendung des Verbindungs-Pooling für den Zugriff auf relationale Datenbanken bereit. Die Unterklasse "com.ibm.websphere.ce.cm.StaleConnectionException" in den WebSphere-Datenquellen der Version 4.0 und in den Datenquellen der aktuellen Version, die den relationalen Ressourcenadapter verwenden, vorhanden. Diese Unterklasse zeigt an, dass die gehaltene Verbindung nicht mehr gültig ist.
- Die Anwendung fordert eine Verbindung an und schlägt fehlt, wenn die Datenbank nicht gestartet ist.
- Die Verbindung kann aufgrund eines Datenbankfehlers nicht mehr verwendet werden. Wenn eine Anwendung versucht, eine zuvor angeforderte Verbindung zu verwenden, ist die Verbindung nicht mehr gültig. In diesem Fall kann in allen Verbindungen, die derzeit von der Verbindung verwendet werden, dieser Fehler auftreten.
- Die Verbindung ist verwaist (weil die Anwendung die Verbindung in dem Zeitlimit, das mit der Einstellung "Zeitlimit für nicht verwendete Verbindungen" mindestens zwei Mal nicht verwendet hat), und die Anwendung versucht, die verwaiste Verbindung zu verwenden. Dies gilt nur für Datenquellen der Version 4.0.
- Die Anwendung versucht, eine JDBC-Ressource zu verwenden, z. B. eine Anweisung, die in einer nicht aktuellen Verbindung angefordert wurde.
- Eine Verbindung wird von der Datenquelle der Version 4.0 geschlossen
(Funktion für automatische Bereinigung von Verbindungen) und ist nicht
mehr verwendbar. Die automatische Verbindungsbereinigung ist der Standardmodus, in dem die Verbindungsverwaltung
arbeitet. In diesem Modus schließt der Transaktionsmanager am Ende einer Transaktion
alle Verbindungen, die für diese Transaktion registriert sind. Auf diese Weise kann der Transaktionsmanager sicherstellen, dass
Verbindungen nicht über einen längeren Zeitraum aufrechterhalten
werden, und dass der Pool nicht vorzeitig die maximale Anzahl von Verbindungen erreicht.
Wenn der Transaktionsmanager die Verbindungen schließt und nach dem Ende einer Transaktion an den Pool freier Verbindungen zurückgibt, hat dies zur Folge, dass eine Anwendung nicht in einer Transaktion eine Verbindung anfordern und diese in einer anderen Transaktion verwenden kann. Wenn die Anwendung dies versucht, wird eine Ausnahme des Typs ObjectClosedException ausgelöst, die wiederum eine StaleConnectionException-Ausnahme auslöst, weil die Verbindung bereits geschlossen ist.
- Wenn Sie die Mindestgröße des Verbindungspools auf 0 setzen, bleibt der Verbindungspool leer, wenn der Anwendungsserver während eines längeren Zeitraums inaktiv ist. Dadurch können Sie vermeiden, dass Verbindungen aufgrund der Verwaltungsaktivität auf der Datenbankseite als nicht aktuell eingestuft werden.
- Setzen Sie das Zeitlimit für nicht verwendete Verbindungen für den Verbindungspool auf einen Wert, der kleiner ist als der für das Zeitlimit der Firewall konfigurierte Wert. Dadurch wird sichergestellt, dass die Verbindung bis zum Ablauf des Zeitlimits für nicht verwendete Verbindungen nicht als abgelaufen markiert wird und ermöglicht, dass die Verbindung zwecks Wiederverwendung im freien Pool verbleibt.
- Setzen sie die Bereinigungszeit für den Verbindungspool auf einen Wert, der kleiner ist als das Zeitlimit für nicht verwendete Verbindungen. Je kleiner der Wert, desto häufiger prüft der Poolverwaltungsthread und desto genauer wird der Zeitgeber für nicht verwaltete Verbindungen eingestellt. Allerdings können häufig ausgeführte Poolverwaltungsthreads zu einer Leistungsverschlechterung führen.
Wenn versucht wird, eine verwaiste Verbindung oder eine durch die automatische Bereinigung geschlossene Verbindung zu verwenden, weist eine Ausnahme wegen einer veralteten Verbindung darauf hin, dass die Anwendung versucht hat, eine bereits an den Verbindungspool zurückgegebene Verbindung zu verwenden. Diese Ausnahme weist jedoch nicht auf ein tatsächliches Problem mit der Verbindung hin. In anderen Fällen kann die Ausnahme wegen einer nicht aktuellen Verbindung anzeigen, dass die Verbindung zur Datenbank ungültig oder nicht aktuell ist. Wenn eine Verbindung nicht aktuell ist, kann sie nicht wiederhergestellt werden. Sie müssen die Verbindung vollständig schließen, anstatt sie an den Pool zurückzugeben.
Veraltete Verbindungen erkennenWenn eine Verbindung zur Datenbank veraltet, löst der JDBC-Treiber beim Ausführen von Operationen in dieser Verbindung eine SQL-Ausnahme aus. Weil eine SQL-Ausnahme eine eher generische Ausnahme ist, enthält sie Status- und Fehlercodes, die Sie verwenden können, um die Bedeutung der Ausnahme zu bestimmen. Allerdings unterscheiden sich die Bedeutungen dieser Status- und Fehlercodes je nach Datenbankhersteller. Die Laufzeit des Verbindungs-Pooling verwaltet für jeden unterstützten Datenbankhersteller eine Aufstellung darüber, welche SQL-Status- und Fehlercodes eine Ausnahme wegen einer nicht aktuellen Verbindung anzeigen. Wenn die Laufzeitumgebung für das Verbindungs-Pooling eine SQL-Ausnahme abfängt, prüft sie, ob diese SQL-Ausnahme eine Ausnahme wegen einer nicht aktuellen Verbindung für den verwendeten Datenbankserver ist.
Wiederherstellung im Falle von veralteten Verbindungen- Wenn das Fehlererkennungsmodell für die Ausnahmezuordnung konfiguriert ist, ersetzt der Anwendungsserver die vom JDBC-Treiber ausgelöste Ausnahme durch die Ausnahme "StaleConnectionException". In diesem Fall kann die Anwendung eine Ausnahme aufgrund einer nicht aktuellen Verbindung abfangen.
- Wenn das Fehlererkennungsmodell für die Ausnahmeprüfung konfiguriert ist, prüft der Anwendungsserver weiterhin die Fehlerzuordnungstabelle, um den Verbindungspool zu verwalten, aber die Ausnahme wird nicht ersetzt. In diesem Fall sollte die Anwendung eine Ausnahme aufgrund einer nicht aktuellen Verbindung nicht abfangen.
Aufgrund der Unterschiede zwischen den Fehlererkennungsmodellen stellt der Anwendungsserver eine API bereit, die die Anwendungen in beiden Fällen verwenden können, um nicht aktuelle Verbindungen zu identifizieren. Hierbei handelt es sich um die API "com.ibm.websphere.rsadapter.WSCallHelper.getDataStoreHelper(datasource).isConnectionError(sqlexception)".
Anwendungen müssen eine Ausnahme aufgrund einer nicht aktuellen Verbindung nicht explizit identifizieren. Die Anwendungen müssen bereits Ausnahmen des Typs "java.sql.SQLException" abfangen, und die Ausnahmen über nicht aktuelle Verbindung oder die vom JDBC-Treiber ausgelöste Ausnahme übernimmt immer die Daten aus der Ausnahme "java.sql.SQLException". Die Ausnahme wegen einer nicht aktuellen Verbindung, die von jeder Methode ausgelöst werden kann, die für das Erstellen von "SQLException" deklariert wurde, wird automatisch im allgemeinen Abfangblock (catch-block) abgefangen. Wenn die Ausnahme wegen einer nicht aktuellen Verbindung jedoch explizit identifiziert werden kann, ist eine Wiederherstellung der Anwendung nach dem Erkennung ungültiger Verbindungen möglich. Wenn der Anwendungscode eine Ausnahme wegen einer nicht aktuellen Verbindung identifiziert, sollte er explizit Schritte zur Wiederherstellung ausführen, z. B. die Operation unter einer neuen Transaktion und einer neuen Verbindung wiederholen.
Beispiel: Behandlung von Ausnahmen beim Datenzugriff - Veraltete Verbindung
Diese Codebeispiele zeigen, wie Ausnahmen wegen veralteter Verbindungen für unterschiedliche Arten von Datenzugriffsclients in unterschiedlichen Transaktionszenarien über das Programm behandelt werden.
Wenn eine Anwendung eine Ausnahme wegen einer veralteten Verbindung für eine Datenbankoperation empfängt, zeigt sie an, dass die gegenwärtig gespeicherte Verbindung nicht mehr gültig ist. Obwohl eine Ausnahme vom Typ "Veraltete Verbindung" für jede Datenbankoperation zurückgegeben werden kann, wird eine solche Ausnahme am häufigsten zurückgegeben, wenn die Verbindung zum ersten Mal abgerufen wird. Da Verbindungen in Pools gestellt werden, wird ein Datenbankfehler erst ermittelt, wenn die Operation, die unmittelbar auf den Abruf aus dem Pool folgt, ausgeführt wird, d. h., wenn zum ersten Mal versucht wird, mit der Datenbank zu kommunizieren. Die Verbindung wird erst bei ihrer Ermittlung als alt markiert. Die Ausnahme wegen einer veralteten Verbindung tritt seltener auf, wenn alle Methoden, die auf die Datenbank zugreifen, eine neue Verbindung aus dem Pool abrufen.

Bevor die Anwendung eine neue Verbindung abrufen kann, um die Operation zu wiederholen, müssen Sie die Transaktion, an der die ursprüngliche Verbindung beteiligt war, zurücksetzen und eine neue Transaktion starten. Sie können die Informationen zu dieser Aktion in die folgenden beiden Kategorien unterteilen:
- Objekte, die in einem Bean-gesteuerten globalen Transaktionskontext (der in derselben Methode gestartet wurde wie der Datenbankzugriff) ausgeführt werden
- Eine Servlet- oder Session-Bean mit Bean-gesteuerten Transaktionen
(BMT) kann eine Transaktion explizit starten, indem sie begin() für
ein javax.transaction.UserTransaction-Objekt aufruft. Dieses Objekt kann vom
Namensservice oder vom EJBContext-Objekt der Bean abgerufen werden.
Zum
Festschreiben einer Bean-gesteuerten Transaktion ruft die Anwendung commit()
für das UserTransaction-Objekt auf. Zum Zurücksetzen der Transaktion ruft
die Anwendung rollback() auf. Entity-Beans und Nicht-BMT-Session-Beans können globale Transaktionen nicht starten.
Wenn ein Objekt, das explizit eine Bean-gesteuerte Transaktion gestartet hat, eine Ausnahme wegen einer veralteten Verbindung für eine Datenbankoperation empfängt, müssen Sie die Verbindung schließen und die Transaktion zurücksetzen. An diesem Punkt kann der Entwickler entscheiden, ob er eine neue Transaktion beginnen, eine neue Verbindung abrufen und die Operation wiederholen soll.
Das folgende Codefragment ist ein Beispiel für die Behandlung von Ausnahmen wegen veralteten Verbindungen in diesem Szenario:// userTransaction abrufen javax.transaction.UserTransaction tran = getSessionContext().getUserTransaction(); //retry zeigt an, ob Wiederholungen durchgeführt werden sollen //numOfRetries zeigt an, wie viele Wiederholungen versucht wurden boolean retry = false; int numOfRetries = 0; java.sql.Connection conn = null; java.sql.Statement stmt = null; do { try { //Transaktion starten tran.begin(); //Es wird vorausgesetzt, dass bereits eine Datenquelle //von JNDI abgerufen wurde conn = ds.getConnection(); conn.setAutoCommit(false); stmt = conn.createStatement(); stmt.execute("INSERT INTO EMPLOYEES VALUES (0101, 'Bill', 'R', 'Smith')"); tran.commit(); retry = false; } catch(java.sql.SQLException sqlX) { // Wenn der Fehler darauf hinweist, dass die Verbindung veraltet ist, // eine ROLLBACK-Operation ausführen und die Aktion wiederholen if (com.ibm.websphere.rsadapter.WSCallHelper .getDataStoreHelper(ds) .isConnectionError(sqlX)) { try { tran.rollback(); } catch (java.lang.Exception e) { //Ausnahme prüfen //Kann normalerweise ignoriert werden } if (numOfRetries < 2) { retry = true; numOfRetries++; } else { retry = false; } } else { //Ausnahme für andere Datenbank prüfen retry = false } } finally { //JDBC-Ressourcen immer löschen try { if(stmt != null) stmt.close(); } catch (java.sql.SQLException sqle) { //Kann normalerweise ignoriert werden } try { if(conn != null) conn.close(); } catch (java.sql.SQLException sqle) { //Kann normalerweise ignoriert werden } } } while (retry) ;
- Objekte, die in einem Bean-gesteuerten globalen Transaktionskontext ausgeführt werden, und eine Transaktion, die nicht in derselben Methode gestartet wurde wie der Datenbankzugriff.
- Wenn das Objekt, das die Ausnahme wegen einer veralteten Verbindung empfängt, die Transaktion nicht direkt
steuern kann, wie z. B. im Falle einer containergesteuerten Transaktion, muss es die
Transaktion für das Zurücksetzen markieren und seinem aufrufenden Prozess (Caller)
mitteilen, dass es die Transaktion wiederholen soll. In den meisten Fällen können Sie
zu diesem Zweck für die Anwendung eine Ausnahme auslösen, die angibt, dass die
Operation wiederholt werden soll.
Diese Aktion ist jedoch nicht
immer zulässig, und oft ist eine Methode so definiert, dass sie nur eine
bestimmte Ausnahme auslöst. Dies trifft auf die Methoden ejbLoad() und ejbStore() in einer Enterprise-Bean zu. Die nächsten beiden Beispiele veranschaulichen
diese Szenarien.
- Beispiel 1: Methode für Datenbankzugriff löst eine Anwendungsausnahme aus
- Wenn die Methode, die auf die Datenbank zugreift, jede erforderliche Ausnahme auslösen kann, empfiehlt es sich die
Ausnahme wegen veralteter Verbindung abzufangen und eine Anwendungsausnahme zu erstellen, die Sie interpretieren können, um die Methode
zu wiederholen.
Das
folgende Beispiel zeigt einen EJB-Client, der eine Methode mit der
Transaktionsabgrenzung TX_REQUIRED für eine Entity-Bean aufruft, d. h., dass der
Container eine globale Transaktion startet, wenn die Methode insertValue() aufgerufen wird:
public class MyEJBClient { //... andere Methoden hier ... public void myEJBClientMethod() { MyEJB myEJB = myEJBHome.findByPrimaryKey("myEJB"); boolean retry = false; do { try { retry = false; myEJB.insertValue(); } catch(RetryableConnectionException retryable) { retry = true; } catch(Exception e) { /* handle some other problem */ } } while (retry); } } //MyEJBClient beenden public class MyEJB implements javax.ejb.EntityBean { //... andere Methoden hier ... public void insertValue() throws RetryableConnectionException, java.rmi.EJBException { try { conn = ds.getConnection(); stmt = conn.createStatement(); stmt.execute("INSERT INTO my_table VALUES (1)"); } catch(java.sql.SQLException sqlX) { // Herausfinden, ob der Fehler darauf hinweist, dass die Verbindung veraltet ist if (com.ibm.websphere.rsadapter.WSCallHelper .getDataStoreHelper(ds) .isConnectionError(sqlX)) { getSessionContext().setRollbackOnly(); throw new RetryableConnectionException(); } else { //Fehler in anderer Datenbank beheben } } finally { //JDBC-Ressourcen immer löschen try { if(stmt != null) stmt.close(); } catch (java.sql.SQLException sqle) { //Kann normalerweise ignoriert werden } try { if(conn != null) conn.close(); } catch (java.sql.SQLException sqle) { //Kann normalerweise ignoriert werden } } } } //MyEJB beenden
MyEJBClient ruft zuerst eine MyEJB-Bean von der Home-Schnittstelle ab, von dem angenommen wird, dass es zuvor über JNDI (Java Naming and Directory Interface) abgerufen wurde. Dann ruft der Client insertValue() für die Bean ab. Die Methode für die Bean ruft eine Verbindung ab und versucht, einen Wert in eine Tabelle einzufügen. Wenn eine der Methode mit einer Ausnahme wegen veralteter Verbindung fehlschlägt, wird die Transaktion als rollbackOnly gekennzeichnet (was den Caller (Aufrufender) dazu veranlasst, die Transaktion rückgängig zu machen) und eine neue Ausnahme vom Typ wiederholbare Verbindung erstellt, die die Ressourcen bereinigt, bevor die Ausnahme ausgelöst wird. Die Ausnahme für wiederholbare Verbindung ist lediglich eine anwendungsdefinierte Ausnahme, die dem Caller mitteilt, die Methode zu wiederholen. Der aufrufende Prozess überwacht diese Ausnahme und wiederholt die Methode, wenn die Ausnahme abgefangen wird. In diesem Beispiel ist keine Transaktionsverwaltung auf dem Client oder dem Server erforderlich; da der Container in der Transaktion beginnt und endet. Der Client kann natürlich eine Bean-gesteuerte Transaktion starten, und das Verhalten ist dann, vorausgesetzt, der Client hat die Transaktion festgeschrieben oder zurückgesetzt.
- Beispiel 2: Die Methode für Datenbankzugriff erstellt eine Ausnahme onlyRemote oder eine EJB-Ausnahme
- Nicht alle Methoden haben die Berechtigung, von der Anwendung definierte
Ausnahmen auszulösen.
Wenn Sie mit BMP (Bean-Managed Persistence, über JavaBeans realisierte Transaktionspersistenz
oder einfach Bean-gesteuerte Persistenz) arbeiten, werden die Methoden
ejbLoad() und ejbStore() zum Speichern des Bean-Status verwendet. Die einzigen
Ausnahmen, die von diesen Methoden ausgelöst werden, sind
java.rmi.Remote und javax.ejb.EJB. Daher können Sie
nicht wie im vorigen Beispiel beschrieben vorgehen.Wenn Sie mit containergesteuerter Persistenz (CMP) arbeiten, verwaltet der Container die Bean-Persistenz, und es ist auch der Container, der die Ausnahme wegen veralteter Verbindung erkennt. Wenn eine veraltete Verbindung erkannt wird, ist die Ausnahme zu dem Zeitpunkt, zu dem sie an den Client zurückgegeben wird, lediglich eine ferne Ausnahme. Deshalb ist ein einfacher Abfangblock (Catch-Block) nicht ausreichend. Es besteht jedoch die Möglichkeit festzustellen, ob die ursprüngliche Ursache einer fernen Ausnahme eine Ausnahme wegen veralteter Verbindung ist. Wenn die ferne Methode eine andere Ausnahme einschließt, wird die ursprüngliche Ausnahme in der Regel beibehalten. Alle fernen Ausnahmeinstanzen haben eine Detaileigenschaft des Typs java.lang.Throwable. Mit dieser Detaileigenschaft können Sie die ursprüngliche Ausnahme ermitteln. Falls es sich dabei um eine Ausnahme wegen veralteter Verbindung handelt, können Sie die Transaktion wiederholen. Tatsächlich geht die Detaileigenschaft verloren, wenn eine dieser fernen Ausnahmen von einer JVM-API an die nächste übergeben wird, daher empfiehlt es sich, eine Transaktion auf demselben Server zu starten, auf dem der Datenbankzugriff erfolgt. Aus diesem Grund zeigt das folgende Beispiel eine Entity-Bean, auf die eine Session-Bean mit Bean-gesteuerter Transaktionsabgrenzung zugreift.
public class MySessionBean extends javax.ejb.SessionBean { ... other methods here ... public void mySessionBMTMethod() throws java.rmi.EJBException { javax.transaction.UserTransaction tran = getSessionContext().getUserTransaction(); boolean retry = false; do { try { retry = false; tran.begin(); // Bewirkt, dass ejbLoad() gestartet wird myBMPBean.myMethod(); // Bewirkt, dass ejbStore() gestartet wird tran.commit(); } catch(java.rmi.EJBException re) { try { tran.rollback(); } catch (Exception e) { //Kann ignoriert werden } if (causedByStaleConnection(re)) retry = true; else throw re; } catch (Exception e) { // Andere Fehler beheben } finally { //JDBC-Ressourcen immer löschen try { if(stmt != null) stmt.close(); } catch (java.sql.SQLException sqle) { //Kann normalerweise ignoriert werden } try { if(conn != null) conn.close(); } catch (java.sql.SQLException sqle) { //Kann normalerweise ignoriert werden } } } while (retry); } public boolean causedByStaleConnection(java.rmi.EJBException re) { // In der Ausnahmekette nach Fehlern suchen, die auf eine // veraltete Verbindung hinweist for (Throwable t = re; t != null; t = t.getCause()) if (t instanceof RetryableConnectionException) return true; // Verbindung nicht veraltet return false; } } public class MyEntityBean extends javax.ejb.EntityBean { ... other methods here ... public void ejbStore() throws java.rmi.EJBException { try { conn = ds.getConnection(); stmt = conn.createStatement(); stmt.execute("UPDATE my_table SET value=1 WHERE primaryKey=" + myPrimaryKey); } catch(java.sql.SQLException sqlX) { // Herausfinden, ob der Fehler darauf hinweist, dass die Verbindung veraltet ist if (com.ibm.websphere.rsadapter.WSCallHelper .getDataStoreHelper(ds) .isConnectionError(sqlX)) { // Transaktion bei Rückgabe der Methode zurücksetzen getEntityContext().setRollbackOnly(); throw new java.rmi.EJBException( "Exception occurred in ejbStore", new RetryableConnectionException(sqlX)); } else { // Andere Fehler beheben } } finally { //JDBC-Ressourcen immer löschen try { if(stmt != null) stmt.close(); } catch (java.sql.SQLException sqle) { //Kann normalerweise ignoriert werden } try { if(conn != null) conn.close(); } catch (java.sql.SQLException sqle) { //Kann normalerweise ignoriert werden } } } }
In mySessionBMTMethod() des vorherigen Beispiels:- Die Session-Bean zuerst ein UserTransaction-Objekt vom Sitzungskontext ab und startet dann eine globale Transaktion.
- Dann ruft sie eine Methode für die Entity-Bean auf, die die Methode ejbLoad() aufruft. Wenn ejbLoad() ausgeführt wird, schreibt der Client die Transaktion anschließend fest und bewirkt, dass die Methode ejbStore() aufgerufen wird.
- In ejbStore() ruft die Entity-Bean eine Verbindung ab und schreibt deren Status in die Datenbank. Wenn die abgerufene Verbindung alt ist, wird sie als rollbackOnly markiert, und eine neue EJBException, die auf die RetryableConnectionException folgt, wird ausgelöst. Diese Ausnahme wird vom Client abgefangen, der die JDBC-Ressourcen bereinigt, die Transaktion rückgängig macht und die Methode causedByStaleConnection() aufruft, die feststellt, ob eine Ausnahme wegen veralteter Verbindung irgendwo in der Ausnahme verborgen ist.
- Wenn die Methode den Wert "true" zurückgibt, wird das retry-Flag gesetzt, die Transaktion wird wiederholt. Andernfalls wird die Ausnahme für den aufrufenden Prozess erneut ausgelöst.
- Die Methode causedByStaleConnection() durchsucht die Kette von Detailattributen, um die Originalausnahme zu ermitteln. Bis die Ausnahme den Client endgültig wieder erreicht, können mehrere Ausnahmen in der ausgelösten Ausnahme verborgen sein. Deshalb sucht die Methode weiter, bis sie eine Ausnahme vom Typ "Veraltete Verbindung" findet und true zurückgegeben wird. Wenn keine Ausnahme dieses Typs in der Liste gefunden wird, wird false zurückgegeben.
- Wenn die Kommunikation mit einer CMP-Bean anstatt mit einer BMP-Bean erfolgt, ist die Session-Bean gleich. Die Methode ejbStore() der CMP-Bean ist dann höchstwahrscheinlich leer, und der Container speichert die Bean mit generiertem Code persistent, nachdem er die Methode aufgerufen hat.
- Wenn während der Persistenz eine Ausnahme wegen einer veralteten Verbindung auftritt, wird sie in einer fernen Ausnahme verborgen, die an den aufrufenden Prozess zurückgegeben wird. Die Methode causedByStaleConnection() durchsucht die Ausnahmekette dann erneut nach der eigentlichen Ausnahme, der Ausnahme wegen veralteter Verbindung.
- Objekte, die in einem lokalen Transaktionskontext ausgeführt werden
- Wenn
eine Datenbankoperation außerhalb des globalen Transaktionskontextes ausgeführt
wird, wird eine lokale Transaktion vom Container implizit gestartet. Dies umfasst
Servlets oder JSPs, die Transaktionen nicht mit der Schnittstelle UserTransaction
starten, sowie Enterprise-Beans, die in nicht angegebenen
Transaktionskontexten ausgeführt werden. Wie bei globalen Transaktionen müssen Sie
die lokale Transaktion zurücksetzen, bevor die Operation wiederholt wird. In diesen
Fällen endet das LTC (Local Transaction Containment), wenn die Geschäftsmethode
endet. Dies gilt nur in den Fällen, in denen Sie Activity-Sessions
verwenden, nicht. In diesem Fall muss die Activity-Session beendet werden,
bevor versucht wird, eine neue Verbindung abzurufen.
Wenn die lokale Transaktion in einer Enterprise-Bean ausgeführt wird, die in einem nicht angegebenen Transaktionskontext aktiv ist, kann das Clientobjekt der Enterprise-Bean außerhalb des LTC (Local Transaction Containment) die unter dem vorangegangenen Punkt beschriebene Methode verwenden, um die Transaktion zu wiederholen. Wenn das LTC jedoch als Teil eines Servlet oder einer JSP-Datei verwendet wird, ist kein Clientobjekt verfügbar, um die Operation zu wiederholen. Aus diesem Grund wird empfohlen, Datenbankoperationen in Servlets und in der JSP-Datei zu vermeiden, es sei denn, sie sind Bestandteil einer Benutzertransaktion.
Veraltete Verbindung auf Linux-Systemen
Damit Sie über den Anwendungsserver auf DB2-Datenbanken auf einer Linux-Plattform zugreifen können, müssen Sie möglicherweise ein Loopback festlegen.
- Wenn Sie mit dem DB2 Universal JDBC Driver Type 2 auf eine lokale DB2-Datenbank zugreifen
- Wenn Sie mit dem DB2 Universal JDBC Driver Type 2 auf DB2 for z/OS zugreifen und dazu eine Installation von DB2 Connect verwenden, die sich auf derselben Maschine befindet wie der Anwendungsserver. Das Problem tritt nur dann auf, wenn DB2 Connect die Ausführung von lokalen Clients innerhalb eines Agenten ausschließt, (d. h., wenn DB2_IN_APP_PROCESS nicht auf den Standardwert oder aber auf Yes gesetzt ist. Geben Sie No als Wert an, um das Problem zu beheben, und vermeiden Sie die Ausführung der folgenden Prozedur.)
'71' -SQLCC_ERR_CONN_CLOSED_BY_PARTNER and SQLCODE -XXXX
db2 catalog TCPIP node RHOST remote LHOST server 50000 db2 uncatalog db WAS db2 catalog db WAS as WASAlias at node loop authentication server //If you connect to WASAlias, it is connect through loopback; //If you connect to WAS, it is "normal" connect. db2 catalog db WASAlias as WAS at node RHOST
Beispiel: Behandlung von Ausnahmen der Servlet-JDBC-Verbindung.
Das folgende Codebeispiel zeigt, wie die Eigenschaften für die Transaktionsverwaltung und die Verbindungsverwaltung festgelegt werden, z. B. die Anzahl der Operationswiederholungen, um auf Ausnahmen wegen veralteter Verbindungen innerhalb einer Servlet-JDBC-Transaktion zu reagieren.
- Er initialisiert ein Servlet.
- Er ermittelt eine Datenquelle.
- Er legt die Fehlernachrichten, die Zahl der Verbindungswiederholungen und die Voraussetzungen für ein Rollback der Transaktion fest.
//===================START_PROLOG======================================
//
// 5630-A23, 5630-A22,
// (C) COPYRIGHT International Business Machines Corp. 2002,2008
// All Rights Reserved
// Licensed Materials - Property of IBM
// US Government Users Restricted Rights - Use, duplication or
// disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
//
// IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
// ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR
// CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
// USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
// OR PERFORMANCE OF THIS SOFTWARE.
//
//===================END_PROLOG========================================
package WebSphereSamples.ConnPool;
import java.io.*;
import javax.servlet.*;
import javax.servlet.http.*;
import java.util.*;
// JDBC-Pakete und Namensservicepaket importieren.
import java.sql.*;
import javax.sql.*;
import javax.naming.*;
import javax.transaction.*;
import com.ibm.websphere.ce.cm.ConnectionWaitTimeoutException;
import com.ibm.websphere.rsadapter.WSCallHelper;
public class EmployeeListTran extends HttpServlet {
private static DataSource ds = null;
private UserTransaction ut = null;
private static String title = "Mitarbeiterliste";
// ****************************************************************
// * Servlet beim ersten Laden initialisieren. *
// * Daten von properties-Datei abrufen und DataSource-Objekt *
// * über JNDI prüfen, um die Leistung der Servicemethoden *
// * des Servlet zu verbessern. *
// ****************************************************************
public void init(ServletConfig config)
throws ServletException
{
super.init(config);
getDS();
}
// ****************************************************************
// * JNDI-Lookup für das DataSource-Objekt und das UserTransaction-Objekt *
// * durchführen. *
// * Diese Methode wird von init() und vom Service aufgerufen *
// * Methode der Datenquelle ist null *
// ****************************************************************
private void getDS() {
try {
Hashtable parms = new Hashtable();
parms.put(Context.INITIAL_CONTEXT_FACTORY,
com.ibm.websphere.naming.WsnInitialContextFactory);
InitialContext ctx = new InitialContext(parms);
// Namensservice-Lookup zum Abrufen des DataSource-Objekts durchführen.
ds = (DataSource)ctx.lookup("java:comp/env/jdbc/SampleDB");
ut = (UserTransaction) ctx.lookup("java:comp/UserTransaction");
} catch (Exception e) {
System.out.println("Naming service exception: " + e.getMessage());
e.printStackTrace();
}
}
// ****************************************************************
// * Antwort auf GET-Anforderung des Benutzers *
// ****************************************************************
public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException
{
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
Vector employeeList = new Vector();
// retryCount auf die gewünschte Anzahl der Wiederholungen nach
// Ausnahme aufgrund einer veralteten Verbindung setzen
int retryCount = 5;
// Wenn der Datenbankcode erfolgreich ausgeführt wird, wird error = false eingestellt.
boolean error = true;
do
{
try
{
//Eine neue Transaktion starten
ut.begin();
// Verbindungsobjekt conn wird mit der DataSource-Factory abrufen.
conn = ds.getConnection();
// DB-Abfrage mit JDBC-Standardcodierung durchführen.
stmt = conn.createStatement();
String query = "Select FirstNme, MidInit, LastName " +
"from Employee ORDER BY LastName";
rs = stmt.executeQuery(query);
while (rs.next())
{
employeeList.addElement(rs.getString(3) + ", "+ rs.getString(1)" + " + rs.getString(2));
}
//error=false einstellen, um Fertigstellung der Datenbankoperationen anzuzeigen.
error=false;
}
catch (SQLException sqlX)
{
// Feststellen, ob das zulässige Zeitlimit für Verbindungsanforderungen
// überschritten ist.
// Dieser Code funktioniert mit jedem Fehlerkennungsmodell.
// Wenn die Ausnahmezuordnung aktiviert ist, muss nach einer
// ConnectionWaitTimeoutException gesucht werden.
// Wenn die Ausnahmeprüfung aktiviert ist, nach einer
// SQLTransientConnectionException mit einer verketteten
// ConnectionWaitTimeoutException suchen.
if ( sqlX instanceof ConnectionWaitTimeoutException
|| sqlX instanceof SQLTransientConnectionException
&& sqlX.getCause() instanceof ConnectionWaitTimeoutException)
{
// Diese Ausnahme wird ausgelöst, wenn eine Verbindung nicht
// innerhalb eines konfigurierbaren Zeitraum aus einem Pool abgerufen
// werden kann. Ein häufiges Auftreten dieser Ausnahme ist
// ein Hinweis auf einen falsch optimierten Verbindungspool.
System.out.println("Connection Wait Timeout Exception during get connection or
process SQL: " + c.getMessage());
// Im Allgemeinen sollen nach dieser Ausnahme keine Wiederholungen
// durchgeführt werden, daher den Wiederholungszähler auf 0 setzen und
// die Transaktion zurücksetzen.
try
{
ut.setRollbackOnly();
}
catch (SecurityException se) {
//Wird ausgelöst, um anzuzeigen, dass der Thread die Transaktion nicht zurücksetzen darf.
System.out.println("Security Exception setting rollback only!" + se.getMessage());
}
catch (IllegalStateException ise) {
//Wird ausgelöst, wenn der aktuelle Thread keiner Transaktion zugeordnet ist.
System.out.println("Illegal State Exception setting rollback only!" + ise.getMessage());
}
catch (SystemException sye) {
//Wird ausgelöst, wenn der Transaktionsmanager eine unerwartete Fehlerbedingung ermittelt.
System.out.println("System Exception setting rollback only!" + sye.getMessage());
}
retryCount=0;
}
else if (WSCallHelper.getDataStoreHelper(ds).isConnectionError(sqlX))
{
// Diese Ausnahme zeigt an, dass die Verbindung zur Datenbank nicht mehr gültig ist.
// Die Transaktion zurücksetzen, dann mehrmals versuchen, eine gültige Verbindung herzustellen
// und, falls das nicht möglich ist, eine Fehlernachricht anzeigen.
System.out.println("Connection is stale: " + sc.getMessage());
try
{
ut.setRollbackOnly();
}
catch (SecurityException se) {
//Wird ausgelöst, um anzuzeigen, dass der Thread die Transaktion nicht zurücksetzen darf.
System.out.println("Security Exception setting rollback only!" + se.getMessage());
}
catch (IllegalStateException ise) {
//Wird ausgelöst, wenn der aktuelle Thread keiner Transaktion zugeordnet ist.
System.out.println("Illegal State Exception setting rollback only!" + ise.getMessage());
}
catch (SystemException sye) {
//Wird ausgelöst, wenn der Transaktionsmanager eine unerwartete Fehlerbedingung ermittelt.
System.out.println("System Exception setting rollback only!" + sye.getMessage());
}
if (--retryCount == 0)
{
System.out.println("Five stale connection exceptions, displaying error page.");
}
}
else
{
System.out.println("SQL Exception during get connection or process SQL: " + sq.getMessage());
// Im Allgemeinen sollen nach dieser Ausnahme keine Wiederholungen
// durchgeführt werden, daher den Wiederholungszähler auf 0 setzen und
// die Transaktion zurücksetzen.
try
{
ut.setRollbackOnly();
}
catch (SecurityException se) {
//Wird ausgelöst, um anzuzeigen, dass der Thread die Transaktion nicht zurücksetzen darf.
System.out.println("Security Exception setting rollback only!" + se.getMessage());
}
catch (IllegalStateException ise) {
//Wird ausgelöst, wenn der aktuelle Thread keiner Transaktion zugeordnet ist.
System.out.println("Illegal State Exception setting rollback only!" + ise.getMessage());
}
catch (SystemException sye) {
//Wird ausgelöst, wenn der Transaktionsmanager eine unerwartete Fehlerbedingung ermittelt.
System.out.println("System Exception setting rollback only!" + sye.getMessage());
}
retryCount=0;
}
}
catch (NotSupportedException nse) {
//Wird von UserTransaction-Startmethode ausgelöst, wenn der Thread bereits einer
//Transaktion zugeordnet wurde und die Implementierung des Transaktionsmanagers
//keine verschachtelten Transaktionen unterstützt.
System.out.println("NotSupportedException on User Transaction begin: " + nse.getMessage());
}
catch (SystemException se) {
//Wird ausgelöst, wenn der Transaktionsmanager eine unerwartete Fehlerbedingung ermittelt.
System.out.println("SystemException in User Transaction:" + se.getMessage());
}
catch (Exception e)
{
System.out.println("Exception in get connection or process SQL: " + e.getMessage());
// Im Allgemeinen sollen nach dieser Ausnahme keine Wiederholungen
// durchgeführt werden, daher den Wiederholungszähler auf 5 setzen und
// die Transaktion zurücksetzen.
try
{
ut.setRollbackOnly();
}
catch (SecurityException se) {
//Wird ausgelöst, um anzuzeigen, dass der Thread die Transaktion nicht zurücksetzen darf.
System.out.println("Security Exception setting rollback only!" + se.getMessage());
}
catch (IllegalStateException ise) {
//Wird ausgelöst, wenn der aktuelle Thread keiner Transaktion zugeordnet ist.
System.out.println("Illegal State Exception setting rollback only!" + ise.getMessage());
}
catch (SystemException sye) {
//Wird ausgelöst, wenn der Transaktionsmanager eine unerwartete Fehlerbedingung ermittelt.
System.out.println("System Exception setting rollback only!" + sye.getMessage());
}
retryCount=0;
}
finally
{
// Die Verbindung in einer finally-Anweisung immer schließen, um
// in allen Fällen ein ordnungsgemäßes Schließen zu gewährleisten. // Durch das Schließen der Verbindung wird die aktuelle Verbindung
// nicht tatsächlich geschlossen, sondern zur Wiederverwendung in
// Pool zurückgegeben.
if (rs != null)
{
try
{
rs.close();
}
catch (Exception e)
{
System.out.println("Close Resultset Exception: " + e.getMessage());
}
}
if (stmt != null)
{
try
{
stmt.close();
}
catch (Exception e)
{
System.out.println("Close Statement Exception: " +
e.getMessage());
}
}
if (conn != null)
{
try
{
conn.close(); }
catch (Exception e)
{
System.out.println("Close connection exception: " +
e.getMessage());
}
}
try
{
ut.commit();
}
catch (RollbackException re) {
//Wird ausgelöst, um anzuzeigen, dass die Transaktion zurückgesetzt und nicht
//festgeschrieben wurde.
System.out.println("User Transaction Rolled back!" + re.getMessage());
}
catch (SecurityException se) {
//Wird ausgelöst, um anzuzeigen, dass der Thread die Transaktion nicht zurücksetzen darf.
System.out.println("Security Exception thrown on transaction commit: " + se.getMessage());
}
catch (IllegalStateException ise) {
//Wird ausgelöst, wenn der aktuelle Thread keiner Transaktion zugeordnet ist.
System.out.println("Illegal State Exception thrown on transaction commit: " + ise.getMessage());
}
catch (SystemException sye) {
//Wird ausgelöst, wenn der Transaktionsmanager eine unerwartete Fehlerbedingung ermittelt.
System.out.println("System Exception thrown on transaction commit: " + sye.getMessage());
}
catch (Exception e)
{
System.out.println("Exception thrown on transaction commit: " + e.getMessage());
}
}
}
while ( error==true && retryCount > 0 );
// HTML-Antwort vorbereiten und zurückgeben, das Zwischenspeichern
// von dynamischem Inhalt auf Browsern verhindern.
res.setContentType("text/html");
res.setHeader("Pragma", "no-cache");
res.setHeader("Cache-Control", "no-cache");
res.setDateHeader("Expires", 0);
try
{
ServletOutputStream out = res.getOutputStream();
out.println("<HTML>");
out.println("<HEAD><TITLE>" + title + "</TITLE></HEAD>");
out.println("<BODY>");
if (error==true)
{
out.println("<H1>There was an error processing this request.</H1>" +
"Please try the request again, or contact " +
"the <a href='mailto:sysadmin@my.com'>System Administrator</a>");
}
else if (employeeList.isEmpty())
{
out.println("<H1>Employee List is Empty</H1>");
}
else
{
out.println("<H1>Employee List </H1>");
for (int i = 0; i < employeeList.size(); i++)
{
out.println(employeeList.elementAt(i) + "<BR>");
}
}
out.println("</BODY></HTML>");
out.close();
}
catch (IOException e)
{
System.out.println("HTML response exception: " + e.getMessage());
}
}
}
Beispiel: Behandlung von Verbindungsausnahmen für Session-Beans in containergesteuerten Datenbanktransaktionen
Das folgende Codebeispiel zeigt, wie im Fall von Ausnahmen wegen veralteter Verbindungen Transaktionen rückgängig gemacht und Ausnahmen an den Bean-Client ausgegeben werden.
//===================START_PROLOG======================================
//
// 5630-A23, 5630-A22,
// (C) COPYRIGHT International Business Machines Corp. 2002,2008
// All Rights Reserved
// Licensed Materials - Property of IBM
// US Government Users Restricted Rights - Use, duplication or
// disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
//
// IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
// ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR
// CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
// USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
// OR PERFORMANCE OF THIS SOFTWARE.
//
//===================END_PROLOG========================================
package WebSphereSamples.ConnPool;
import java.util.*;
import java.sql.*;
import javax.sql.*;
import javax.ejb.*;
import javax.naming.*;
import com.ibm.websphere.ce.cm.ConnectionWaitTimeoutException;
import com.ibm.websphere.rsadapter.WSCallHelper;
/*************************************************************************************
* Diese Bean wurde konzipiert, um Datenbankverbindungen in einer containergesteuerten *
* Transaktions-Session-Bean zu veranschaulichen. Das Transaktionsattribut der Bean *
* muss auf TX_REQUIRED oder TX_REQUIRES_NEW gesetzt werden. *
**************************************************************************************
*/
public class ShowEmployeesCMTBean implements SessionBean {
private javax.ejb.SessionContext mySessionCtx = null;
final static long serialVersionUID = 3206093459760846163L;
private javax.sql.DataSource ds;
//************************************************************************************
//* ejbActivate ruft die Methode getDS auf, die den JNDI-Lookup für die DataSource durchführt.
//* Da der Lookup für die DataSource sich in einer separaten Methode befindet, kann er
//* auch über die Methode getEmployees aufgerufen werden, wenn das DataSource-Feld leer ist.
//************************************************************************************
public void ejbActivate() throws java.rmi.EJBException {
getDS();
}
/**
* Methode ejbCreate
* @exception javax.ejb.CreateException
* @exception java.rmi.EJBException
*/
public void ejbCreate() throws javax.ejb.CreateException, java.rmi.EJBException {}
/**
* Methode ejbPassivate
* @exception java.rmi.EJBException
*/
public void ejbPassivate() throws java.rmi.EJBException {}
/**
* ejbRemove method
* @exception java.rmi.EJBException
*/
public void ejbRemove() throws java.rmi.EJBException {}
//************************************************************************************
//* Die Methode getEmployees führt die Datenbankabfrage durch und ruft die Angestelltendaten ab. //* Die Methode getDS wird nur aufgerufen, wenn keine DataSource-Variable angegeben ist. //* Da diese Session-Bean containergesteuerte Transaktion verwendet, kann sie die Transaktion
//* nicht nach einer StaleConnectionException ausführen. Sie kann jedoch eine Ausnahme
//* für ihren Client auslösen, die angibt, dass die Operation wiederholt werden kann.
//************************************************************************************
public Vector getEmployees() throws ConnectionWaitTimeoutException, SQLException,
RetryableConnectionException
{
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
Vector employeeList = new Vector();
if (ds == null) getDS();
try
{
// Verbindungsobjekt conn wird mit der DataSource-Factory abrufen.
conn = ds.getConnection();
// DB-Abfrage mit JDBC-Standardcodierung durchführen.
stmt = conn.createStatement();
String query = "Select FirstNme, MidInit, LastName " +
"from Employee ORDER BY LastName;"
rs = stmt.executeQuery(query);
while (rs.next())
{
employeeList.addElement(rs.getString(3) + ", "+ rs.getString(1)" + " + rs.getString(2));
}
}
catch (SQLException sqlX)
{
// Feststellen, ob die Verbindung veraltet ist.
if (WSCallHelper.getDataStoreHelper(ds).isConnectionError(sqlX))
{
// Diese Ausnahme zeigt an, dass die Verbindung zur Datenbank nicht mehr gültig ist.
// Die Transaktion zurücksetzen und eine Ausnahme an den Client absetzen, die anzeigt,
// dass die Transaktion gegebenenfalls wiederholt werden kann.
System.out.println("Connection is stale: " + sqlX.getMessage());
System.out.println("Rolling back transaction and throwing RetryableConnectionException");
mySessionCtx.setRollbackOnly();
throw new RetryableConnectionException(sqlX.toString());
}
// Feststellen, ob das zulässige Zeitlimit für Verbindungsanforderungen
// überschritten ist.
else if ( sqlX instanceof ConnectionWaitTimeoutException
|| sqlX instanceof SQLTransientConnectionException
&& sqlX.getCause() instanceof ConnectionWaitTimeoutException)
{
// Diese Ausnahme wird ausgelöst, wenn eine Verbindung nicht
// innerhalb eines konfigurierbaren Zeitraum aus einem Pool abgerufen
// werden kann. Ein häufiges Auftreten dieser Ausnahme ist
// ein Hinweis auf einen falsch optimierten Verbindungspool.
System.out.println("Connection Wait Timeout Exception during get connection or process SQL: " +
sqlX.getMessage());
throw sqlX instanceof ConnectionWaitTimeoutException ?
sqlX :
(ConnectionWaitTimeoutException) sqlX.getCause();
}
else
{
//Durch das Auslösen einer fernen Ausnahme wird die containergesteuerte
//Transaktion automatisch zurückgesetzt
System.out.println("SQL Exception during get connection or process SQL: " +
sqlX.getMessage());
throw sqlX;
}
}
finally
{
// Die Verbindung in einer finally-Anweisung immer schließen, um
// in allen Fällen ein ordnungsgemäßes Schließen zu gewährleisten. // Durch das Schließen der Verbindung wird die aktuelle Verbindung
// nicht tatsächlich geschlossen, sondern zur Wiederverwendung in
// Pool zurückgegeben.
if (rs != null)
{
try
{
rs.close();
}
catch (Exception e)
{
System.out.println("Close Resultset Exception: " +
e.getMessage());
}
}
if (stmt != null)
{
try
{
stmt.close();
}
catch (Exception e)
{
System.out.println("Close Statement Exception: " +
e.getMessage());
}
}
if (conn != null)
{
try
{
conn.close(); }
catch (Exception e)
{
System.out.println("Close connection exception: " +
e.getMessage());
}
}
}
return employeeList;
}
/**
* Methode getSessionContext
* @return javax.ejb.SessionContext
*/
public javax.ejb.SessionContext getSessionContext() {
return mySessionCtx;
}
//************************************************************************************
//* Die Methode "getDS" für die JNDI-Lookup-Operation für die Datenquelle aus.
//* Diese Methode wird über ejbActivate und getEmployees aufgerufen, wenn *
//* kein DataSource-Objekt angegeben ist. *//************************************************************************************
private void getDS() {
try {
Hashtable parms = new Hashtable();
parms.put(Context.INITIAL_CONTEXT_FACTORY,
com.ibm.websphere.naming.WsnInitialContextFactory);
InitialContext ctx = new InitialContext(parms);
// Namensservice-Lookup zum Abrufen des DataSource-Objekts durchführen.
ds = (DataSource)ctx.lookup("java:comp/env/jdbc/SampleDB");
}
catch (Exception e) {
System.out.println("Naming service exception: " + e.getMessage());
e.printStackTrace();
}
}
/**
* Methode setSessionContext
* @param ctx javax.ejb.SessionContext
* @exception java.rmi.EJBException
*/
public void setSessionContext(javax.ejb.SessionContext ctx) throws java.rmi.EJBException {
mySessionCtx = ctx;
}
}
//===================START_PROLOG======================================
//
// 5630-A23, 5630-A22,
// (C) COPYRIGHT International Business Machines Corp. 2002,2008
// All Rights Reserved
// Licensed Materials - Property of IBM
// US Government Users Restricted Rights - Use, duplication or
// disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
//
// IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
// ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR
// CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
// USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
// OR PERFORMANCE OF THIS SOFTWARE.
//
//===================END_PROLOG========================================
package WebSphereSamples.ConnPool;
/**
* Dies ist eine Home-Schnittstelle für die Session-Bean
*/
public interface ShowEmployeesCMTHome extends javax.ejb.EJBHome {
/**
* Methode create für eine Session-Bean
* @return WebSphereSamples.ConnPool.ShowEmployeesCMT
* @exception javax.ejb.CreateException
* @exception java.rmi.RemoteException
*/
WebSphereSamples.ConnPool.ShowEmployeesCMT create() throws javax.ejb.CreateException,
java.rmi.RemoteException;
}
//===================START_PROLOG======================================
//
// 5630-A23, 5630-A22,
// (C) COPYRIGHT International Business Machines Corp. 2002,2008
// All Rights Reserved
// Licensed Materials - Property of IBM
// US Government Users Restricted Rights - Use, duplication or
// disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
//
// IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
// ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR
// CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
// USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
// OR PERFORMANCE OF THIS SOFTWARE.
//
//===================END_PROLOG========================================
package WebSphereSamples.ConnPool;
/**
* Dies ist ein ferne EJB-Schnittstelle
*/
public interface ShowEmployeesCMT extends javax.ejb.EJBObject {
/**
*
* @return java.util.Vector
*/
java.util.Vector getEmployees() throws java.sql.SQLException, java.rmi.RemoteException,
ConnectionWaitTimeoutException, WebSphereSamples.ConnPool.RetryableConnectionException;
}
//===================START_PROLOG======================================
//
// 5630-A23, 5630-A22,
// (C) COPYRIGHT International Business Machines Corp. 2002,2008
// All Rights Reserved
// Licensed Materials - Property of IBM
// US Government Users Restricted Rights - Use, duplication or
// disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
//
// IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
// ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR
// CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
// USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
// OR PERFORMANCE OF THIS SOFTWARE.
//
//===================END_PROLOG========================================
package WebSphereSamples.ConnPool;
/**
* Ausnahme, die anzeigt, dass die Operation wiederholt werden kann
* Build-Datum: (02.04.2001 10:48:08)
* @author: Administrator
*/
public class RetryableConnectionException extends Exception {
/**
* Konstruktor RetryableConnectionException.
*/
public RetryableConnectionException() {
super();
}
/**
* Konstruktor RetryableConnectionException.
* @param s java.lang.String
*/
public RetryableConnectionException(String s) {
super(s);
}
}
Beispiel: Behandlung von Verbindungsausnahmen für Session-Beans in Bean-gesteuerten Datenbanktransaktionen
Das folgende Codebeispiel zeigt Optionen zur Behandlung von Ausnahmen wegen veralteter Verbindungen. Sie können verschiedene Parameter für die Transaktionsverwaltung und Verbindungsverwaltung festlegen, z. B. die Anzahl der Operationswiederholungen und das Zeitlimit für Verbindungen.
//===================START_PROLOG======================================
//
// 5630-A23, 5630-A22,
// (C) COPYRIGHT International Business Machines Corp. 2002,2008
// All Rights Reserved
// Licensed Materials - Property of IBM
// US Government Users Restricted Rights - Use, duplication or
// disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
//
// IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
// ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR
// CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
// USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
// OR PERFORMANCE OF THIS SOFTWARE.
//
//===================END_PROLOG========================================
package WebSphereSamples.ConnPool;
import java.util.*;
import java.sql.*;
import javax.sql.*;
import javax.ejb.*;
import javax.naming.*;
import javax.transaction.*;
import com.ibm.websphere.ce.cm.ConnectionWaitTimeoutException;
import com.ibm.websphere.rsadapter.WSCallHelper;
/**********************************************************************************
* Diese Bean wurde konzipiert, um Datenbankverbindungen in einer Bean-gesteuerten
* Transaktions-Session-Bean zu veranschaulichen. Das Transaktionsattribut der Bean *
* muss auf TX_BEANMANAGED gesetzt werden. **********************************************************************************/
public class ShowEmployeesBMTBean implements SessionBean {
private javax.ejb.SessionContext mySessionCtx = null;
final static long serialVersionUID = 3206093459760846163L;
private javax.sql.DataSource ds;
private javax.transaction.UserTransaction userTran;
//************************************************************************************
//* ejbActivate ruft die Methode getDS auf, die den JNDI-Lookup für die DataSource durchführt.
//* Da der Lookup für die DataSource sich in einer separaten Methode befindet, kann er
//* auch über die Methode getEmployees aufgerufen werden, wenn das DataSource-Feld leer ist.
//************************************************************************************
public void ejbActivate() throws java.rmi.EJBException {
getDS();
}
/**
* Methode ejbCreate
* @exception javax.ejb.CreateException
* @exception java.rmi.EJBException
*/
public void ejbCreate() throws javax.ejb.CreateException, java.rmi.EJBException {}
/**
* Methode ejbPassivate
* @exception java.rmi.EJBException
*/
public void ejbPassivate() throws java.rmi.EJBException {}
/**
* ejbRemove method
* @exception java.rmi.EJBException
*/
public void ejbRemove() throws java.rmi.EJBException {}
//************************************************************************************
//* Die Methode getEmployees führt die Datenbankabfrage durch und ruft die Angestelltendaten ab. //* Die Methode getDS wird nur aufgerufen, wenn keine DataSource- bzw. userTran-Variable angegeben ist.
//* Wenn eine veraltete Verbindung gefunden wird, versucht die Bean, die Transaktion fünf Mal zu
//* wiederholen, und löst dann eine Ausnahme vom Typ "EJBException" aus.
//************************************************************************************
public Vector getEmployees() throws EJBException {
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
Vector employeeList = new Vector();
// retryCount auf die gewünschte Anzahl der Wiederholungen nach
// Erkennung einer veralteten Verbindung setzen
int retryCount = 5;
// Wenn der Datenbankcode erfolgreich ausgeführt wird, wird error = false eingestellt.
boolean error = true;
if (ds == null || userTran == null) getDS();
do
{
try
{
//try/catch-Block für UserTransaction-Vorgänge
//Die Transaktion beginnen
userTran.begin ();
try
{
//try/catch-Block für Datenbankoperation
// Verbindungsobjekt conn wird mit der DataSource-Factory abrufen.
conn = ds.getConnection();
// DB-Abfrage mit JDBC-Standardcodierung durchführen.
stmt = conn.createStatement();
String query = "Select FirstNme, MidInit, LastName " +
"from Employee ORDER BY LastName";
rs = stmt.executeQuery(query);
while (rs.next())
{
employeeList.addElement(rs.getString(3) + ", " + rs.getString(1) + " " + rs.getString(2));
}
//Da alle Datenbankoperationen erfolgreich ausgeführt werden, error = false setzen.
error = false;
}
catch (SQLException sqlX)
{
if (WSCallHelper.getDataStoreHelper(ds).isConnectionError(sqlX))
{
// Diese Ausnahme zeigt an, dass die Verbindung zur Datenbank nicht mehr gültig ist.
// Die Transaktion zurücksetzen und eine Ausnahme an den Client absetzen, die anzeigt,
// dass die Transaktion gegebenenfalls wiederholt werden kann.
System.out.println("Stale connection: " +
se.getMessage());
userTran.rollback();
if (--retryCount == 0)
{
//Die Transaktion wurde bereits so häufig wie angefordert wiederholt, eine EJBException auslösen.
throw new EJBException("Transaction Failure: " + sqlX.toString());
}
else
{
System.out.println("Retrying transaction, retryCount = " +
retryCount);
}
}
else if (sqlX instanceof ConnectionWaitTimeoutException
|| sqlX instanceof SQLTransientConnectionException
&& sqlX.getCause() instanceof ConnectionWaitTimeoutException)
{
// Diese Ausnahme wird ausgelöst, wenn eine Verbindung nicht
// innerhalb eines konfigurierbaren Zeitraum aus einem Pool abgerufen
// werden kann. Ein häufiges Auftreten dieser Ausnahme ist
// ein Hinweis auf einen falsch optimierten Verbindungspool.
System.out.println("Connection request timed out: " +
sqlX.getMessage());
userTran.rollback();
throw new EJBException("Transaction failure: " + sqlX.getMessage());
}
else
{
// catch bearbeitet alle anderen SQL-Ausnahmen
System.out.println("SQL Exception during get connection or process SQL: " +
sqlX.getMessage());
userTran.rollback();
throw new EJBException("Transaction failure: " + sqlX.getMessage());
}
finally
{
// Die Verbindung in einer finally-Anweisung immer schließen, um
// in allen Fällen ein ordnungsgemäßes Schließen zu gewährleisten. // Durch das Schließen der Verbindung wird die aktuelle Verbindung
// nicht tatsächlich geschlossen, sondern zur Wiederverwendung in
// Pool zurückgegeben.
if (rs != null) {
try {
rs.close();
}
catch (Exception e) {
System.out.println("Close Resultset Exception: " + e.getMessage());
}
}
if (stmt != null) {
try {
stmt.close();
}
catch (Exception e) {
System.out.println("Close Statement Exception: " +
e.getMessage());
}
}
if (conn != null) {
try {
conn.close(); }
catch (Exception e) {
System.out.println("Close connection exception: " +
e.getMessage());
}
}
}
if (!error) {
//Datenbankvorgänge erfolgreich abgeschlossen, die Transaktion festschreiben
userTran.commit ();
}
//Ausnahmen für UserTransaction abfangen
}
catch (NotSupportedException nse) {
//Wird von UserTransaction-Startmethode ausgelöst, wenn der Thread bereits einer
//Transaktion zugeordnet wurde und die Implementierung des Transaktionsmanagers
//keine verschachtelten Transaktionen unterstützt.
System.out.println("NotSupportedException on User Transaction begin: " +
nse.getMessage());
throw new EJBException("Transaction failure: " + nse.getMessage());
}
catch (RollbackException re) {
//Wird ausgelöst, um anzuzeigen, dass die Transaktion zurückgesetzt und nicht
//festgeschrieben wurde.
System.out.println("User Transaction Rolled back!" + re.getMessage());
throw new EJBException("Transaction failure: " + re.getMessage());
}
catch (SystemException se) {
//Wird ausgelöst, wenn der Transaktionsmanager eine unerwartete Fehlerbedingung ermittelt.
System.out.println("SystemException in User Transaction:" + se.getMessage());
throw new EJBException("Transaction failure: " + se.getMessage());
}
catch (Exception e) {
//Alle generischen oder unerwarteten Ausnahmen bearbeiten
System.out.println("Exception in User Transaction: " + e.getMessage());
throw new EJBException("Transaction failure: " + e.getMessage());
}
}
while (error);
return employeeList;
}
/**
* Kommentar zur Methode getSessionContext
* @return javax.ejb.SessionContext
*/
public javax.ejb.SessionContext getSessionContext() {
return mySessionCtx;
}
//************************************************************************************
//* Die Methode getDS führt den JNDI-Lookup für die DataSource durch. *
//* Diese Methode wird über ejbActivate und getEmployees aufgerufen, wenn *
//* kein DataSource-Objekt angegeben ist.
//************************************************************************************
private void getDS() {
try {
Hashtable parms = new Hashtable();
parms.put(Context.INITIAL_CONTEXT_FACTORY,
com.ibm.websphere.naming.WsnInitialContextFactory);
InitialContext ctx = new InitialContext(parms);
// Namensservice-Lookup zum Abrufen des DataSource-Objekts durchführen.
ds = (DataSource)ctx.lookup("java:comp/env/jdbc/SampleDB");
//UserTransaction-Objekt erstellen
userTran = mySessionCtx.getUserTransaction();
}
catch (Exception e) {
System.out.println("Naming service exception: " + e.getMessage());
e.printStackTrace();
}
}
/**
* Methode setSessionContext
* @param ctx javax.ejb.SessionContext
* @exception java.rmi.EJBException
*/
public void setSessionContext(javax.ejb.SessionContext ctx) throws java.rmi.EJBException {
mySessionCtx = ctx;
}
}
//===================START_PROLOG======================================
//
// 5630-A23, 5630-A22,
// (C) COPYRIGHT International Business Machines Corp. 2002,2008
// All Rights Reserved
// Licensed Materials - Property of IBM
// US Government Users Restricted Rights - Use, duplication or
// disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
//
// IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
// ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR
// CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
// USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
// OR PERFORMANCE OF THIS SOFTWARE.
//
//===================END_PROLOG========================================
package WebSphereSamples.ConnPool;
/**
* Dies ist eine Home-Schnittstelle für die Session-Bean
*/
public interface ShowEmployeesBMTHome extends javax.ejb.EJBHome {
/**
* Methode create für eine Session-Bean
* @return WebSphereSamples.ConnPool.ShowEmployeesBMT
* @exception javax.ejb.CreateException
* @exception java.rmi.RemoteException
*/
WebSphereSamples.ConnPool.ShowEmployeesBMT create() throws javax.ejb.CreateException,
java.rmi.RemoteException;
}
//===================START_PROLOG======================================
//
// 5630-A23, 5630-A22,
// (C) COPYRIGHT International Business Machines Corp. 2002,2008
// All Rights Reserved
// Licensed Materials - Property of IBM
// US Government Users Restricted Rights - Use, duplication or
// disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
//
// IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
// ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR
// CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
// USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
// OR PERFORMANCE OF THIS SOFTWARE.
//
//===================END_PROLOG========================================
package WebSphereSamples.ConnPool;
/**
* Dies ist ein ferne EJB-Schnittstelle
*/
public interface ShowEmployeesBMT extends javax.ejb.EJBObject {
/**
*
* @return java.util.Vector
*/
java.util.Vector getEmployees() throws java.rmi.RemoteException, javax.ejb.EJBException;
}
Beispiel: Behandlung von Verbindungsausnahmen für BMP-Beans in containergesteuerten Datenbanktransaktionen
Das folgende Codebeispiel zeigt, wie im Fall von Ausnahmen wegen veralteter Verbindungen Transaktionen rückgängig gemacht und Ausnahmen an den Bean-Client ausgegeben werden.
//===================START_PROLOG======================================
//
// 5630-A23, 5630-A22,
// (C) COPYRIGHT International Business Machines Corp. 2005,2008
// All Rights Reserved
// Licensed Materials - Property of IBM
// US Government Users Restricted Rights - Use, duplication or
// disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
//
// IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
// ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR
// CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
// USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
// OR PERFORMANCE OF THIS SOFTWARE.
//
//===================END_PROLOG========================================
package WebSphereSamples.ConnPool;
import java.util.*;
import javax.ejb.*;
import java.sql.*;
import javax.sql.*;
import javax.ejb.*;
import javax.naming.*;
import com.ibm.websphere.rsadapter.WSCallHelper;
/**
* Dies ist eine Entity-Bean-Klasse mit BMP-Feldern
* String firstName, String lastName, String middleInit
* String empNo, int edLevel
*/
public class EmployeeBMPBean implements EntityBean {
private javax.ejb.EntityContext entityContext = null;
final static long serialVersionUID = 3206093459760846163L;
private java.lang.String firstName;
private java.lang.String lastName;
private String middleInit;
private javax.sql.DataSource ds;
private java.lang.String empNo;
private int edLevel;
/**
* Methode ejbActivate
* ejbActivate ruft die Methode getDS() auf, die das
* JNDI-Lookup für die Datenquelle durchführt.
*/
public void ejbActivate() {
getDS();
}
/**
* Methode ejbCreate für eine BMP-Entity-Bean
* @return WebSphereSamples.ConnPool.EmployeeBMPKey
* @param key WebSphereSamples.ConnPool.EmployeeBMPKey
* @exception javax.ejb.CreateException
*/
public WebSphereSamples.ConnPool.EmployeeBMPKey ejbCreate(String empNo,
String firstName, String lastName, String middleInit, int edLevel) throws
javax.ejb.CreateException {
Connection conn = null;
PreparedStatement ps = null;
if (ds == null) getDS();
this.empNo = empNo;
this.firstName = firstName;
this.lastName = lastName;
this.middleInit = middleInit;
this.edLevel = edLevel;
String sql = "insert into Employee (empNo, firstnme, midinit, lastname, edlevel) values (?,?,?,?,?)";
try {
conn = ds.getConnection();
ps = conn.prepareStatement(sql);
ps.setString(1, empNo);
ps.setString(2, firstName);
ps.setString(3, middleInit);
ps.setString(4, lastName);
ps.setInt(5, edLevel);
if (ps.executeUpdate() != 1) {
System.out.println("ejbCreate Failed to add user.");
throw new CreateException("Failed to add user.");
}
}
catch (SQLException se)
{
if (WSCallHelper.getDataStoreHelper(ds).isConnectionError(se))
{
// Diese Ausnahme zeigt an, dass die Verbindung zur Datenbank nicht mehr gültig ist.
// Die Transaktion zurücksetzen und eine Ausnahme an den Client absetzen, die anzeigt,
// dass die Transaktion gegebenenfalls wiederholt werden kann.
System.out.println("Connection is stale: " + se.getMessage());
throw new CreateException(se.getMessage());
}
else
{
System.out.println("SQL Exception during get connection or process SQL: " +
se.getMessage());
throw new CreateException(se.getMessage());
}
}
finally
{
// Die Verbindung in einer finally-Anweisung immer schließen, um
// in allen Fällen ein ordnungsgemäßes Schließen zu gewährleisten.
// Durch das Schließen der Verbindung wird die aktuelle Verbindung
// nicht tatsächlich geschlossen, sondern zur Wiederverwendung in
// Pool zurückgegeben.
if (ps != null)
{
try
{
ps.close();
}
catch (Exception e)
{
System.out.println("Close Statement Exception: " +
e.getMessage());
}
}
if (conn != null)
{
try
{
conn.close(); }
catch (Exception e)
{
System.out.println("Close connection exception: " +
e.getMessage());
}
}
}
return new EmployeeBMPKey(this.empNo);
}
/**
* Methode ejbFindByPrimaryKey
* @return WebSphereSamples.ConnPool.EmployeeBMPKey
* @param primaryKey WebSphereSamples.ConnPool.EmployeeBMPKey
* @exception javax.ejb.FinderException
*/
public WebSphereSamples.ConnPool.EmployeeBMPKey ejbFindByPrimaryKey(WebSphereSamples.ConnPool.EmployeeBMPKey primaryKey) javax.ejb.FinderException {
loadByEmpNo(primaryKey.empNo);
return primaryKey;
}
/**
* Methode ejbLoad
*/
public void ejbLoad() {
try {
EmployeeBMPKey pk = (EmployeeBMPKey) entityContext.getPrimaryKey();
loadByEmpNo(pk.empNo);
} catch (FinderException fe) {
throw new EJBException("Cannot load Employee state from database.");
}
}
/**
* Methode ejbPassivate
*/
public void ejbPassivate() {}
/**
* Methode ejbPostCreate für eine BMP-Entity-Bean
* @param key WebSphereSamples.ConnPool.EmployeeBMPKey
*/
public void ejbPostCreate(String empNo, String firstName, String lastName, String middleInit,
int edLevel) {}
/**
* ejbRemove method
* @exception javax.ejb.RemoveException
*/
public void ejbRemove() throws javax.ejb.RemoveException
{
if (ds == null)
GetDS();
String sql = "delete from Employee where empNo=?";
Connection con = null;
PreparedStatement ps = null;
try
{
con = ds.getConnection();
ps = con.prepareStatement(sql);
ps.setString(1, empNo);
if (ps.executeUpdate() != 1) {
throw new EJBException("Cannot remove employee: " + empNo);
}
}
catch (SQLException se)
{
if (WSCallHelper.getDataStoreHelper(ds).isConnectionError(se))
{
// Diese Ausnahme zeigt an, dass die Verbindung zur Datenbank nicht mehr gültig ist.
// Die Transaktion zurücksetzen und eine Ausnahme an den Client absetzen, die anzeigt,
// dass die Transaktion gegebenenfalls wiederholt werden kann.
System.out.println("Connection is stale: " + se.getMessage());
throw new EJBException(se.getMessage());
}
else
{
System.out.println("SQL Exception during get connection or process SQL: " +
se.getMessage());
throw new EJBException(se.getMessage());
}
}
finally
{
// Die Verbindung in einer finally-Anweisung immer schließen, um
// in allen Fällen ein ordnungsgemäßes Schließen zu gewährleisten.
// Durch das Schließen der Verbindung wird die aktuelle Verbindung
// nicht tatsächlich geschlossen, sondern zur Wiederverwendung in
// Pool zurückgegeben.
if (ps != null)
{
try
{
ps.close();
}
catch (Exception e)
{
System.out.println("Close Statement Exception: " +
e.getMessage());
}
}
if (con != null)
{
try
{
con.close();
}
catch (Exception e)
{
System.out.println("Close connection exception: " +
e.getMessage());
}
}
}
}
/**
* edLevel des Angestellten abrufen
* Build-Datum: (20.04.2001 15:46:22)
* @return int
*/
public int getEdLevel() {
return edLevel;
}
/**
* Methode getEntityContext
* @return javax.ejb.EntityContext
*/
public javax.ejb.EntityContext getEntityContext() {
return entityContext;
}
/**
* Vornamen des Angestellten abrufen
* Build-Datum: (19.04.2001 13:34:47)
* @return java.lang.String
*/
public java.lang.String getFirstName() {
return firstName;
}
/**
* Familiennamen des Angestellten abrufen
* Build-Datum: (19.04.2001 13:35:41)
* @return java.lang.String
*/
public java.lang.String getLastName() {
return lastName;
}
/**
* Zweiten Vornamen des Angestellten abrufen
* Build-Datum: (19.04.2001 13:36:15)
* @return char
*/
public String getMiddleInit() {
return middleInit;
}
/**
* JNDI-Lookup für DataSource durchführen
* Build-Datum: (19.04.2001 15:28:15)
*/
private void getDS() {
try {
Hashtable parms = new Hashtable();
parms.put(Context.INITIAL_CONTEXT_FACTORY,
com.ibm.websphere.naming.WsnInitialContextFactory);
InitialContext ctx = new InitialContext(parms);
// Namensservice-Lookup zum Abrufen des DataSource-Objekts durchführen.
ds = (DataSource)ctx.lookup("java:comp/env/jdbc/SampleDB");
}
catch (Exception e) {
System.out.println("Naming service exception: " + e.getMessage());
e.printStackTrace();
}
}
/**
* Daten zum Angestellten aus der Datenbank laden
* Build-Datum: (19.04.2001 15:44:07)
* @param empNo java.lang.String
*/
private void loadByEmpNo(String empNoKey) throws javax.ejb.FinderException{
String sql = "select empno, firstnme, midinit, lastname, edLevel from employee where empno = ?";
Connection conn = null;
PreparedStatement ps = null;
ResultSet rs = null;
if (ds == null) getDS();
try
{
// Verbindungsobjekt conn wird mit der DataSource-Factory abrufen.
conn = ds.getConnection();
// DB-Abfrage mit JDBC-Standardcodierung durchführen.
ps = conn.prepareStatement(sql);
ps.setString(1, empNoKey);
rs = ps.executeQuery();
if (rs.next())
{
empNo= rs.getString(1);
firstName=rs.getString(2);
middleInit=rs.getString(3);
lastName=rs.getString(4);
edLevel=rs.getInt(5);
}
else
{
throw new ObjectNotFoundException("Cannot find employee number " +
empNoKey);
}
}
catch (SQLException se)
{
if (WSCallHelper.getDataStoreHelper(ds).isConnectionError(se))
{
// Diese Ausnahme zeigt an, dass die Verbindung zur Datenbank nicht mehr gültig ist.
// Die Transaktion zurücksetzen und eine Ausnahme an den Client absetzen, die anzeigt,
// dass die Transaktion gegebenenfalls wiederholt werden kann.
System.out.println("Connection is stale: " + se.getMessage());
throw new FinderException(se.getMessage());
}
else
{
System.out.println("SQL Exception during get connection or process SQL: " +
se.getMessage());
throw new FinderException(se.getMessage());
}
}
finally
{
// Die Verbindung immer in einer finally-Anweisung schließen, um
// sicherzustellen, dass sie in allen Fällen ordnungsgemäß
// geschlossen wird. Durch das Schließen der Verbindung wird die
// Verbindung nicht tatsächlich geschlossen, sondern zur
// Wiederverwendung an den Pool zurückgegeben.
if (rs != null)
{
try
{
rs.close();
}
catch (Exception e)
{
System.out.println("Close Resultset Exception: " + e.getMessage());
}
}
if (ps != null)
{
try
{
ps.close();
}
catch (Exception e)
{
System.out.println("Close Statement Exception: " +
e.getMessage());
}
}
if (conn != null)
{
try
{
conn.close(); }
catch (Exception e)
{
System.out.println("Close connection exception: " +
e.getMessage());
}
}
}
}
/**
* Schulabschluss des Angestellten angeben
* Build-Datum: (20.04.2001 15:46:22)
* @param newEdLevel int
*/
public void setEdLevel(int newEdLevel) {
edLevel = newEdLevel;
}
/**
* Methode setEntityContext
* @param ctx javax.ejb.EntityContext
*/
public void setEntityContext(javax.ejb.EntityContext ctx) {
entityContext = ctx;
}
/**
* Vornamen des Angestellten angeben
* Build-Datum: (19.04.2001 13:34:47)
* @param newFirstName java.lang.String
*/
public void setFirstName(java.lang.String newFirstName) {
firstName = newFirstName;
}
/**
* Familiennamen des Angestellten angeben
* Build-Datum: (19.04.2001 13:35:41)
* @param newLastName java.lang.String
*/
public void setLastName(java.lang.String newLastName) {
lastName = newLastName;
}
/**
* Zweiten Vornamen des Angestellten angeben
* Build-Datum: (19.04.2001 13:36:15)
* @param newMiddleInit char
*/
public void setMiddleInit(String newMiddleInit) {
middleInit = newMiddleInit;
}
/**
* Methode unsetEntityContext
*/
public void unsetEntityContext() {
entityContext = null;
}
}
//===================START_PROLOG======================================
//
// 5630-A23, 5630-A22,
// (C) COPYRIGHT International Business Machines Corp. 2002,2008
// All Rights Reserved
// Licensed Materials - Property of IBM
// US Government Users Restricted Rights - Use, duplication or
// disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
//
// IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
// ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR
// CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
// USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
// OR PERFORMANCE OF THIS SOFTWARE.
//
//===================END_PROLOG========================================
package WebSphereSamples.ConnPool;
/**
* Dies ist ein ferne EJB-Schnittstelle
*/
public interface EmployeeBMP extends javax.ejb.EJBObject {
/**
*
* @return int
*/
int getEdLevel() throws java.rmi.RemoteException;
/**
*
* @return java.lang.String
*/
java.lang.String getFirstName() throws java.rmi.RemoteException;
/**
*
* @return java.lang.String
*/
java.lang.String getLastName() throws java.rmi.RemoteException;
/**
*
* @return java.lang.String
*/
java.lang.String getMiddleInit() throws java.rmi.RemoteException;
/**
*
* @return void
* @param newEdLevel int
*/
void setEdLevel(int newEdLevel) throws java.rmi.RemoteException;
/**
*
* @return void
* @param newFirstName java.lang.String
*/
void setFirstName(java.lang.String newFirstName) throws java.rmi.RemoteException;
/**
*
* @return void
* @param newLastName java.lang.String
*/
void setLastName(java.lang.String newLastName) throws java.rmi.RemoteException;
/**
*
* @return void
* @param newMiddleInit java.lang.String
*/
void setMiddleInit(java.lang.String newMiddleInit) throws java.rmi.RemoteException;
}
//===================START_PROLOG======================================
//
// 5630-A23, 5630-A22,
// (C) COPYRIGHT International Business Machines Corp. 2002,2008
// All Rights Reserved
// Licensed Materials - Property of IBM
// US Government Users Restricted Rights - Use, duplication or
// disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
//
// IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
// ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR
// CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
// USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
// OR PERFORMANCE OF THIS SOFTWARE.
//
//===================END_PROLOG========================================
package WebSphereSamples.ConnPool;
/**
* Dies ist ein ferne EJB-Schnittstelle
*/
public interface EmployeeBMP extends javax.ejb.EJBObject {
/**
*
* @return int
*/
int getEdLevel() throws java.rmi.RemoteException;
/**
*
* @return java.lang.String
*/
java.lang.String getFirstName() throws java.rmi.RemoteException;
/**
*
* @return java.lang.String
*/
java.lang.String getLastName() throws java.rmi.RemoteException;
/**
*
* @return java.lang.String
*/
java.lang.String getMiddleInit() throws java.rmi.RemoteException;
/**
*
* @return void
* @param newEdLevel int
*/
void setEdLevel(int newEdLevel) throws java.rmi.RemoteException;
/**
*
* @return void
* @param newFirstName java.lang.String
*/
void setFirstName(java.lang.String newFirstName) throws java.rmi.RemoteException;
/**
*
* @return void
* @param newLastName java.lang.String
*/
void setLastName(java.lang.String newLastName) throws java.rmi.RemoteException;
/**
*
* @return void
* @param newMiddleInit java.lang.String
*/
void setMiddleInit(java.lang.String newMiddleInit) throws java.rmi.RemoteException;
}
//===================START_PROLOG======================================
//
// 5630-A23, 5630-A22,
// (C) COPYRIGHT International Business Machines Corp. 2002,2008
// All Rights Reserved
// Licensed Materials - Property of IBM
// US Government Users Restricted Rights - Use, duplication or
// disclosure restricted by GSA ADP Schedule Contract with IBM Corp.
//
// IBM DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
// ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL, INDIRECT OR
// CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
// USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
// OR PERFORMANCE OF THIS SOFTWARE.
//
//===================END_PROLOG========================================
package WebSphereSamples.ConnPool;
/**
* Dies ist eine Primärschlüsselklasse für die Entity-Bean
**/
public class EmployeeBMPKey implements java.io.Serializable {
public String empNo;
final static long serialVersionUID = 3206093459760846163L;
/**
* Konstruktor EmployeeBMPKey()
*/
public EmployeeBMPKey() {
}
/**
* Konstruktor EmployeeBMPKey(String key)
*/
public EmployeeBMPKey(String key) {
empNo = key;
}
/**
* Methode equals
* Benutzer muss eine passende Implementierung für die Methode equal bereitstellen. Die
* generierte Methode geht davon aus, dass der Schlüssel ein Zeichenfolgeobjekt ist.
*/
public boolean equals (Object o) {
if (o instanceof EmployeeBMPKey)
return empNo.equals(((EmployeeBMPKey)o).empNo);
else
return false;
}
/**
* Methode hashCode
* Benutzer muss eine passende Implementierung für die Methode hashCode bereitstellen. Die
* generierte Methode geht davon aus, dass der Schlüssel ein Zeichenfolgeobjekt ist.
*/
public int hashCode () {
return empNo.hashCode();
Beispiel: Behandlung von Ausnahmen beim Datenzugriff - ConnectionWaitTimeoutException (für die JDBC-API)
Dieses Codebeispiel zeigt, wie die Bedingungen festgelegt werden, unter denen der Anwendungsserver die Ausnahme ConnectionWaitTimeoutException für eine JDBC-Anwendung auslöst.
Wenn die Ausnahme "ConnectionWaitTimeoutException" abgefangen wird, gibt es wenig Chancen für eine Wiederherstellung.
public void test1() {
java.sql.Connection conn = null;
java.sql.Statement stmt = null;
java.sql.ResultSet rs = null;
try {
// Datenquelle suchen
java.util.Properties props = new java.util.Properties();
props.put(
javax.naming.Context.INITIAL_CONTEXT_FACTORY,
com.ibm.websphere.naming.WsnInitialContextFactory);
ic = new javax.naming.InitialContext(props);
javax.sql.DataSource ds1 = (javax.sql.DataSource) ic.lookup(jndiString);
// Verbindung abrufen.
conn = ds1.getConnection();
stmt = conn.createStatement();
rs = stmt.executeQuery("select * from mytable where this = 54");
}
catch (java.sql.SQLException sqlX) {
if (sqlX instanceof com.ibm.websphere.ce.cm.ConnectionWaitTimeoutException
|| sqlX instanceof java.sql.SQLTransientConnectionException
&& sqlX.getCause() instanceof com.ibm.websphere.ce.cm.ConnectionWaitTimeoutException)
{
//Den Benutzer benachrichtigen, dass das System keine Verbindung
//zur Datenbank hertellen konnte. Dies ist meist der Fall, wenn der
//Verbindungspool voll ist und keine Verbindung für gemeinsame
//Benutzung vorhanden ist.
}
else
{
// Andere Datenbankfehler beheben.
}
}
finally {
if (rs != null)
try {
rs.close();
}
catch (java.sql.SQLException sqle1) {
}
if (stmt != null)
try {
stmt.close();
}
catch (java.sql.SQLException sqle1) {
}
if (conn != null)
try {
conn.close(); }
catch (java.sql.SQLException sqle1) {
}
}
}
Beispiel: Behandlung von Ausnahmen beim Datenzugriff - ConnectionWaitTimeoutException für Java EE Connector Architecture
Dieses Codebeispiel zeigt, wie die Bedingungen festgelegt werden, unter denen WebSphere Application die Ausnahme ConnectionWaitTimeout für eine JCA-Anwendung auslöst.
In allen Fällen, in denen die Ausnahme ConnectionWaitTimeout abgefangen wird, gibt es praktisch keine Möglichkeit der Fehlerbehebung.
Das folgende Codefragment veranschaulicht, wie diese Ausnahme in Java Platform, Enterprise Edition (Java EE) Connector Architecture (JCA) verwendet wird:
/**
* Diese Methode führt einen einfachen Verbindungstest durch.
*/
public void testConnection()
throws javax.naming.NamingException, javax.resource.ResourceException, com.ibm.websphere.ce.j2c.ConnectionWaitTimeoutException {
javax.resource.cci.ConnectionFactory factory = null;
javax.resource.cci.Connection conn = null;
javax.resource.cci.ConnectionMetaData metaData = null;
try {
// Die Verbindungsfactory abrufen
if (verbose) System.out.println("Look up the connection factory...");
try {
factory =
(javax.resource.cci.ConnectionFactory) (new InitialContext()).lookup("java:comp/env/eis/Sample");
}
catch (javax.naming.NamingException ne) {
// Die Verbindungsfactory kann nicht abgerufen werden.
throw ne;
}
// Verbindung abrufen
if (verbose) System.out.println("Get the connection...");
conn = factory.getConnection();
// Verbindungsdaten der Verbindung abrufen
metaData = conn.getMetaData();
// Informationen zu Metadaten ausgeben.
System.out.println("EISProductName" is + metaData.getEISProductName());
}
catch (com.ibm.websphere.ce.j2c.ConnectionWaitTimeoutException cwtoe) {
// Wartezeit für Verbindung
throw cwtoe;
}
catch (javax.resource.ResourceException re) {
// Fehler in Verbindungen.
throw re;
}
finally {
if (conn != null) {
try {
conn.close(); }
catch (javax.resource.ResourceException re) {
}
}
}
}
Beispiel: Behandlung von Ausnahmen beim Datenzugriff - Fehlerzuordnung in DataStoreHelper
Der Anwendungsserver stellt eine DataStoreHelper-Schnittstelle für die Zuordnung unterschiedlicher SQL-Datenbankfehlercodes zu den entsprechenden Ausnahmen im Anwendungsserver bereit.
Die Fehlerzuordnung ist erforderlich, weil unterschiedliche Datenbankanbieter unterschiedliche SQL-Fehler und -Codes verwenden können, um dasselbe Problem darzustellen. Beispielsweise hat die Ausnahme wegen veralteter Verbindung in den verschiedenen Datenbanken unterschiedliche Codes. Die DB2-SQL-Codes 1015, 1034, 1036 usw. zeigen an, dass die Verbindung aufgrund eines temporären Datenbankproblems nicht mehr verfügbar ist. Die Oracle-SQL-Codes 28, 3113, 3114 usw. zeigen dieselbe Situation an.
Durch Zuordnung dieser Fehlercodes zu Standardausnahmen wird die Konsistenz erreicht, die erforderlich ist, damit Anwendungen in den unterschiedlichen Installationen des Anwendungsservers portierbar sind. Das folgende Codesegment veranschaulicht, wie zwei Fehlercodes der Fehlermaske zugeordnet werden:public class NewDSHelper extends GenericDataStoreHelper
{
public NewDSHelper(java.util.Properties dataStoreHelperProperties)
{
super(dataStoreHelperProperties);
java.util.Hashtable myErrorMap = null;
myErrorMap = new java.util.Hashtable();
myErrorMap.put(new Integer(-803), myDuplicateKeyException.class);
myErrorMap.put(new Integer(-1015), myStaleConnectionException.class);
myErrorMap.put("S1000", MyTableNotFoundException.class);
setUserDefinedMap(myErrorMap);
...
}
}
Eine Konfigurationsoption mit dem Namen "Fehlererkennungsmodell" steuert, wie die Fehlerzuordnung eingesetzt wird. Bis zur Version 6 war die Ausnahmezuordnung die einzige verfügbare Option für das Fehlererkennungsmodell. Ab Version 7 wird eine weitere Option mit dem Namen "Ausnahmeprüfung" bereitgestellt. Unter dem Modell "Ausnahmezuordnung" verwendet der Anwendungsserver die Fehlerzuordnung und ersetzt Ausnahmen durch den entsprechenden, in der Fehlerzuordnung aufgelisteten Ausnahmetyp. Unter dem Modell "Ausnahmeprüfung" verwendet der Anwendungsserver weiterhin die Fehlerzuordnung für seine eigenen Zwecke, ersetzt aber keine Ausnahmen. Wenn Sie das Modell "Ausnahmezuordnung" weiterhin verwenden möchten, müssen Sie nichts ändern. Die Ausnahmezuordnung ist das Standardfehlererkennungsmodell. Wenn Sie das Modell "Ausnahmeprüfung" verwenden möchten, lesen Sie den Artikel "Fehlererkennungsmodell auf das Modell "Ausnahmeprüfung" umstellen" unter "Zugehörige Links".
Datenbank-Deadlocks und Konflikte bei Fremdschlüsseln
Die Wiederholung bestimmter SQL-Fehlernachrichten zeigen Probleme an, z. B. Verletzungen der referenziellen Integrität der Datenbank, die Sie vermeiden können, indem Sie das Feature für CMP-Sequenzgruppierung verwenden.
Ausnahmen durch Fremdschlüsselkonflikte, die aufgrund von Verletzungen der referenziellen Integrität der Datenbank auftretenEine Datenbankrichtlinie für referenzielle Integrität (RI) gibt Regeln für das Schreiben von Daten in die Datenbanktabellen und das Löschen von Daten aus den Datenbanktabellen vor, um die relationale Konsistenz zu gewährleisten. Die Laufzeitanforderungen für die Verwaltung der Bean-Persistenz können jedoch dazu führen, dass eine EJB-Anwendung gegen RI-Regeln verstößt, woraufhin möglicherweise Datenbankausnahmen ausgelöst werden.
The insert or update value of the FOREIGN KEY table1.name_of_foreign_key_constraint
is not equal to any value of the parent key of the parent table.
oderA parent row cannot be deleted because the relationship table1.name_of_foreign_key_constraint
is not equal to any value of the parent key of the parent table.
Wenn Sie die Reihenfolge festlegen, in der Entity-Beans relationale Datenbanktabellen aktualisieren, indem Sie Bean-Sequenzen definieren, können Sie derartige Ausnahmen vermeiden.
Ausnahmen durch gegenseitige Sperren bei optimistischer ParallelitätssteuerungAuch hier können Sequenzen Ausnahmen für Entity-Beans mit optimistischer Parallelitätssteuerung, die mit einer Zurücksetzung von Transaktionen verbunden sind, auf ein Minimum reduziert werden. Die optimistische Parallelitätssteuerung gibt vor, dass Datenbanksperren nur für eine Mindestzeit gehalten werden, damit eine möglichst große Anzahl von Transaktionen kontinuierlich Zugriff auf die Daten haben. Bei einer Datenbank mit so hoher Verfügbarkeit können parallele Transaktionen versuchen, dieselbe Tabellenzeile zu sperren, und so eine gegenseitige Sperre bewirken. Die dadurch ausgelösten Ausnahmen können Nachrichten wie die folgende generieren (die in einer Umgebung mit DB2 erzeugt wurde):
Unsuccessful execution caused by deadlock or timeout.
Nutzen Sie das Sequenzfeature, um die Bean-Persistenz so zu organisieren, dass die Wahrscheinlichkeit von gegenseitigen Datenbanksperren sinkt.