Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Metodichka_Po_Tp.doc
Скачиваний:
0
Добавлен:
01.07.2025
Размер:
1.44 Mб
Скачать

2. Обработка исключений jdbc

Обработка исключений была опущена в предыдущих примерах, поскольку этот вопрос требует отдельного рассмотрения. Почти всякий вызов интерфейса JDBC, который выполняется в приложении, способен активизировать исключение, и поэтому он должен быть заключен в блок try. В интерфейсе JDBC определены три исключения в иерархической взаимосвязи. Эта иерархия сверху вниз выглядит следующим образом:

SQLException

SQLWarning

DataTruncation

Исключение SQLException активизируется методами интерфейса JDBC в том случае, если в базе данных возникает ошибка. Существует ряд методов, которые могут быть вызваны для выборки информации об ошибке:

  • Метод int getErrorCodeO возвращает код ошибки конкретной базы данных

  • Метод String getSQLState() возвращает состояние X/Open SQLState, связанное с ошибкой

  • Метод String getMessage() наследуется из класса java.lang.Exception (возвращает описание ошибки)

Исключения JDBC могут быть связаны в цепочку, поэтому, если во время выполнения одной операции возникает более одной ошибки, информация обо всех ошибках сохраняется. Метод getNextException() возвращает ссылку на следующее исключение в цепочке или пустое значение, если исключений больше нет.

SQLWarning представляет собой такое исключение, которое не активизируется, но связывается в цепочку с конкретным объектом ResultSet или объектом оператора, к которому оно применяется. Как и в случае с исключениями SQLException, в цепочку может быть связано более одного исключения SQLWarning. Метод getNextWarning() класса SQLWarning возвращает следующее предупреждение в цепочке или пустое значение, если предупреждений больше нет. Например, при обработке результирующего набора в приложении наличие предупреждений можно проверить с помощью метода getWarnings() следующим образом:

java.sql.SQLWarning warn=rset.getWarnings();

while(warn!=null)

{

// сделать что-нибудь с предупреждением

. . . . .. . . . .

warn=warn.getNextWarning();

}

Исключение DataTruncation является особым случаем исключения SQLWarning, которое применяется к значениям столбцов и параметров. Исключение DataTruncation может быть связано в цепочку с объектом результирующего набора, однако оно активизируется при его применении к объекту оператора. Оно предоставляет дополнительные методы определения индекса столбца или параметра, к которому оно применяется, фактической и ожидаемой длины и т.д. При связывании исключения DataTruncation в цепочку с результирующим набором отличить его от других предупреждений можно на основании значения "01004" его состояния SQLState. Приведенный выше фрагмент кода можно расширить для проверки усечения данных:

int colNum, javaLen, dbLen;

java.sql.SQLWarning warn=rset.getWarnings();

while(warn!=null)

{

if(warn.getSQLState()=="01004")

{

colName=((DataTruncation)warn).getIndex();

javaLen=((DataTruncation)warn).getTransferSize();

dbLen=((DataTruncation)warn).getDataSize();

// сделать что-нибудь с этой информацией

. . . . .. . . . .

}

else

{

// это другое исключение java.sql.SQLWarning

. . . . .. . . . .

}

warn=warn.getNextWarning();

}

Методы getTransferSize() и getDataSize() применяются к длине столбца или параметра интерфейса JDBC, а также столбца или параметра базы данных. Исключение DataTruncation, скорее всего, будет активизировано тогда, когда значение параметра в результате окажется слишком длинным. В этом случае оно не связывается в цепочку в виде предупреждения, но активизируется в виде исключения, которое должно быть перехвачено:

int parmName, javaLen, dbLen;

try

{

cstmt.executeUpdate();

}

catch(SQLException e)

{

while(e!=null)

{

if(e.getSQLState()=="01004")

{

parmName=((DataTruncation)warn).getIndex();

javaLen=((DataTruncation)warn).getTransferSize();

dbLen=((DataTruncation)warn).getDataSize();

// сделать что-нибудь с этой информацией

. . . . .. . . . .

}

else

{

// это другое исключение SQLException

. . . . .. . . . .

}

e=e.getNextWarning();

}

}

Исключение DataTruncation может быть перехвачено как исключение SQLException, поскольку оно происходит от исключения SQLException. А когда оно перехватывается как исключение SQLException, то последнее необходимо явно привести к исключению DataTruncation, прежде чем получить доступ к методам этого интерфейса.

Обработка перехваченного исключения SQLException в значительной степени зависит от конкретных потребностей приложения. В некоторых случаях может оказаться полезной просто повторная активизация перехваченного исключения или активизация исключения специально для конкретного приложения, чтобы его можно было обработать на более высоком уровне. При активизации исключения из блока catch следует рассмотреть ряд вопросов. Для тех читателей, которые знакомы с языком Java, очевидным является первое положение: активизация исключений из вложенных блоков try — далеко не самая удачная идея. Рассмотрим следующий пример, в котором активизируется исключение, являющееся расширением класса java.lang.Exception и определенное в приложении как DBException:

try

{

// некоторые операции получения объектов Java, присвоения значений и т.д.

. . . . . . . . . . .

try

{

// некоторые вызовы интерфейса JDBC

}

catch(SQLException sqle)

{

// выполнить очистку и активизировать исключение, чтобы его можно было активизировать на более высоком уровне

. . . . . . .

throw new DBException(sqle.getMessage(),sqle.getErrorCode());

}

}

catch(java.lang.Exception e)

{

// выполнить что-нибудь

. . . . . . .

}

Новое исключение DBException, активизированное из внутреннего блока, перехватывается во внешнем блоке, поскольку исключение DBException является потомком класса java.lang.Exception. Добиться требуемого результата можно с помощью нескольких перехватов для внешнего блока try:

try

{

// некоторые операции получения объектов Java, присвоения значений и т.д.

// некоторые вызовы интерфейса JDBC

. . . . . . . . . . .

}

catch(SQLException sqle)

{

// выполнить очистку и активизировать исключение, чтобы его можно было активизировать на более высоком уровне

. . . . . . .

throw new DBException(sqle.getMessage(),sqle.getErrorCode());

}

catch(java.lang.Exception e)

{

// выполнить что-нибудь

. . . . . . .

}

Исключения должны перехватываться от низшего к высшему уровню иерархии. Если исключение java.lang.Exception перехватывается до исключения DBException, то блок DBException не будет достигнут. В предыдущем примере информация из первого перехваченного исключения SQLException копируется в новое исключение DBException. Если же несколько исключений связываются в цепочку, тогда эта информация не сохраняется. Цепочка может быть сохранена в том случае, если исключение DBException расширяет класс java.lang.Exception с помощью метода SetNextException():

catch(Exception sqle)

{

DBException first=new DBException(sqle.getMessage(),sqle.getErrorCode());

sqle=sqle.getNextException();

while(sqle!=null)

{

first.setNextException(sqle);

}

throw first;

}

Для перехвата исключения SQLException нередко требуются дополнительные действия, особенно в контексте транзакции. Допустим, что в приложении определен метод, который выполняет вставку строки в три отдельные таблицы в течение одной транзакции. Если при этом любая из операций вставки потерпит неудачу, должен быть осуществлен откат всей транзакции. В этом случае следует выдать команду отката в обработчике исключений. Это лишь один простой пример множества ситуаций, в которых исключение SQLException требует выполнения очистки. Следует иметь в виду, что в результате вызовов интерфейса JDBC распределяются внешние ресурсы и изменяется состояние базы данных, и поэтому обработчики исключений нужно проектировать соответствующим образом.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]