Найдите, если было выбрано SQLException из-за дублирования

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

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

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

Много TIA!

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

Ответ 1

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

Единственные три пути, которые я вижу, чтобы обойти это:

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

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

Ответ 2

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

Ответ 3

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

Ответ 4

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

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

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

Ответ 5

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

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

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

Ответ 6

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

Ответ 7

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

Или вы спросили, как вы определяете дуплекс, прежде чем пытаетесь вставить?

Ответ 8

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

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