Comment mapper un champ d'entité dont le nom est un mot réservé dans JPA

92
@Column(name="open")

Utilisation du dialecte sqlserver avec 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'.

Je me serais attendu à ce que hibernate utilise l'identifiant cité lors de la création de la table.

Des idées sur la façon de gérer cela ... autre que de renommer le champ?

TJR
la source
Voir par exemple hibernate.onjira.com/browse/HHH-1272
Ondra Žižka

Réponses:

55

Eu le même problème, mais avec un nom de table appelé Transaction. Si vous définissez

hibernate.globally_quoted_identifiers=true

Ensuite, tous les identificateurs de base de données seront cités.

J'ai trouvé ma réponse ici Caractère spécial dans le nom de la table hibernation donnant une erreur

Et trouvé tous les paramètres disponibles ici https://docs.jboss.org/hibernate/orm/5.2/userguide/html_single/appendices/Configurations.html

Impossible de trouver de meilleurs documents pour cela.

Dans mon cas, le paramètre était dans mon fichier de propriétés Spring. Comme mentionné dans les commentaires, il pourrait également être dans d'autres fichiers de configuration liés à la mise en veille prolongée.

Rafiek
la source
9
En quoi n'est-ce pas le paramètre par défaut?
Josh M.
SQL peut devenir illisible et l'utilisation de mots-clés comme noms est une mauvaise pratique qui ne doit pas être encouragée. Je pense...?
Rafiek
1
D'accord. Je préfère un mot réservé échappé comme nom toute la journée à un nom qui ne rentre pas.
Josh M.
Oui, vous pourriez dire que l'abstraction fournie par Hibernate ne concerne que la façon dont elle est techniquement implémentée. Mais si vous utilisez également des outils tels que Flyway ou Liquibase, cela ajoute à la complexité lorsque vous devez considérer qu'il peut y avoir des mots réservés. Cela a été mon expérience lors de la migration de schémas.
Rafiek
2
Pour ceux qui se demandent où cela doit être défini, c'est probablement dans vos persistence.xmlprojets JBoss.
Addison le
138

Avec Hibernate en tant que fournisseur JPA 1.0, vous pouvez échapper à un mot-clé réservé en l'enfermant dans des backticks:

@Column(name="`open`")

Voici la syntaxe héritée d'Hiberate Core:

5.4. Identificateurs entre guillemets SQL

Vous pouvez forcer Hibernate à citer un identifiant dans le SQL généré en plaçant le nom de la table ou de la colonne entre des crochets inverses dans le document de mappage. Hibernate utilisera le style de citation correct pour le dialecte SQL. Il s'agit généralement de guillemets doubles, mais SQL Server utilise des crochets et MySQL utilise des backticks.

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

En JPA 2.0, la syntaxe est standardisée et devient:

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

Références

Questions connexes

Pascal Thivent
la source
Et merci de ma part. Cela a résolu un problème que j'avais. btw - La référence est maintenant sur: docs.jboss.org/hibernate/stable/core/manual/en-US/html/…
Steve
5
Je ne comprends pas pourquoi je dois faire ça, pourquoi Hibernate ne le fait pas automatiquement à ma place ???
Daniel Hári
@ DanielHári peut-être trouvez-vous ma réponse plus "automatique"?
Rafiek
1
@Rafiek: Oh oui, c'est la solution parfaite, voté pour (y).
Daniel Hári
1
L'utilisation @Column(name="[open]")est beaucoup plus jolie :)
Waleed Abdalmajeed
16

Échappement manuel des mots-clés réservés

Si vous utilisez JPA, vous pouvez échapper avec des guillemets doubles:

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

Si vous utilisez l'API native Hibernate, vous pouvez les échapper en utilisant des backticks:

@Column(name = "`open`")

Échapper automatiquement les mots-clés réservés

Si vous souhaitez échapper automatiquement aux mots-clés réservés, vous pouvez définir truela hibernate.globally_quoted_identifierspropriété de configuration spécifique à Hibernate :

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

Format Yaml

spring:
  jpa:
    properties:
      hibernate:
        globally_quoted_identifiers: true

Pour plus de détails, consultez cet article .

Vlad Mihalcea
la source
15

Si vous utilisez comme indiqué ci-dessous, cela devrait fonctionner

@Column(name="[order]")
private int order;
Raman
la source
Vous faites juste ça sur le terrain privé et non sur le getter?
Jake Gaston
5
c'est spécifique à sqlserver.
Alfredo M
11
@Column(name="\"open\"")

Cela fonctionnera à coup sûr, le même problème s'est produit avec moi lorsque j'apprenais à mettre en veille prolongée.

wmnitin
la source
4

Non - changez le nom de la colonne.

Ceci est spécifique à la base de données et vous ne pouvez tout simplement pas créer une telle colonne. Après tout, hibernate envoie enfin DDL à la base de données. Si vous ne pouvez pas créer de DDL valide avec ce nom de colonne, cela signifie que la mise en veille prolongée ne le peut pas non plus. Je ne pense pas que les citations résoudraient le problème même si vous écrivez le DDL.

Même si vous réussissez à échapper au nom, changez-le. Cela fonctionnera avec cette base de données, mais ne fonctionnera pas avec une autre.

Bozho
la source
Cela peut fonctionner. Voir stackoverflow.com/questions/285775/… . Attendons la confirmation de l'OP.
ewernli
1
Ce n'est pas spécifique à la base de données! Vous y échappez avec un `et hibernate le traduisez en un style de citation correct pour le dialecte SQL
Daniel Käfer
2

Certaines implémentations JPA (par exemple celle que j'utilise, DataNucleus) citent automatiquement l'identifiant pour vous, donc vous ne l'obtiendrez jamais.

Neil Stockton
la source
Oui, surpris qu'Hibernate n'offre apparemment toujours pas une fonctionnalité aussi basique étant donné le nombre de fois où les gens sont frappés par elle (et quelqu'un vous a même refusé d'avoir osé mentionner que c'était possible ailleurs)