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?

TJR
fonte
Veja, por exemplo, hibernate.onjira.com/browse/HHH-1272
Ondra Žižka

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.

Rafiek
fonte
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

Pascal Thivent
fonte
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 .

Vlad Mihalcea
fonte
15

Se você usar como mostrado abaixo, deve funcionar

@Column(name="[order]")
private int order;
Raman
fonte
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.

wmnitin
fonte
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.

Bozho
fonte
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.

Neil Stockton
fonte
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)