Como mapear um campo de entidade cujo nome é uma palavra reservada em JPA


94
@Column(name="open")

Usando o dialeto sqlserver com 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'.

Eu esperava que o hibernate usasse o identificador entre aspas ao criar a tabela.

Alguma ideia de como lidar com isso ... além de renomear o campo?


Respostas:


55

Tive o mesmo problema, mas com um nome de tabela chamado Transaction. Se você definir

hibernate.globally_quoted_identifiers=true

Em seguida, todos os identificadores de banco de dados serão colocados entre aspas.

Encontrei minha resposta aqui Caractere especial no nome da tabela hibernação, dando erro

E encontrou todas as configurações disponíveis aqui https://docs.jboss.org/hibernate/orm/5.2/userguide/html_single/appendices/Configurations.html

Não foi possível encontrar documentos melhores para isso.

No meu caso, a configuração estava no meu arquivo de propriedades do Spring. Conforme mencionado nos comentários, ele também pode estar em outros arquivos de configuração relacionados ao hibernate.


9
Como esta não é a configuração padrão?
Josh M.

SQL pode se tornar ilegível e usar palavras-chave como nomes é uma prática ruim que não deve ser encorajada. Eu acho que...?
Rafiek

1
OK. Prefiro uma palavra reservada com escape como nome o dia todo a um nome que não se encaixa.
Josh M.

Sim, você poderia dizer que a abstração fornecida pelo Hibernate é apenas uma preocupação e não como ela é implementada tecnicamente. Mas se você também usa ferramentas como Flyway ou Liquibase, aumenta a complexidade quando você precisa considerar que pode haver palavras reservadas. Esta tem sido minha experiência ao migrar schema's.
Rafiek

2
Para aqueles que estão se perguntando onde isso precisa ser definido, provavelmente está em seus persistence.xmlprojetos do JBoss.
Addison

138

Com o Hibernate como provedor JPA 1.0, você pode escapar de uma palavra-chave reservada colocando-a entre crases:

@Column(name="`open`")

Esta é a sintaxe herdada do Hiberate Core:

5,4 Identificadores entre aspas SQL

Você pode forçar o Hibernate a citar um identificador no SQL gerado colocando o nome da tabela ou coluna entre crases no documento de mapeamento. O Hibernate usará o estilo de cotação correto para o dialeto SQL. Geralmente são aspas duplas, mas o SQL Server usa colchetes e o MySQL usa crases.

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

No JPA 2.0, a sintaxe é padronizada e se torna:

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

Referências

Perguntas relacionadas


E obrigado de minha parte. Resolveu um problema que eu tinha. btw - A referência está agora em: docs.jboss.org/hibernate/stable/core/manual/en-US/html/…
Steve

5
Eu não entendo porque eu tenho que fazer isso, porque o Hibernate não faz isso automaticamente ao invés de mim ???
Daniel Hári

@DanielHári talvez ache minha resposta mais "automática"?
Rafiek,

1
@Rafiek: Ah, sim, essa é a solução perfeita, voto positivo (y).
Daniel Hári

1
Usar @Column(name="[open]")é muito mais bonito :)
Waleed Abdalmajeed

17

Escape manual das palavras-chave reservadas

Se você estiver usando JPA, pode escapar com aspas duplas:

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

Se você estiver usando a API nativa do Hibernate, poderá escapar deles usando crases:

@Column(name = "`open`")

Escape automático de palavras-chave reservadas

Se você deseja escapar automaticamente das palavras-chave reservadas, pode definir a propriedade de configuração trueespecífica do Hibernate hibernate.globally_quoted_identifiers:

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

Formato Yaml

spring:
  jpa:
    properties:
      hibernate:
        globally_quoted_identifiers: true

Para mais detalhes, confira este artigo .


15

Se você usar como mostrado abaixo, deve funcionar

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

Você está apenas fazendo isso no campo privado, não no getter?
Jake Gaston

5
isso é específico do sqlserver.
Alfredo M

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

Isso vai funcionar com certeza, o mesmo problema aconteceu comigo, quando eu estava aprendendo a hibernar.


4

Não - altere o nome da coluna.

Isso é específico do banco de dados e você simplesmente não pode criar tal coluna. Afinal o hibernate finalmente envia DDL para o banco de dados. Se você não pode criar um DDL válido com este nome de coluna, isso significa que o hibernate também não pode. Não acho que citar resolveria o problema, mesmo se você estiver escrevendo o DDL.

Mesmo se você conseguir escapar do nome - mude-o. Ele funcionará com este banco de dados, mas não funcionará com outro.


Isso pode funcionar. Consulte stackoverflow.com/questions/285775/… . Vamos aguardar a confirmação do OP.
ewernli

1
Isso não é específico do banco de dados! Você pode escapar com um `e hibernar, traduzindo para o estilo de cotação correto para o dialeto SQL
Daniel Käfer

2

Algumas implementações JPA (por exemplo, o que eu uso, DataNucleus) citam automaticamente o identificador para você, então você nunca terá isso.


Sim, surpreso que o Hibernate aparentemente ainda não oferece um recurso tão básico, dado o número de vezes que as pessoas são atingidas por ele (e alguém até votou contra você por ousar mencionar que isso era possível em outro lugar)
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.