Jak zmapować pole encji, którego nazwa jest słowem zastrzeżonym w JPA

92
@Column(name="open")

Używanie dialektu sqlserver z hibernacją.

[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'.

Spodziewałbym się, że hibernacja użyje identyfikatora w cudzysłowie podczas tworzenia tabeli.

Jakieś pomysły, jak sobie z tym poradzić ... inne niż zmiana nazwy pola?

TJR
źródło
Zobacz np. Hibernate.onjira.com/browse/HHH-1272
Ondra Žižka

Odpowiedzi:

55

Miałem ten sam problem, ale z nazwą tabeli o nazwie Transaction. Jeśli ustawisz

hibernate.globally_quoted_identifiers=true

Następnie wszystkie identyfikatory bazy danych zostaną zacytowane.

Znalazłem moją odpowiedź tutaj Znak specjalny w nazwie tabeli hibernuje, dając błąd

Wszystkie dostępne ustawienia znalazłem tutaj https://docs.jboss.org/hibernate/orm/5.2/userguide/html_single/appendices/Configurations.html

Nie mogłem jednak znaleźć lepszych dokumentów do tego.

W moim przypadku ustawienie było w moim pliku właściwości Spring. Jak wspomniano w komentarzach, może on również znajdować się w innych plikach konfiguracyjnych związanych z hibernacją.

Rafiek
źródło
9
Dlaczego nie jest to ustawienie domyślne?
Josh M.
SQL może stać się nieczytelny, a używanie słów kluczowych jako nazw jest złą praktyką, której nie należy zachęcać. Myślę...?
Rafiek
1
W porządku. Wolę słowo zastrzeżone ze ucieczką jako nazwę przez cały dzień od nazwy, która nie pasuje.
Josh M.
Tak, można by powiedzieć, że abstrakcja dostarczana przez Hibernate jest ważna, a nie jak jest technicznie zaimplementowana. Ale jeśli używasz również narzędzi takich jak Flyway lub Liquibase, zwiększa to złożoność, gdy musisz wziąć pod uwagę, że mogą być zarezerwowane słowa. Takie było moje doświadczenie podczas migracji schematów.
Rafiek
2
Dla tych, którzy zastanawiają się, gdzie należy to ustawić, prawdopodobnie jest to w Twoich persistence.xmlprojektach JBoss.
Addison,
138

Z Hibernate jako dostawcą JPA 1.0, możesz ominąć zarezerwowane słowo kluczowe, umieszczając je między znakami odwrotnymi:

@Column(name="`open`")

Oto składnia odziedziczona po Hiberate Core:

5.4. Identyfikatory w cudzysłowie SQL

Możesz zmusić Hibernate do cytowania identyfikatora w wygenerowanym kodzie SQL poprzez umieszczenie nazwy tabeli lub kolumny w odwrotnych apostrofach w dokumencie mapowania. Hibernate użyje poprawnego stylu cytowania dla dialektu SQL. Zwykle są to cudzysłowy, ale SQL Server używa nawiasów, a MySQL używa odwrotnych apostrofów.

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

W JPA 2.0 składnia jest ustandaryzowana i wygląda następująco:

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

Bibliografia

Powiązane pytania

Pascal Thivent
źródło
Dziękuję ode mnie. To rozwiązało problem, który miałem. btw - Ref jest teraz pod adresem: docs.jboss.org/hibernate/stable/core/manual/en-US/html/…
Steve,
5
Nie rozumiem, dlaczego muszę to robić, dlaczego Hibernate nie robi tego automatycznie zamiast mnie ???
Daniel Hári
@ DanielHári może uważasz, że moja odpowiedź jest bardziej „automatyczna”?
Rafiek
1
@Rafiek: O tak, to idealne rozwiązanie, przegłosowano (y).
Daniel Hári
1
Używanie @Column(name="[open]")jest o wiele ładniejsze :)
Waleed Abdalmajeed
16

Ręczna zmiana znaczenia zarezerwowanych słów kluczowych

Jeśli korzystasz z JPA, możesz uciec za pomocą podwójnych cudzysłowów:

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

Jeśli korzystasz z natywnego interfejsu API Hibernate, możesz uciec przed nimi za pomocą odwrotnych znaków:

@Column(name = "`open`")

Automatyczna zmiana znaczenia zarezerwowanych słów kluczowych

Jeśli chcesz automatycznie uniknąć zarezerwowanych słów kluczowych, możesz ustawić właściwość konfiguracyjną truespecyficzną dla Hibernate hibernate.globally_quoted_identifiers:

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

Format Yaml

spring:
  jpa:
    properties:
      hibernate:
        globally_quoted_identifiers: true

Więcej informacji znajdziesz w tym artykule .

Vlad Mihalcea
źródło
15

Jeśli używasz jak pokazano poniżej, powinno działać

@Column(name="[order]")
private int order;
Ramana
źródło
Robisz to na prywatnym polu, a nie na getterze?
Jake Gaston
5
jest to specyficzne dla sqlserver.
Alfredo M
11
@Column(name="\"open\"")

To na pewno zadziała, ten sam problem zdarzył się ze mną, kiedy uczyłem się hibernacji.

wmnitin
źródło
4

Nie - zmień nazwę kolumny.

Jest to specyficzne dla bazy danych i po prostu nie możesz utworzyć takiej kolumny. Po hibernacji ostatecznie wysyła DDL do bazy danych. Jeśli nie możesz utworzyć prawidłowego DDL z tą nazwą kolumny, oznacza to, że hibernacja również nie może. Nie sądzę, aby cytowanie rozwiązało problem, nawet jeśli piszesz DDL.

Nawet jeśli jakoś uda ci się uciec od nazwy - zmień ją. Będzie działać z tą bazą danych, ale nie będzie działać z inną.

Bozho
źródło
To może zadziałać. Zobacz stackoverflow.com/questions/285775/… . Poczekajmy na potwierdzenie OP.
ewernli
1
To nie jest specyficzne dla bazy danych! Uciekasz przed tym przez `i hibernuj, tłumacząc to na poprawny styl cytowania dla dialektu SQL
Daniel Käfer
2

Niektóre implementacje JPA (np. Ta, której używam, DataNucleus) automatycznie cytują dla Ciebie identyfikator, więc nigdy go nie otrzymasz.

Neil Stockton
źródło
Tak, zdziwiony, że Hibernate nadal nie oferuje tak podstawowej funkcji, biorąc pod uwagę, ile razy ludzie są przez nią trafieni (a ktoś nawet cię przegłosował za to, że odważył się wspomnieć, że było to możliwe gdzie indziej)