Найти, если SQLException было выброшено из-за дубликата - PullRequest
11 голосов
/ 07 апреля 2009

У меня есть Java-программа, которая не зависит от базы данных, и мне нужно знать при вставке, было ли выброшено исключение SQLException из-за дублирующего ключа.

Если бы я использовал один драйвер базы данных, я бы просто использовал ErrorCode, но, поскольку я могу использовать очень разные движки, ErrorCode не совпадает.

Кто-нибудь делал это раньше? Есть идеи?

Много ТИА!

Редактировать: У меня есть файл конфигурации, в котором я храню класс драйвера (например: org.apache.derby.jdbc.ClientDriver) и некоторую другую необходимую информацию (например, имя пользователя, пароль, URL-адрес .. .). Соединение всегда передается как «java.SQL.Connection», поэтому мне все равно, какие драйверы используются.

Ответы [ 8 ]

9 голосов
/ 08 апреля 2009

Это именно то, для чего предназначен SQLException.getSQLState (). Согласно Google, «23000» указывает на уникальное нарушение ограничения, по крайней мере, MySQL , PostgreSQL и Oracle .

7 голосов
/ 07 апреля 2009

С базовым JDBC, на самом деле нет способа сделать то, что вы говорите, в кросс-базе данных. Как вы упомянули, можно использовать getErrorCode , но требуются коды ошибок, специфичные для поставщика.

Я вижу только три способа обойти это:

  1. Используйте какую-то платформу, которая выполняет весь перевод кода ошибки в значимые исключения (Hibernate, вероятно, сделает это, кто-то еще упомянул, что Spring делает)
  2. Проверьте наличие дубликата вручную (с выбором) перед выполнением вставки. (Это не будет 100%, так как технически возможно, что кто-то мог сделать вставку после вашего запроса).
  3. После того, как вы получите исключение sql на вставке, попробуйте запросить этот идентификатор. Если вы действительно можете найти совпадение - вы можете быть уверены, что полученная вами ошибка произошла из-за дублирования первичного ключа. (Хотя вполне возможно, что было несколько проблем, и на самом деле это была не та проблема, которая была брошена).

Я бы порекомендовал написать ваш код, чтобы как можно больше избежать проблемы, а затем (если это абсолютно необходимо) использовать # 3.

2 голосов
/ 07 апреля 2009

Я думаю, что идеальным решением было бы, чтобы слой данных выдавал конкретное исключение в этом случае, возможно, подкласс SQLException для DuplicateKeyException или что-то подобное.

Если вы хотите иметь возможность обрабатывать разные исключения по-разному, то для начала вы должны выбросить разные типы исключений (или подтипы).

Я думаю, что это та область, в которой Spring Framework делает все правильно: они предоставляют очень богатую иерархию "исключений из базы данных" , которые расширяют DataAccessException с деревья типов для «восстанавливаемых исключений», «переходных исключений», «исключений целостности данных» и т. д. и т. д. Это оставляет ваш клиентский код свободным для перехвата любого (или ни одного) из типов исключений, с которыми он может обращаться или заботиться: указывает на ошибку, которая может не повториться, если вы повторно запустите транзакцию, неустранимая ошибка, или вы можете просто перехватить корневой тип.

2 голосов
/ 07 апреля 2009

Вы можете «обучить» программу при запуске (или конфигурации), вставив известный дубликат ключа и записав выданный код ошибки.

1 голос
/ 07 апреля 2009

Что ж, если вы не можете полагаться на исключение, чтобы сообщить вам, почему оно было выброшено, вы можете проверить, выполнив исключение с помощью «select count (*) из таблицы, где key = @keyfailedtoinsert;»

К сожалению, исключение не может дать вам имя таблицы и имя ключа. В некоторых случаях код Java, который вызывал вызываемый драйвер JDBC, мог никогда не иметь их, например, если вставка произошла в хранимой процедуре или как в триггере.

Итак, вы вернулись к необходимости доверять поставщику каждого драйвера JDBC.

0 голосов
/ 07 апреля 2009

Я предполагаю, что вы не используете JDBC, или это будет очень простой поиск ошибок.

Есть ли у вас другой набор классов для доступа к различным базам данных? Если это так, вы можете перехватить исключение в определенных классах базы данных и выдать свой собственный тип исключения, общий для всех типов базы данных.

0 голосов
/ 07 апреля 2009

Я что-то упустил? Если вы используете JDBC, вы должны получить исключение повторяющегося ключа, независимо от используемой БД.

Или вы спросили, как бы вы определили дубликат, ДО того, как попытались вставить?

0 голосов
/ 07 апреля 2009

Я полагаю, что простой и надежный способ - проверить, существует ли ключ перед выполнением вставки. Как вы правильно заметили, каждая база данных имеет свой собственный способ сообщения об ошибке.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...