Cómo mapear un campo de entidad cuyo nombre es una palabra reservada en JPA

92
@Column(name="open")

Usando dialecto 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'.

Hubiera esperado que hibernate usara un identificador entre comillas al crear la tabla.

¿Alguna idea sobre cómo manejar esto ... además de cambiar el nombre del campo?

TJR
fuente
Ver, por ejemplo, hibernate.onjira.com/browse/HHH-1272
Ondra Žižka

Respuestas:

55

Tuve el mismo problema, pero con un nombre de tabla llamado Transaction. Si pones

hibernate.globally_quoted_identifiers=true

Entonces se citarán todos los identificadores de la base de datos.

Encontré mi respuesta aquí Carácter especial en el nombre de la tabla hibernación dando error

Y encontré todas las configuraciones disponibles aquí https://docs.jboss.org/hibernate/orm/5.2/userguide/html_single/appendices/Configurations.html

Sin embargo, no se pudieron encontrar mejores documentos para esto.

En mi caso, la configuración estaba en mi archivo de propiedades de Spring. Como se menciona en los comentarios, también podría estar en otros archivos de configuración relacionados con la hibernación.

Rafiek
fuente
9
¿Cómo no es esta la configuración predeterminada?
Josh M.
SQL puede volverse ilegible y el uso de palabras clave como nombres es una mala práctica que no debe fomentarse. Yo creo que...?
Rafiek
1
Bueno. Preferiré una palabra reservada escapada como nombre durante todo el día a un nombre que no encaja.
Josh M.
Sí, se podría decir que la abstracción proporcionada por Hibernate es solo de interés y no cómo se implementa técnicamente. Pero si también usa herramientas como Flyway o Liquibase, entonces aumenta la complejidad cuando necesita considerar que puede haber palabras reservadas. Esta ha sido mi experiencia al migrar el esquema.
Rafiek
2
Para aquellos que se preguntan dónde debe establecerse esto, probablemente esté en sus persistence.xmlproyectos de JBoss.
Addison
138

Con Hibernate como proveedor de JPA 1.0, puede escapar de una palabra clave reservada encerrándola entre comillas invertidas:

@Column(name="`open`")

Esta es la sintaxis heredada de Hiberate Core:

5.4. Identificadores entre comillas SQL

Puede forzar a Hibernate a citar un identificador en el SQL generado al incluir el nombre de la tabla o columna entre comillas invertidas en el documento de mapeo. Hibernate utilizará el estilo de cita correcto para el dialecto SQL. Suelen ser comillas dobles, pero SQL Server usa corchetes y MySQL usa comillas invertidas.

<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 sintaxis está estandarizada y se convierte en:

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

Referencias

Preguntas relacionadas

Pascal Thivent
fuente
Y gracias de mi parte. Resolvió un problema que tenía. por cierto - La referencia está ahora en: docs.jboss.org/hibernate/stable/core/manual/en-US/html/…
Steve
5
No entiendo por qué tengo que hacer esto, ¿por qué Hibernate no lo hace automáticamente en mi lugar?
Daniel Hári
@ DanielHári ¿quizás encuentres mi respuesta más "automática"?
Rafiek
1
@Rafiek: Oh, sí, esa es la solución perfecta, votó a favor (y).
Daniel Hári
1
Usar @Column(name="[open]")es mucho más bonito :)
Waleed Abdalmajeed
16

Escapando manualmente de las palabras clave reservadas

Si está utilizando JPA, puede escapar con comillas dobles:

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

Si está utilizando la API nativa de Hibernate, puede escapar de ellos usando comillas invertidas:

@Column(name = "`open`")

Escapar automáticamente las palabras clave reservadas

Si desea escapar automáticamente de las palabras clave reservadas, puede establecer truela hibernate.globally_quoted_identifierspropiedad de configuración específica de Hibernate :

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

Formato Yaml

spring:
  jpa:
    properties:
      hibernate:
        globally_quoted_identifiers: true

Para obtener más detalles, consulte este artículo .

Vlad Mihalcea
fuente
15

Si usa como se muestra a continuación, debería funcionar

@Column(name="[order]")
private int order;
Raman
fuente
¿Estás haciendo esto en el campo privado, no en el getter?
Jake Gaston
5
esto es específico de sqlserver.
Alfredo M
11
@Column(name="\"open\"")

Esto funcionará con seguridad. El mismo problema sucedió conmigo, cuando estaba aprendiendo a hibernar.

wmnitin
fuente
4

No, cambie el nombre de la columna.

Esto es específico de la base de datos y simplemente no puede crear una columna de este tipo. Después de todo, hibernate finalmente envía DDL a la base de datos. Si no puede crear un DDL válido con este nombre de columna, esto significa que hibernar tampoco puede hacerlo. No creo que las citas resuelvan el problema incluso si estás escribiendo el DDL.

Incluso si de alguna manera logras escapar del nombre, cámbialo. Funcionará con esta base de datos, pero no funcionará con otra.

Bozho
fuente
Eso puede funcionar. Consulte stackoverflow.com/questions/285775/… . Esperemos la confirmación del OP.
ewernli
1
¡Esto no es específico de la base de datos! Se escapa con un `e hibernar, traducirlo al estilo de cita correcto para el dialecto SQL
Daniel Käfer
2

Algunas implementaciones de JPA (por ejemplo, la que yo uso, DataNucleus) citan automáticamente el identificador por ti, por lo que nunca obtienes esto.

Neil Stockton
fuente
Sí, sorprendió que Hibernate aparentemente todavía no ofrece una característica básica dado el número de veces que la gente se lo hicieran por (y alguien incluso le downvoted por haberse atrevido a mencionar que esto era posible en otros lugares)