Come mappare un campo entità il cui nome è una parola riservata in JPA


92
@Column(name="open")

Utilizzo del dialetto sqlserver con hibernate.

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

Mi sarei aspettato che l'ibernazione usasse l'identificatore tra virgolette durante la creazione della tabella.

Qualche idea su come gestire questo ... oltre a rinominare il campo?


Risposte:


55

Ha avuto lo stesso problema, ma con un tablename chiamato Transaction. Se imposti

hibernate.globally_quoted_identifiers=true

Quindi verranno citati tutti gli identificatori del database.

Ho trovato la mia risposta qui Carattere speciale nel nome della tabella ibernazione che dà errore

E ho trovato tutte le impostazioni disponibili qui https://docs.jboss.org/hibernate/orm/5.2/userguide/html_single/appendices/Configurations.html

Non sono riuscito a trovare documenti migliori per questo però.

Nel mio caso l'impostazione era nel file delle proprietà di Spring. Come accennato nei commenti, potrebbe anche essere in altri file di configurazione correlati all'ibernazione.


9
In che modo questa non è l'impostazione predefinita?
Josh M.

SQL potrebbe diventare illeggibile e l'utilizzo di parole chiave come nomi è una cattiva pratica che non dovrebbe essere incoraggiata. Credo...?
Rafiek

1
Va bene. Preferirò una parola riservata con escape come nome tutto il giorno su un nome che non si adatta.
Josh M.

Sì, potresti dire che l'astrazione fornita da Hibernate è solo preoccupante e non come è tecnicamente implementata. Ma se usi anche strumenti come Flyway o Liquibase, aumenta la complessità quando devi considerare che potrebbero esserci parole riservate. Questa è stata la mia esperienza durante la migrazione di schemi.
Rafiek

2
Per coloro che si chiedono dove deve essere impostato, probabilmente è nei tuoi persistence.xmlprogetti JBoss.
Addison

138

Con Hibernate come provider JPA 1.0, puoi sfuggire a una parola chiave riservata racchiudendola tra i backtick:

@Column(name="`open`")

Questa è la sintassi ereditata da Hiberate Core:

5.4. Identificatori SQL tra virgolette

È possibile forzare Hibernate a citare un identificatore nell'SQL generato racchiudendo il nome della tabella o della colonna tra i backtick nel documento di mappatura. Hibernate utilizzerà lo stile di citazione corretto per il dialetto SQL. Di solito si tratta di virgolette doppie, ma SQL Server utilizza le parentesi e MySQL utilizza i backtick.

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

In JPA 2.0, la sintassi è standardizzata e diventa:

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

Riferimenti

Domande correlate


E grazie da parte mia. Ha risolto un problema che avevo. btw - Ref è ora a: docs.jboss.org/hibernate/stable/core/manual/en-US/html/…
Steve

5
Non capisco perché devo farlo, perché Hibernate non lo fa automaticamente al posto mio ???
Daniel Hári

@ DanielHári forse trovi la mia risposta più "automatica"?
Rafiek

1
@Rafiek: Oh sì, questa è la soluzione perfetta, votato in su (y).
Daniel Hári

1
L'uso @Column(name="[open]")è molto più
carino

16

Esecuzione manuale dell'escape delle parole chiave riservate

Se utilizzi JPA, puoi eseguire l'escape con virgolette doppie:

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

Se stai usando l'API nativa di Hibernate, puoi sfuggirle usando i backtick:

@Column(name = "`open`")

Escape automatico delle parole chiave riservate

Se desideri sfuggire automaticamente alle parole chiave riservate, puoi impostare truela hibernate.globally_quoted_identifiersproprietà di configurazione specifica di Hibernate :

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

Formato Yaml

spring:
  jpa:
    properties:
      hibernate:
        globally_quoted_identifiers: true

Per maggiori dettagli, consulta questo articolo .


15

Se usi come mostrato sotto dovrebbe funzionare

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

Lo stai solo facendo in campo privato, non nel getter?
Jake Gaston

5
questo è specifico di sqlserver.
Alfredo M

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

Questo funzionerà di sicuro, lo stesso problema è accaduto con me, quando stavo imparando l'ibernazione.


4

No, cambia il nome della colonna.

Questo è specifico del database e non puoi creare una colonna del genere. Dopo tutto, l'ibernazione invia finalmente DDL al database. Se non puoi creare un DDL valido con questo nome di colonna, significa che anche l'ibernazione non può farlo. Non credo che la citazione risolva il problema anche se stai scrivendo il DDL.

Anche se in qualche modo riesci a sfuggire al nome, cambialo. Funzionerà con questo database, ma non con un altro.


Questo può funzionare. Vedi stackoverflow.com/questions/285775/… . Aspettiamo la conferma dell'OP.
ewernli

1
Questo non è specifico del database! Esci con un `e ibernato traducilo nello stile di citazione corretto per il dialetto SQL
Daniel Käfer,

2

Alcune implementazioni JPA (ad esempio quella che uso, DataNucleus) citano automaticamente l'identificatore per te, quindi non lo ottieni mai.


Sì, sorpreso dal fatto che Hibernate apparentemente non offra ancora una funzionalità così basilare dato il numero di volte in cui le persone ne vengono colpite (e qualcuno ti ha persino svalutato per aver osato menzionare che questo era possibile altrove)
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.