Независимое от базы данных сравнение строк с JPA - PullRequest
4 голосов
/ 30 сентября 2011

Я работаю с JPA (Hibernate в качестве провайдера) и базовой базой данных MySQL.

У меня есть таблица с каждым названием улиц в Германии. Каждое название улицы имеет уникальный номер. Для одного задания мне нужно узнать номер имени. Для этого я написал JPQL-запрос, подобный следующему

"SELECT s FROM Strassencode s WHERE s.name = :name"

К сожалению, в Германии есть названия улиц, которые отличаются только маленькими и заглавными буквами, такими как «Am kleinen Feld» и «Am Kleinen Feld». Очевидно, что одно из них является грамматически неправильным, но как название улицы, оба написания разрешены, и оба имеют разное число.

Когда я отправляю свой JPQL-запрос в базу данных, я использую

query.getSingleResult();

из-за того, что каждое название улицы в таблице уникально. Но с базой данных MySQL я получу NonUniqueResultException, потому что база данных mySQL по умолчанию выполняет сравнение без учета регистра. Распространенный способ заставить MySQL написать запрос типа

SELECT 'abc' LIKE BINARY 'ABC';

, как описано в главе 11.5.1 Справочного руководства mySQL, но в JPQL нет соответствующего ключевого слова.

Моей первой попыткой было аннотировать поле name в классе с помощью

@Column(nullable = false, columnDefinition = "varbinary(128)")

В аннотации, подобной этой, база данных автоматически выполняет сравнение с учетом регистра, поскольку одна из строк является двоичной. Но когда я использую это решение, у меня возникают проблемы, когда я читаю имена из базы данных, чтобы записать их в файл, потому что такие буквы, как ä, ö, ü, интерпретируются неправильно.

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

Есть ли решение, в котором я могу настроить JPA для сравнения строк с учетом регистра без необходимости точной настройки базы данных вручную?

Ответы [ 3 ]

1 голос
/ 04 октября 2011

Похоже, что нет способа настроить JPA для решения этой проблемы. Но я обнаружил, что можно установить параметры сортировки не только на уровне таблиц, вы также можете установить их для всей базы данных, как описано в Справочном руководстве 12.1.10 CREATE DATABASE SYNTAX и 9.1.3.2. Набор символов базы данных и сопоставление

CREATE {DATABASE | SCHEMA} [IF NOT EXISTS] db_name
[create_specification] ...

create_specification:
    [DEFAULT] CHARACTER SET [=] charset_name
  | [DEFAULT] COLLATE [=] collation_name

Мне нужно было создать базу данных только с:

CREATE DATABASE db_name CHARACTER SET latin1 COLLATE latin1_general_cs;

С этим я мог бы поместить в поле name uniqueConstraint и вставить и «Am kleinen Feld», и «Am Kleinen Feld», и когда я запрашиваю один из них, я получу только один.

Однако, спасибо за помощь

1 голос
/ 30 сентября 2011

Чтобы оставаться «независимым», как вы говорите для базы данных и JPA-провайдера, я бы избегал getSingleResult () и извлекал список () и сопоставлял в памяти имя.Вероятно, вы получите более одного, но не 100 или более.

Другим способом может быть сохранение нормализованного (обрезанного до нижнего регистра) имени в новом поле.

0 голосов
/ 30 сентября 2011

Вы также пишете запрос SQL.Это похоже на обычный запрос:

Query sqlQuery = session.createSqlQuery("select * from CITY where name like binary :name').addString('name', name);

Обратите внимание, что код примерно готов.

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