Як зіставити поле сутності, ім’я якої є зарезервованим словом у JPA


92
@Column(name="open")

Використання діалекту sqlserver із сплячим режимом.

[SchemaUpdate] Unsuccessful: create table auth_session (id numeric(19,0) identity not null, active tinyint null, creation_date datetime not null, last_modified datetime not null, maxidle int null, maxlive int null, open tinyint null, sessionid varchar(255) not null, user_id numeric(19,0) not null, primary key (id), unique (sessionid))
[SchemaUpdate] Incorrect syntax near the keyword 'open'.

Я б очікував, що сплячий режим використовуватиме ідентифікатор лапок при створенні таблиці.

Будь-які ідеї щодо того, як з цим впоратися ... крім перейменування поля?


Див., Наприклад, hibernate.onjira.com/browse/HHH-1272
Ondra Žižka

Відповіді:


55

Була та сама проблема, але з назвою таблиці Transaction. Якщо встановити

hibernate.globally_quoted_identifiers=true

Тоді будуть вказані всі ідентифікатори бази даних.

Знайшов свою відповідь тут Спеціальний символ в назві таблиці в сплячому режимі дає помилку

І знайшов усі доступні налаштування тут https://docs.jboss.org/hibernate/orm/5.2/userguide/html_single/appendices/Configurations.html

Не вдалося знайти кращих документів для цього.

У моєму випадку настройка була у моєму файлі властивостей Spring. Як зазначалося в коментарях, це може бути і в інших конфігураційних файлах, пов'язаних зі сплячим режимом.


9
Як це не налаштування за замовчуванням?
Джош М.

SQL може стати нечитабельним, а використання ключових слів як імен - погана практика, яку не слід заохочувати. Я думаю...?
Рафієк,

1
Добре. Я віддаю перевагу втеченому зарезервованому слову як імені цілий день перед іменем, яке не відповідає
Джош М.

Так, можна сказати, що абстракція, надана Hibernate, викликає лише занепокоєння, а не те, як вона технічно реалізована. Але якщо ви також використовуєте інструменти, такі як Flyway або Liquibase, це додає складності, коли вам потрібно врахувати, що можуть бути зарезервовані слова. Це був мій досвід при міграції схем.
Рафієк

2
Для тих, хто цікавиться, де це потрібно встановити, це, мабуть, у ваших persistence.xmlпроектах JBoss.
Аддісон

138

За допомогою Hibernate як провайдера JPA 1.0 ви можете уникнути зарезервованого ключового слова, уклавши його в зворотні позначки:

@Column(name="`open`")

Це синтаксис, успадкований від Hiberate Core:

5.4. Ідентифікатори, що цитуються в SQL

Ви можете змусити Hibernate вказати ідентифікатор у згенерованому SQL, включивши ім’я таблиці або стовпця в зворотні позначки в документі зіставлення. Hibernate використовуватиме правильний стиль цитування для SQL Dialect. Зазвичай це подвійні лапки, але SQL Server використовує дужки, а MySQL використовує зворотні позначки.

<class name="LineItem" table="`Line Item`">
    <id name="id" column="`Item Id`"/><generator class="assigned"/></id>
    <property name="itemNumber" column="`Item #`"/>
    ...
</class>

У JPA 2.0 синтаксис стандартизований і стає:

@Column(name="\"open\"")

Список літератури

Пов’язані запитання


І дякую від мене. Це вирішило мою проблему. До речі - Ref зараз на: docs.jboss.org/hibernate/stable/core/manual/en-US/html/…
Стів

5
Я не розумію, чому я повинен це робити, чому Hibernate не роблять це автоматично замість мене ???
Даніель Харі,

@ DanielHári, можливо, ти вважаєш мою відповідь більш "автоматичною"?
Рафієк

1
@Rafiek: О так, це ідеальне рішення, проголошене (y).
Даніель Харі,

1
Використовувати @Column(name="[open]")набагато красивіше :)
Валід Абдалмаджед,

16

Уникнення зарезервованих ключових слів вручну

Якщо ви використовуєте JPA, ви можете врятуватись подвійними лапками:

@Column(name = "\"open\"")

Якщо ви використовуєте Hibernate рідний API, тоді ви можете уникнути їх, використовуючи зворотні посилання:

@Column(name = "`open`")

Автоматичне екранування зарезервованих ключових слів

Якщо ви хочете автоматично уникнути зарезервованих ключових слів, ви можете встановити властивість конфігурації для trueсплячого режиму hibernate.globally_quoted_identifiers:

<property
    name="hibernate.globally_quoted_identifiers"
    value="true"
/>

Формат Yaml

spring:
  jpa:
    properties:
      hibernate:
        globally_quoted_identifiers: true

Щоб дізнатися більше, перегляньте цю статтю .


15

Якщо ви використовуєте, як показано нижче, це має спрацювати

@Column(name="[order]")
private int order;

Ви просто робите це на приватному полі, а не на геттері?
Джейк Гастон,

5
це специфічно для sqlserver.
Альфредо М

11
@Column(name="\"open\"")

Це точно спрацює, така ж проблема сталася і зі мною, коли я навчався сплячому режиму.


4

Ні - змініть назву стовпця.

Це специфічно для бази даних, і ви просто не можете створити такий стовпець. Адже сплячий режим нарешті надсилає DDL до бази даних. Якщо ви не можете створити дійсний DDL з цією назвою стовпця, це означає, що сплячий режим також не може. Я не думаю, що цитування може вирішити проблему, навіть якщо ви пишете DDL.

Навіть якщо вам якось вдається уникнути назви - змініть його. Він буде працювати з цією базою даних, але не працюватиме з іншою.


Це може спрацювати. Див. Stackoverflow.com/questions/285775/… . Зачекаємо підтвердження OP.
ewernli

1
Це не специфічно для бази даних! Ви втечете від нього за допомогою `і ввімкніть сплячий режим, перекладіть його, щоб виправити стиль цитування для SQL Dialect
Даніел Кафер

2

Деякі реалізації JPA (наприклад, та, яку я використовую, DataNucleus) автоматично вводять ідентифікатор для вас, тому ви ніколи цього не отримуєте.


Так, здивований тим, що Hibernate, здавалося б, все ще не пропонує такої базової функції, враховуючи кількість випадків, коли люди потрапляють під нього (і хтось навіть підтримав вас за те, що ви наважилися згадати, що це можливо в іншому місці)
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.