与数据访问相关的异常
当操作失败时,遵循 Enterprise JavaBeans (EJB) 2.x 规范的所有企业 Bean 容器管理的持久性 (CMP) Bean 都将接收到标准的 EJB 异常。如果有任何 JDBC 操作失败,那么 Java™ 数据库连接 (JDBC) 应用程序将接收到标准的 SQL 异常。产品为其关系资源适配器 (RRA) 提供专门的异常,表明当前保持的连接不再有效。
- 连接等待超时异常表明应用程序等待的时间已经达到连接超时设置指定的秒数,但还未收到连接。这种情况发生在池已经到达了最大大小,并且在等待期间其他应用程序使用了所有的连接。此外,因为连接属性不匹配或连接在不同的事务中,所以当前没有应用程序可以共享的在使用的连接。
对于 V4.0 数据源,ConnectionWaitTimeout 对象创建了从 com.ibm.ejs.cm.pool.ConnectionWaitTimeoutException 类实例化的异常。
对于 Java 2 连接器 (J2C) 连接工厂,ConnectionWaitTimeout 对象将生成 com.ibm.websphere.ce.j2c.ConnectionWaitTimeoutException 类的资源异常。
将错误检测模型配置为异常映射时,较高版本的数据源将发出 com.ibm.websphere.ce.cm.ConnectionWaitTimeoutException 子类的 SQL 异常。错误检测模型配置为异常检查时,较高版本的数据源将发出 java.sql.SQLTransientConnectionException 类的 SQL 异常,并带有 com.ibm.websphere.ce.cm.ConnectionWaitTimeoutException 类的链接异常。
- 错误检测模型配置为异常映射时,失效连接异常表明连接不再有效。 错误检测模型配置为异常检查时,JDBC 驱动程序将发出 JDBC 4.0 异常(例如 java.sql.SQLRecoverableException 或 java.sql.SQLNonTransientConnectionException),或 JDBC 驱动程序指定合适的 SQLState 以表明连接不再有效。请阅读“旧连接”主题以了解有关此类型的异常的更多信息。
- 条目用 ;(分号)分隔。
- 每个条目由键和值组成,其中,键是错误代码(数字值)或者 SQLState(这是用引号引起来的文本)。
- 键和值之间用 =(等号)分隔。
"S1000"=;1062=com.ibm.websphere.ce.cm.DuplicateKeyException;"08004"=
com.ibm.websphere.ce.cm.StaleConnectionException
通过选择数据源并配置定制属性,可在管理控制台中找到 userDefinedErrorMap。- 旧连接
- 示例:处理数据访问异常 - 旧连接
- Linux 系统上的旧连接
- 示例:处理 Servlet JDBC 连接异常
- 示例:处理容器管理的数据库事务中会话 Bean 的连接异常
- 示例:处理 Bean 管理的数据库事务中会话 Bean 的连接异常
- 示例:处理容器管理的数据库事务中 BMP Bean 的连接异常
- 示例:处理数据访问异常 - ConnectionWaitTimeoutException(对于 JDBC API)
- 示例:处理数据访问异常 - ConnectionWaitTimeoutException(对于 Java EE 连接器体系结构)
- 示例:处理数据访问异常 - 在 DataStoreHelper 中的映射错误
- 数据库死锁和外键冲突
旧连接
该产品提供了 java.sql.SQLException 类的特殊子类以使用连接池访问关系数据库。此 com.ibm.websphere.ce.cm.StaleConnectionException 子类存在于 WebSphere® 4.0 数据源和使用关系资源适配器的最新版本的数据源中。此类表明当前保持的连接不再有效。
- 未启动数据库时,应用程序尝试获取连接将失败。
- 由于数据库故障,连接不再可用。当应用程序尝试使用先前获取的连接时,该连接却不再有效。在这种情况下,应用程序当前使用的所有连接在尝试使用该连接时会获取此错误。
- 连接是孤立连接(因为应用程序未使用连接的时间超过了未使用超时设置中的值的两倍),应用程序尝试使用该孤立连接。此情况仅适用于 V4.0 数据源。
- 应用程序尝试使用失效连接上获取的 JDBC 资源(例如语句)。
- 连接被 V4.0 数据源自动清除连接功能关闭并且不能再使用。自动清除连接是连接管理进行操作的标准方式。此方式表明在事务结束时,事务管理器关闭在该事务中使用的所有连接。这使事务管理器能确保不超时持有连接,并且池不会提前达到其最大连接数。
但是,如果事务管理器在事务结束之后关闭了连接并将连接返回至空闲池,那么随之产生否定分支。 应用程序无法尝试在一个事务中使用从另一个事务中获取的连接。如果应用程序尝试这样做,将会发生 ObjectClosedException,而这则是一个 StaleConnectionException,因为该连接已关闭。
- 将最小连接池大小设置为 0,这样当应用程序服务器长期处于不活动状态时,连接池将保持为空。这有助于避免连接因数据库端的维护活动变为失效。
- 将连接池“未使用超时”设置为比对防火墙超时所配置值更小的值。这可以确保连接在达到“未使用超时”之前不会失效,并使连接可保留在空闲池中以供复用。
- 将连接池“收集时间”设置为比“未使用超时”更小的值。值越小,池维护线程检查越频繁,未使用计时器就越为精确。但是,池维护线程频繁运行可能会降低性能。
如果您正在尝试使用孤立连接或者由“自动清除连接”功能使其变得不可用的连接,那么旧连接异常会指出应用程序已经尝试使用已返回到连接池的连接。它不表明连接的实际问题。但是,其他情况的失效连接异常表示数据库的连接已出错或失效。一旦连接失效,您无法将其恢复,并且必须完全关闭该连接而不是将其返回到池。
检测失效连接当到数据库的连接变得失效时,该连接上的操作导致来自 JDBC 驱动程序的 SQL 异常。因为 SQL 异常是相当一般的异常,它包含可用来确定异常含意的状态和错误代码值。但是,这些状态和错误代码的含意因数据库供应商不同而不同。连接池运行时维护哪种 SQL 状态的映射,而错误代码为支持的每个数据库供应商表明失效连接异常。当连接池运行时捕获 SQL 异常时,它会检查此 SQL 异常是否是使用中的数据库服务器的失效连接异常。
从失效连接恢复- 将错误检测模型配置为异常映射时,应用程序服务器将使用 StaleConnectionException 来替换 JDBC 驱动程序发出的异常。 在这种情况下,应用程序可能会陷入失效连接异常的陷阱。
- 将错误检测模型配置为异常检查时,应用程序服务器仍会参考错误映射以管理连接池,但是它不会替换异常。在这种情况下,应用程序不应陷入失效连接异常的陷阱。
考虑到这两个错误检测模型之间的差异,应用程序服务器将提供一个 API,在任何一种情况下,应用程序都可以使用该 API 来标识失效连接。此 API 是 com.ibm.websphere.rsadapter.WSCallHelper.getDataStoreHelper(datasource).isConnectionError(sqlexception)。
不要求应用程序显式标识失效连接异常。已要求应用程序捕获 java.sql.SQLException,失效连接异常或 JDBC 驱动程序发出的异常总是从 java.sql.SQLException 继承数据。失效连接异常(声明发出 SQLException 的任何方法都可能导致此异常)将在常规 catch 块中自动捕获。但是,显式标识失效连接异常使应用程序能从错误连接恢复。当应用程序代码标识失效连接异常时,它应采取显式步骤来进行恢复,例如在新的事务和新的连接下重试操作。
示例:处理数据访问异常 - 旧连接
这些代码采样证明如何在不同的事务方案中按程序地寻址不同类型数据访问客户机的旧连接异常。
当应用程序接收到关于数据库操作的失效的连接异常,这表明当前保持的连接不再有效。虽然在进行任何数据库操作时都可能收到旧连接异常,但系统通常在首次检索到连接后发出旧连接异常。 因为连接是合用的,所以直到进行了紧接着的从池中检索的操作(这是第一次尝试与数据库通信)才检测到数据库故障。仅当检测到故障后,该连接才标记为失效。如果访问数据库的每种方法都从池获得了新的连接时,那么较少发生失效的连接异常。

在应用程序可获取一个新连接以重试操作之前,回滚原始连接中涉及的事务并开始新事务。您可以将有关此操作的详细信息分为以下两个类别:
- 在 Bean 管理的全局事务上下文中采用与数据库访问相同的方法开始运行的对象
- 使用 Bean 管理的事务 (BMT) 的 Servlet 或会话会话 Bean 可通过调用 javax.transaction.UserTransaction
对象的 begin() 来显式地启动全局事务,您可从命名或从 Bean EJBContext 对象中检索到它。
要提交 Bean 管理的事务,应用程序调用 UserTransaction 对象的 commit()。要回滚事务,应用程序调用 rollback()。
实体 Bean 和非 BMT 会话 Bean 无法显式开始全局事务。
如果显式地启动 Bean 管理的事务的对象接收到关于数据库操作的失效的连接异常,那么结束该连接并回滚该事务。在这里,应用程序开发者可以确定开始一个新事务、获取一个新连接和重试操作。
以下代码段显示了处理此方案中失效连接异常的示例://get a userTransaction javax.transaction.UserTransaction tran = getSessionContext().getUserTransaction(); //retry indicates whether to retry or not //numOfRetries states how many retries have // been attempted boolean retry = false; int numOfRetries = 0; java.sql.Connection conn = null; java.sql.Statement stmt = null; do { try { //begin a transaction tran.begin(); //Assumes that a datasource has already been obtained //from JNDI 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) { // If the error indicates the connection is stale, then // rollback and retry the action if (com.ibm.websphere.rsadapter.WSCallHelper .getDataStoreHelper(ds) .isConnectionError(sqlX)) { try { tran.rollback(); } catch (java.lang.Exception e) { //deal with exception //in most cases, this can be ignored } if (numOfRetries < 2) { retry = true; numOfRetries++; } else { retry = false; } } else { //deal with other database exception retry = false } } finally { //always cleanup JDBC resources try { if(stmt != null) stmt.close(); } catch (java.sql.SQLException sqle) { //usually can ignore } try { if(conn != null) conn.close(); } catch (java.sql.SQLException sqle) { //usually can ignore } } } while (retry) ;
- 对象操作在不是以与数据库访问相同的方法开始的全局事务上下文和事务中。
- 当接收到失效的连接异常的对象没有直接控制事务时(如,在容器管理的事务中),该对象必须标记回滚的事务,然后向其调用者表明要重试该事务。大多数情况下,您可以通过创建表明要重试该操作的应用程序异常来执行此操作。但是,并非总是允许执行此操作,并且通常只是定义用于创建特殊异常的方法。这是在企业 Bean 上使用 ejbLoad() 和 ejbStore() 方法时的情况。下面两个示例解释了这些方案。
- 示例 1:数据库访问方法创建应用程序异常
- 当访问数据库的方法能够任意创建任何需要的异常时,最佳实践是捕捉失效的连接异常并创建可以说明您要重试该方法的某个应用程序异常。
以下示例显示在使用事务定界 TX_REQUIRED 的实体 Bean 上调用方法的 EJB
客户机,这意味着当调用 insertValue() 时容器将开始一个全局事务:
public class MyEJBClient { //... other methods here ... 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); } } //end MyEJBClient public class MyEJB implements javax.ejb.EntityBean { //... other methods here ... 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) { // Find out if the error indicates the connection is stale if (com.ibm.websphere.rsadapter.WSCallHelper .getDataStoreHelper(ds) .isConnectionError(sqlX)) { getSessionContext().setRollbackOnly(); throw new RetryableConnectionException(); } else { //handle other database problem } } finally { //always cleanup JDBC resources try { if(stmt != null) stmt.close(); } catch (java.sql.SQLException sqle) { //usually can ignore } try { if(conn != null) conn.close(); } catch (java.sql.SQLException sqle) { //usually can ignore } } } } //end MyEJB
假设早已从 Java 命名和目录接口 (JNDI) 中检索到 Home 接口,那么 MyEJBClient 先从 Home 接口获取 MyEJB bean。 然后调用 Bean 上的 insertValue()。bean 上的方法将获取连接,并尝试将值插入表中。如果某种方法失败并发出失效的连接异常,那么它将事务标记为 rollbackOnly(促使调用者回滚该事务)并创建一个新的可重试的连接异常(抛出异常之前清除资源)。可重试的连接异常仅仅是应用程序定义的异常,该异常告知调用者要重试方法。调用者监视可重试的连接异常,并且如果捕捉到该异常,那么重试方法。在此示例中,因为容器正在开始和结束事务;客户机或服务器中不需要事务管理。当然,客户机可以启动一个 Bean 管理的事务,且假定客户机已落实或回滚该事务,其行为仍将相同。
- 示例 2:数据库访问方法创建 onlyRemote 异常或 EJB 异常
- 并不是所有的方法都允许抛出由应用程序定义的异常。如果您使用 Bean 管理的持久性 (BMP),那么使用
ejbLoad() 和 ejbStore() 方法来存储 Bean 状态。从这些方法发出的异常仅仅是 java.rmi.Remote 异常或 javax.ejb.EJB 异常,因此您无法使用与前一个示例类似的某些内容。如果您使用容器管理的持久性 (CMP),那么容器管理 Bean 持久性,并且由该容器来查看失效的连接异常。如果在异常返回到客户机时检测到失效的连接,那么说明此异常只是一个远程异常,因此,简单的 catch 块是不够的。有一种方法能够确定远程异常的根本原因是不是失效的连接异常。当创建远程异常以合并另一个异常时,通常保留原始异常。 所有的远程异常实例都有详细信息属性,其类型是 java.lang.Throwable。通过此详细信息,您可以跟踪回到原始异常,并且如果该异常是失效的连接异常,那么重试事务。实际上,当这些远程异常从一个 Java 虚拟机 API 流动到下一个 API 时,详细信息会丢失,因此最好在数据库访问发生时的同一服务器中启动事务。出于这个原因,以下示例显示了由使用 Bean 管理的事务定界的会话 Bean 来访问实体 bean。
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(); // causes ejbLoad() to be invoked myBMPBean.myMethod(); // causes ejbStore() to be invoked tran.commit(); } catch(java.rmi.EJBException re) { try { tran.rollback(); } catch(Exception e) { //can ignore } if (causedByStaleConnection(re)) retry = true; else throw re; } catch(Exception e) { // handle some other problem } finally { //always cleanup JDBC resources try { if(stmt != null) stmt.close(); } catch (java.sql.SQLException sqle) { //usually can ignore } try { if(conn != null) conn.close(); } catch (java.sql.SQLException sqle) { //usually can ignore } } } while (retry); } public boolean causedByStaleConnection(java.rmi.EJBException re) { // Search the exception chain for errors // indicating a stale connection for (Throwable t = re; t != null; t = t.getCause()) if (t instanceof RetryableConnectionException) return true; // Not found to be stale 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) { // Find out if the error indicates the connection is stale if (com.ibm.websphere.rsadapter.WSCallHelper .getDataStoreHelper(ds) .isConnectionError(sqlX)) { // rollback the tran when method returns getEntityContext().setRollbackOnly(); throw new java.rmi.EJBException( "Exception occurred in ejbStore", new RetryableConnectionException(sqlX)); } else { // handle some other problem } } finally { //always cleanup JDBC resources try { if(stmt != null) stmt.close(); } catch (java.sql.SQLException sqle) { //usually can ignore } try { if(conn != null) conn.close(); } catch (java.sql.SQLException sqle) { //usually can ignore } } } }
前一个示例的 mySessionBMTMethod() 中:- 会话 Bean 首先从会话上下文中检索 UserTransaction 对象,然后开始全局事务。
- 其次,它将调用实体 Bean 上的方法,即调用 ejbLoad() 方法。 如果 ejbLoad() 运行成功,那么客户机然后将提交引起调用 ejbStore() 方法的事务。
- 在 ejbStore() 中,实体 Bean 会获取连接并将其状态写入到数据库;如果检索的连接是旧连接,那么将事务标记为 rollbackOnly 并抛出包含 RetryableConnectionException 的新 EJBException。然后客户机捕捉到该异常(清除 JDBC 资源、回滚事务)并且调用 causedByStaleConnection(),以确定异常中某处是否隐含失效的连接异常。
- 如果方法返回 true,那么设置重试标志并重试该事务;否则,重新向调用者发出异常。
- causedByStaleConnection() 方法将审核详细信息属性的链,以查找原始异常。当异常最终返回到客户机时,可能会发生多个异常的合并,因此只有当方法遇到旧连接异常时才停止搜索并返回 true;否则列表中没有旧连接异常并返回 false。
- 如果您正在讨论的是 CMP Bean 而不是 BMP Bean,那么会话 Bean 相同。CMP Bean ejbStore() 方法很可能为空,并且在调用此方法之后,容器中将持久保存具有所生成的代码的 Bean。
- 如果持久状态期间发生失效的连接异常,那么通过远程异常包装该异常并且将它返回给调用者。causedByStaleConnection() 方法将再次浏览异常链,并查找根本异常(可能是失效的连接异常)。
- 在局部事务上下文中运行的对象
- 当数据库操作发生在全局事务上下文之外,那么容器将隐含地开始一个局部事务。这包括没有用 UserTransaction 接口开始事务的 Servlet 或 JSP,以及在未指定的事务上下文中运行的企业 Bean。
当使用全局事务时,您必须在重试操作之前回滚局部事务。在这些情况下,局部事务容器通常在业务方法结束时结束。
一个异常是您是否正在使用活动会话。在这种情况下,活动会话必须在尝试获取新连接之前结束。
当局部事务发生在未指定的事务上下文中运行的企业 Bean 中、企业 Bean 客户机对象和局部事务容器之外时,可以使用在前一个项目符号中描述的方法来重试事务。但是,当局部事务容器作为 Servlet 或 JSP 文件的一部分发生的,那么没有客户机对象可用于重试该操作。出于这个原因,建议避免 Servlet 和 JSP 文件中的数据库操作,除非它们是用户事务的一部分。
Linux 系统上的旧连接
您可能必须设置回送,才能从 Linux 平台上的应用程序服务器访问 DB2® 数据库。
- 使用 DB2 通用 JDBC 2 类驱动程序来连接到本地 DB2 数据库
- 使用 DB2 通用 JDBC 2 类驱动程序通过与应用程序服务器安装在同一台机器上的 DB2 Connect™ 来访问 DB2 for z/OS®。只有当 DB2 Connect 限制代理程序内运行的本地客户机时才会出现这种问题。(即,如果 DB2_IN_APP_PROCESS 设置不是缺省值,或者该设置为 Yes。将值设置为 No 可解决该问题并避免执行以下过程。)
'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
示例:处理 Servlet JDBC 连接异常
以下代码样本说明如何设置事务管理和连接管理属性(如操作重试次数)来解决 Servlet JDBC 事务中的旧连接异常。
- 初始化 Servlet
- 查找数据源
- 指定错误消息、连接重试次数和事务回滚要求
//===================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.*;
// Import JDBC packages and naming service packages.
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 = "Employee List";
// ****************************************************************
// * Initialize servlet when it is first loaded. *
// * Get information from the properties file, and look up the *
// * DataSource object from JNDI to improve performance of the *
// * the servlet's service methods. *
// ****************************************************************
public void init(ServletConfig config)
throws ServletException
{
super.init(config);
getDS();
}
// ****************************************************************
// * Perform the JNDI lookup for the DataSource and *
// * User Transaction objects. *
// * This method is invoked from init(), and from the service *
// * method of the DataSource is 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);
// Perform a naming service lookup to get the DataSource object.
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();
}
}
// ****************************************************************
// * Respond to user GET request *
// ****************************************************************
public void doGet(HttpServletRequest req, HttpServletResponse res) throws ServletException, IOException
{
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
Vector employeeList = new Vector();
// Set retryCount to the number of times you would like to retry after a
// stale connection exception
int retryCount = 5;
// If the Database code processes successfully, we will set error = false
boolean error = true;
do
{
try
{
//Start a new Transaction
ut.begin();
// Get a Connection object conn using the DataSource factory.
conn = ds.getConnection();
// Run DB query using standard JDBC coding.
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));
}
//Set error to false to indicate successful completion of the database work
error=false;
}
catch (SQLException sqlX)
{
// Determine if the connection request timed out.
// This code works regardless of which error detection
// model is used. If exception mapping is enabled, then
// we need to look for ConnectionWaitTimeoutException.
// If exception checking is enabled, then look for
// SQLTransientConnectionException with a chained
// ConnectionWaitTimeoutException.
if ( sqlX instanceof ConnectionWaitTimeoutException
|| sqlX instanceof SQLTransientConnectionException
&& sqlX.getCause() instanceof ConnectionWaitTimeoutException)
{
// This exception is thrown if a connection can not be obtained from the
// pool within a configurable amount of time. Frequent occurrences of
// this exception indicate an incorrectly tuned connection pool
System.out.println("Connection Wait Timeout Exception during get connection or
process SQL:" + c.getMessage());
//In general, we do not want to retry after this exception, so set retry count to 0
//and roll back the transaction
try
{
ut.setRollbackOnly();
}
catch (SecurityException se)
{
//Thrown to indicate that the thread is not allowed to roll back the transaction.
System.out.println("Security Exception setting rollback only!" + se.getMessage());
}
catch (IllegalStateException ise)
{
//Thrown if the current thread is not associated with a transaction.
System.out.println("Illegal State Exception setting rollback only!" + ise.getMessage());
}
catch (SystemException sye)
{
//Thrown if the transaction manager encounters an unexpected error condition
System.out.println("System Exception setting rollback only!" + sye.getMessage());
}
retryCount=0;
}
else if (WSCallHelper.getDataStoreHelper(ds).isConnectionError(sqlX))
{
// This exception indicates that the connection to the database is no longer valid.
//Roll back the transaction, then retry several times to attempt to obtain a valid
//connection, display an error message if the connection still can not be obtained.
System.out.println("Connection is stale:" + sc.getMessage());
try
{
ut.setRollbackOnly();
}
catch (SecurityException se)
{
//Thrown to indicate that the thread is not allowed to roll back the transaction.
System.out.println("Security Exception setting rollback only!" + se.getMessage());
}
catch (IllegalStateException ise)
{
//Thrown if the current thread is not associated with a transaction.
System.out.println("Illegal State Exception setting rollback only!" + ise.getMessage());
}
catch (SystemException sye)
{
//Thrown if the transaction manager encounters an unexpected error condition
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());
//In general, we do not want to retry after this exception, so set retry count to 0
//and rollback the transaction
try
{
ut.setRollbackOnly();
}
catch (SecurityException se)
{
//Thrown to indicate that the thread is not allowed to roll back the transaction.
System.out.println("Security Exception setting rollback only!" + se.getMessage());
}
catch (IllegalStateException ise)
{
//Thrown if the current thread is not associated with a transaction.
System.out.println("Illegal State Exception setting rollback only!" + ise.getMessage());
}
catch (SystemException sye)
{
//Thrown if the transaction manager encounters an unexpected error condition
System.out.println("System Exception setting rollback only!" + sye.getMessage());
}
retryCount=0;
}
}
catch (NotSupportedException nse)
{
//Thrown by UserTransaction begin method if the thread is already associated with a
//transaction and the Transaction Manager implementation does not support nested
//transactions.
System.out.println("NotSupportedException on User Transaction begin:" + nse.getMessage());
}
catch (SystemException se)
{
//Thrown if the transaction manager encounters an unexpected error condition
System.out.println("SystemException in User Transaction:" +se.getMessage());
}
catch (Exception e)
{
System.out.println("Exception in get connection or process SQL:" + e.getMessage());
//In general, we do not want to retry after this exception, so set retry count to 5
//and roll back the transaction
try
{
ut.setRollbackOnly();
}
catch (SecurityException se)
{
//Thrown to indicate that the thread is not allowed to roll back the transaction.
System.out.println("Security Exception setting rollback only!" + se.getMessage());
}
catch (IllegalStateException ise)
{
//Thrown if the current thread is not associated with a transaction.
System.out.println("Illegal State Exception setting rollback only!" + ise.getMessage());
}
catch (SystemException sye)
{
//Thrown if the transaction manager encounters an unexpected error condition
System.out.println("System Exception setting rollback only!" + sye.getMessage());
}
retryCount=0;
}
finally
{
// Always close the connection in a finally statement to ensure proper
// closure in all cases. Closing the connection does not close and
// actual connection, but releases it back to the pool for reuse.
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)
{
//Thrown to indicate that the transaction has been rolled back rather than committed.
System.out.println("User Transaction Rolled back!" + re.getMessage());
}
catch (SecurityException se)
{
//Thrown to indicate that the thread is not allowed to commit the transaction.
System.out.println("Security Exception thrown on transaction commit:" + se.getMessage());
}
catch (IllegalStateException ise)
{
//Thrown if the current thread is not associated with a transaction.
System.out.println("Illegal State Exception thrown on transaction commit:" + ise.getMessage());
}
catch (SystemException sye)
{
//Thrown if the transaction manager encounters an unexpected error condition
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 );
// Prepare and return HTML response, prevent dynamic content from being cached
// on browsers.
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());
}
}
}
示例:处理容器管理的数据库事务中会话 Bean 的连接异常
以下代码样本说明了在出现旧连接异常的情况下如何回滚事务以及如何向 Bean 客户机发出异常。
//===================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;
/*************************************************************************************
* This bean is designed to demonstrate Database Connections in a
* Container Managed Transaction Session Bean. Its transaction attribute *
* should be set to TX_REQUIRED or TX_REQUIRES_NEW. *
**************************************************************************************
*/
public class ShowEmployeesCMTBean implements SessionBean {
private javax.ejb.SessionContext mySessionCtx = null;
final static long serialVersionUID = 3206093459760846163L;
private javax.sql.DataSource ds;
//************************************************************************************
//* ejbActivate calls the getDS method, which does the JNDI lookup for the DataSource.
//* Because the DataSource lookup is in a separate method, we can also invoke it from
//* the getEmployees method in the case where the DataSource field is null.
//************************************************************************************
public void ejbActivate() throws java.rmi.EJBException {
getDS();
}
/**
* ejbCreate method
* @exception javax.ejb.CreateException
* @exception java.rmi.EJBException
*/
public void ejbCreate() throws javax.ejb.CreateException, java.rmi.EJBException {}
/**
* ejbPassivate method
* @exception java.rmi.EJBException
*/
public void ejbPassivate() throws java.rmi.EJBException {}
/**
* ejbRemove method
* @exception java.rmi.EJBException
*/
public void ejbRemove() throws java.rmi.EJBException {}
//************************************************************************************
//* The getEmployees method runs the database query to retrieve the employees.
//* The getDS method is only called if the DataSource variable is null.
//* Because this session bean uses Container Managed Transactions, it cannot retry the
//* transaction on a StaleConnectionException. However, it can throw an exception to
//* its client indicating that the operation is retriable.
//************************************************************************************
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
{
// Get a Connection object conn using the DataSource factory.
conn = ds.getConnection();
// Run DB query using standard JDBC coding.
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)
{
// Determine if the connection is stale
if (WSCallHelper.getDataStoreHelper(ds).isConnectionError(sqlX))
{
// This exception indicates that the connection to the database is no longer valid.
// Roll back the transaction, and throw an exception to the client indicating they
// can retry the transaction if desired.
System.out.println("Connection is stale:" + sqlX.getMessage());
System.out.println("Rolling back transaction and throwing RetryableConnectionException");
mySessionCtx.setRollbackOnly();
throw new RetryableConnectionException(sqlX.toString());
}
// Determine if the connection request timed out.
else if ( sqlX instanceof ConnectionWaitTimeoutException
|| sqlX instanceof SQLTransientConnectionException
&& sqlX.getCause() instanceof ConnectionWaitTimeoutException)
{
// This exception is thrown if a connection can not be obtained from the
// pool within a configurable amount of time. Frequent occurrences of
// this exception indicate an incorrectly tuned connection pool
System.out.println("Connection Wait Timeout Exception during get connection or process SQL:" +
sqlX.getMessage());
throw sqlX instanceof ConnectionWaitTimeoutException ?
sqlX :
(ConnectionWaitTimeoutException) sqlX.getCause();
}
else
{
//Throwing a remote exception will automatically roll back the container managed
//transaction
System.out.println("SQL Exception during get connection or process SQL:" +
sqlX.getMessage());
throw sqlX;
}
}
finally
{
// Always close the connection in a finally statement to ensure proper
// closure in all cases. Closing the connection does not close and
// actual connection, but releases it back to the pool for reuse.
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;
}
/**
* getSessionContext method
* @return javax.ejb.SessionContext
*/
public javax.ejb.SessionContext getSessionContext() {
return mySessionCtx;
}
//************************************************************************************
//* The getDS method performs the JNDI lookup for the data source.
//* This method is called from ejbActivate, and from getEmployees if the data source
//* object is 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);
// Perform a naming service lookup to get the DataSource object.
ds = (DataSource)ctx.lookup("java:comp/env/jdbc/SampleDB");
}
catch (Exception e) {
System.out.println("Naming service exception:" + e.getMessage());
e.printStackTrace();
}
}
/**
* setSessionContext method
* @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;
/**
* This is a Home interface for the Session Bean
*/
public interface ShowEmployeesCMTHome extends javax.ejb.EJBHome {
/**
* create method for a 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;
/**
* This is an Enterprise Java Bean Remote Interface
*/
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;
/**
* Exception indicating that the operation can be retried
* Creation date: (4/2/2001 10:48:08 AM)
* @author: Administrator
*/
public class RetryableConnectionException extends Exception {
/**
* RetryableConnectionException constructor.
*/
public RetryableConnectionException() {
super();
}
/**
* RetryableConnectionException constructor.
* @param s java.lang.String
*/
public RetryableConnectionException(String s) {
super(s);
}
}
示例:处理 Bean 管理的数据库事务中会话 Bean 的连接异常
以下代码样本说明用于解决旧连接异常的选项。可以设置不同的事务管理和连接管理参数(如操作重试次数)以及连接超时时间间隔。
//===================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;
/**********************************************************************************
* This bean is designed to demonstrate Database Connections in a *
* Bean-Managed Transaction Session Bean. Its transaction attribute *
* should be set to TX_BEANMANAGED.
**********************************************************************************/
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 calls the getDS method, which makes the JNDI lookup for the DataSource
//* Because the DataSource lookup is in a separate method, we can also invoke it from
//* the getEmployees method in the case where the DataSource field is null.
//************************************************************************************
public void ejbActivate() throws java.rmi.EJBException {
getDS();
}
/**
* ejbCreate method
* @exception javax.ejb.CreateException
* @exception java.rmi.EJBException
*/
public void ejbCreate() throws javax.ejb.CreateException, java.rmi.EJBException {}
/**
* ejbPassivate method
* @exception java.rmi.EJBException
*/
public void ejbPassivate() throws java.rmi.EJBException {}
/**
* ejbRemove method
* @exception java.rmi.EJBException
*/
public void ejbRemove() throws java.rmi.EJBException {}
//************************************************************************************
//* The getEmployees method runs the database query to retrieve the employees.
//* The getDS method is only called if the DataSource or userTran variables are null.
//* If a stale connection occurs, the bean retries the transaction 5 times,
//* then throws an EJBException.
//************************************************************************************
public Vector getEmployees() throws EJBException {
Connection conn = null;
Statement stmt = null;
ResultSet rs = null;
Vector employeeList = new Vector();
// Set retryCount to the number of times you would like to retry after a
// stale connection
int retryCount = 5;
// If the Database code processes successfully, we will set error = false
boolean error = true;
if (ds == null || userTran == null) getDS();
do
{
try
{
//try/catch block for UserTransaction work
//Begin the transaction
userTran.begin();
try
{
//try/catch block for database work
//Get a Connection object conn using the DataSource factory.
conn = ds.getConnection();
// Run DB query using standard JDBC coding.
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));
}
//Set error to false, as all database operations are successfully completed
error = false;
}
catch (SQLException sqlX)
{
if (WSCallHelper.getDataStoreHelper(ds).isConnectionError(sqlX))
{
// This exception indicates that the connection to the database is no longer valid.
// Rollback the transaction, and throw an exception to the client indicating they
// can retry the transaction if desired.
System.out.println("Stale connection:" +
se.getMessage());
userTran.rollback();
if (--retryCount == 0)
{
//If we have already retried the requested number of times, throw an EJBException.
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)
{
// This exception is thrown if a connection can not be obtained from the
// pool within a configurable amount of time. Frequent occurrences of
// this exception indicate an incorrectly tuned connection pool
System.out.println("Connection request timed out:" +
sqlX.getMessage());
userTran.rollback();
throw new EJBException("Transaction failure:" + sqlX.getMessage());
}
else
{
// This catch handles all other SQL Exceptions
System.out.println("SQL Exception during get connection or process SQL:" +
sqlX.getMessage());
userTran.rollback();
throw new EJBException("Transaction failure:" + sqlX.getMessage());
}
finally
{
// Always close the connection in a finally statement to ensure proper
// closure in all cases. Closing the connection does not close and
// actual connection, but releases it back to the pool for reuse.
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) {
//Database work completed successfully, commit the transaction
userTran.commit();
}
//Catch UserTransaction exceptions
}
catch (NotSupportedException nse) {
//Thrown by UserTransaction begin method if the thread is already associated with a
//transaction and the Transaction Manager implementation does not support nested transactions.
System.out.println("NotSupportedException on User Transaction begin:" +
nse.getMessage());
throw new EJBException("Transaction failure:" + nse.getMessage());
}
catch (RollbackException re) {
//Thrown to indicate that the transaction has been rolled back rather than committed.
System.out.println("User Transaction Rolled back!" + re.getMessage());
throw new EJBException("Transaction failure:" + re.getMessage());
}
catch (SystemException se) {
//Thrown if the transaction manager encounters an unexpected error condition
System.out.println("SystemException in User Transaction:" + se.getMessage());
throw new EJBException("Transaction failure:" + se.getMessage());
}
catch (Exception e) {
//Handle any generic or unexpected Exceptions
System.out.println("Exception in User Transaction:" + e.getMessage());
throw new EJBException("Transaction failure:" + e.getMessage());
}
}
while (error);
return employeeList;
}
/**
* getSessionContext method comment
* @return javax.ejb.SessionContext
*/
public javax.ejb.SessionContext getSessionContext() {
return mySessionCtx;
}
//************************************************************************************
//* The getDS method performs the JNDI lookup for the DataSource.
//* This method is called from ejbActivate, and from getEmployees if the DataSource
//* object is 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);
// Perform a naming service lookup to get the DataSource object.
ds = (DataSource)ctx.lookup("java:comp/env/jdbc/SampleDB");
//Create the UserTransaction object
userTran = mySessionCtx.getUserTransaction();
}
catch (Exception e) {
System.out.println("Naming service exception:" + e.getMessage());
e.printStackTrace();
}
}
/**
* setSessionContext method
* @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;
/**
* This is a Home interface for the Session Bean
*/
public interface ShowEmployeesBMTHome extends javax.ejb.EJBHome {
/**
* create method for a 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;
/**
* This is an Enterprise Java Bean Remote Interface
*/
public interface ShowEmployeesBMT extends javax.ejb.EJBObject {
/**
*
* @return java.util.Vector
*/
java.util.Vector getEmployees() throws java.rmi.RemoteException, javax.ejb.EJBException;
}
示例:处理容器管理的数据库事务中 BMP Bean 的连接异常
以下代码样本说明了在出现旧连接异常的情况下如何回滚事务以及如何向 Bean 客户机发出异常。
//===================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;
/**
* This is an Entity Bean class with five BMP fields
* 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;
/**
* ejbActivate method
* ejbActivate calls getDS(), which performs the
* JNDI lookup for the datasource.
*/
public void ejbActivate() {
getDS();
}
/**
* ejbCreate method for a 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))
{
// This exception indicates that the connection to the database is no longer valid.
// Rollback the transaction, and throw an exception to the client indicating they
// can retry the transaction if desired.
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
{
// Always close the connection in a finally statement to ensure proper
// closure in all cases. Closing the connection does not close an
// actual connection, but releases it back to the pool for reuse.
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);
}
/**
* ejbFindByPrimaryKey method
* @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;
}
/**
* ejbLoad method
*/
public void ejbLoad() {
try {
EmployeeBMPKey pk = (EmployeeBMPKey) entityContext.getPrimaryKey();
loadByEmpNo(pk.empNo);
} catch (FinderException fe) {
throw new EJBException("Cannot load Employee state from database.");
}
}
/**
* ejbPassivate method
*/
public void ejbPassivate() {}
/**
* ejbPostCreate method for a 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))
{
// This exception indicates that the connection to the database is no longer valid.
// Rollback the transaction, and throw an exception to the client indicating they
// can retry the transaction if desired.
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
{
// Always close the connection in a finally statement to ensure proper
// closure in all cases. Closing the connection does not close an
// actual connection, but releases it back to the pool for reuse.
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());
}
}
}
}
/**
* Get the employee's edLevel
* Creation date: (4/20/2001 3:46:22 PM)
* @return int
*/
public int getEdLevel() {
return edLevel;
}
/**
* getEntityContext method
* @return javax.ejb.EntityContext
*/
public javax.ejb.EntityContext getEntityContext() {
return entityContext;
}
/**
* Get the employee's first name
* Creation date: (4/19/2001 1:34:47 PM)
* @return java.lang.String
*/
public java.lang.String getFirstName() {
return firstName;
}
/**
* Get the employee's last name
* Creation date: (4/19/2001 1:35:41 PM)
* @return java.lang.String
*/
public java.lang.String getLastName() {
return lastName;
}
/**
* get the employee's middle initial
* Creation date: (4/19/2001 1:36:15 PM)
* @return char
*/
public String getMiddleInit() {
return middleInit;
}
/**
* Lookup the DataSource from JNDI
* Creation date: (4/19/2001 3:28:15 PM)
*/
private void getDS() {
try {
Hashtable parms = new Hashtable();
parms.put(Context.INITIAL_CONTEXT_FACTORY,
com.ibm.websphere.naming.WsnInitialContextFactory);
InitialContext ctx = new InitialContext(parms);
// Perform a naming service lookup to get the DataSource object.
ds = (DataSource)ctx.lookup("java:comp/env/jdbc/SampleDB");
}
catch (Exception e) {
System.out.println("Naming service exception:" + e.getMessage());
e.printStackTrace();
}
}
/**
* Load the employee from the database
* Creation date: (4/19/2001 3:44:07 PM)
* @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
{
// Get a Connection object conn using the DataSource factory.
conn = ds.getConnection();
// Run DB query using standard JDBC coding.
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))
{
// This exception indicates that the connection to the database is no longer valid.
// Roll back the transaction, and throw an exception to the client indicating they
// can retry the transaction if desired.
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
{
// Always close the connection in a finally statement to ensure
// proper closure in all cases. Closing the connection does not
// close an actual connection, but releases it back to the pool
// for reuse.
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());
}
}
}
}
/**
* set the employee's education level
* Creation date: (4/20/2001 3:46:22 PM)
* @param newEdLevel int
*/
public void setEdLevel(int newEdLevel) {
edLevel = newEdLevel;
}
/**
* setEntityContext method
* @param ctx javax.ejb.EntityContext
*/
public void setEntityContext(javax.ejb.EntityContext ctx) {
entityContext = ctx;
}
/**
* set the employee's first name
* Creation date: (4/19/2001 1:34:47 PM)
* @param newFirstName java.lang.String
*/
public void setFirstName(java.lang.String newFirstName) {
firstName = newFirstName;
}
/**
* set the employee's last name
* Creation date: (4/19/2001 1:35:41 PM)
* @param newLastName java.lang.String
*/
public void setLastName(java.lang.String newLastName) {
lastName = newLastName;
}
/**
* set the employee's middle initial
* Creation date: (4/19/2001 1:36:15 PM)
* @param newMiddleInit char
*/
public void setMiddleInit(String newMiddleInit) {
middleInit = newMiddleInit;
}
/**
* unsetEntityContext method
*/
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;
/**
* This is an Enterprise Java Bean Remote Interface
*/
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;
/**
* This is an Enterprise Java Bean Remote Interface
*/
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;
/**
* This is a Primary Key Class for the Entity Bean
**/
public class EmployeeBMPKey implements java.io.Serializable {
public String empNo;
final static long serialVersionUID = 3206093459760846163L;
/**
* EmployeeBMPKey() constructor
*/
public EmployeeBMPKey() {
}
/**
* EmployeeBMPKey(String key) constructor
*/
public EmployeeBMPKey(String key) {
empNo = key;
}
/**
* equals method
* - user must provide a proper implementation for the equal method. The generated
* method assumes the key is a String object.
*/
public boolean equals (Object o) {
if (o instanceof EmployeeBMPKey)
return empNo.equals(((EmployeeBMPKey)o).empNo);
else
return false;
}
/**
* hashCode method
* - user must provide a proper implementation for the hashCode method. The generated
* method assumes the key is a String object.
*/
public int hashCode () {
return empNo.hashCode();
示例:处理数据访问异常 - ConnectionWaitTimeoutException(对于 JDBC API)
此代码样本说明如何指定应用程序服务器对 JDBC 应用程序发出 ConnectionWaitTimeoutException 异常的情况。
在捕获到 ConnectionWaitTimeoutException 的所有情况下,几乎不能恢复。
public void test1() {
java.sql.Connection conn = null;
java.sql.Statement stmt = null;
java.sql.ResultSet rs = null;
try {
// Look for datasource
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);
// Get Connection.
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)
{
//notify the user that the system could not provide a
//connection to the database. This usually happens when the
//connection pool is full and there is no connection
//available for to share.
}
else
{
// handle other database problems.
}
}
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) {
}
}
}
示例:处理数据访问异常 - ConnectionWaitTimeoutException(对于 Java EE 连接器体系结构)
此代码样本说明如何指定 WebSphere Application Server 对 JCA 应用程序发出 ConnectionWaitTimeout 异常的情况。
在捕获到 ConnectionWaitTimeout 异常的所有情况下,几乎不能恢复。
以下代码段说明了如何在 Java Platform, Enterprise Edition (Java EE) 连接器体系结构 (JCA) 中使用此异常:
/**
* This method does a simple Connection test.
*/
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 {
// lookup the connection factory
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) {
// Connection factory cannot be looked up.
throw ne;
}
// Get connection
if (verbose) System.out.println("Get the connection...");
conn = factory.getConnection();
// Get ConnectionMetaData
metaData = conn.getMetaData();
// Print out the metadata Information.
System.out.println("EISProductName" is + metaData.getEISProductName());
}
catch (com.ibm.websphere.ce.j2c.ConnectionWaitTimeoutException cwtoe) {
// Connection Wait Timeout
throw cwtoe;
}
catch (javax.resource.ResourceException re) {
// Something wrong with connections.
throw re;
}
finally {
if (conn != null) {
try {
conn.close();
}
catch (javax.resource.ResourceException re) {
}
}
}
}
映示例:处理数据访问异常 - 在 DataStoreHelper 中的映射错误
应用程序服务器提供了一个 DataStoreHelper 接口,用于将不同的数据库 SQL 错误代码映射至应用程序服务器中的相应异常。
由于各个数据库供应商可能使用不同的 SQL 错误和代码来表示同一问题,所以有必要实施错误映射。例如,失效的连接异常在不同的数据库中有不同的代码。DB2 SQLCODE 1015、1034 和 1036 等表明由于临时性的数据库问题使连接不再可用。Oracle SQLCODE 28、3113 和 3114 等等表明同一情况。
将这些错误代码映射至标准异常可提供一致性,从而使得应用程序可以在所安装的不同应用程序服务器之间移植。以下代码段说明了如何将两个错误代码添加到错误映射中: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);
...
}
}
称为“错误检测模型”的配置选项可以控制错误映射的使用方式。在 V6 和更早版本中,只有“异常映射”选项可用于“错误检测模型”。在 V7 和更高版本中,还可以使用名为“异常检查”的另一个选项。在“异常映射模型”下,应用程序服务器会查阅错误映射,并且会将异常替换为错误映射中列出的相应异常类型。在“异常检查模型”下,应用程序服务器仍会出于检查异常的目的而查阅错误映射,但不会替换异常。如果您想要继续使用“异常映射”,那么不需要进行任何更改。“异常映射”是缺省的“错误检测模型”。如果您想要使用“异常检查模型”,请参阅相关链接中的以下主题:更改“错误检测模型”以使用“异常检查模型”。
数据库死锁和外键冲突
重复出现某些 SQL 错误消息表明存在问题(例如,数据库引用完整性违例),可以使用容器管理的持久性 (CMP) 序列分组功能来防止发生这些问题。
由于违反数据库引用完整性,外键冲突导致异常数据库引用完整性 (RI) 策略规定如何将数据写到数据库表和从中删除以维护相关一致性的规则。但是,管理 Bean 持久性的运行时需求可能导致 Enterprise JavaBeans (EJB) 应用程序违反 RI 规则,这可能会导致数据库异常。
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.
或A 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.
要防止这些异常发生,必须通过为 bean 定义序列组来指定实体 bean 更新关系数据库表的顺序。
因乐观并发控制模式引起的死锁导致的异常另外,序列分组可以使为乐观并发控制配置的实体 bean 的事务回滚异常的发生降至最低。乐观并发控制规定持有数据库锁定的时间最短,以使最大事务数同时访问数据。在可用性这么高的数据库中,并发事务可以尝试锁定同一表行并创建死锁。所导致的异常可能生成类似于以下内容(在运行 DB2 的环境中产生)的消息:
Unsuccessful execution caused by deadlock or timeout.
使用序列分组功能对 bean 持久性进行排序,这样发生数据库死锁的可能性就会降低。