名前がJPAの予約語であるエンティティフィールドをマップする方法


92
@Column(name="open")

Hibernateでsqlserverダイアレクトを使用する。

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

テーブルを作成するときに、hibernateが引用符で囲まれた識別子を使用することを期待していました。

これを処理する方法についてのアイデアはありますか...フィールドの名前を変更する以外に?


回答:


55

同じ問題がありましたが、テーブル名がTransaction。でした。設定した場合

hibernate.globally_quoted_identifiers=true

次に、すべてのデータベース識別子が引用されます。

ここで私の答えが見つかりまし たテーブル名hibernateの特殊文字がエラーを出します

そして、ここで利用可能なすべての設定を見つけました https://docs.jboss.org/hibernate/orm/5.2/userguide/html_single/appendices/Configurations.html

しかし、これに適したドキュメントは見つかりませんでした。

私の場合、設定はSpringプロパティファイルにありました。コメントで述べたように、それは他の休止状態に関連する構成ファイルにもある可能性があります。


9
これはどのようにデフォルト設定ではありませんか?
ジョシュ・M.

SQLが読み取れなくなる可能性があり、名前としてキーワードを使用することは推奨されるべきではない悪い習慣です。おもう...?
Rafiek

1
はい。収まらない名前よりも、エスケープされた予約語を1日中名前として使用することをお勧めします。
ジョシュM.

はい、Hibernateによって提供される抽象化は問題であり、技術的にどのように実装されているかではないと言えます。ただし、FlywayやLiquibaseなどのツールも使用している場合は、予約語がある可能性があることを考慮する必要があると、複雑さが増します。これは、スキーマを移行するときの私の経験です。
Rafiek

2
これをどこに設定する必要があるのか​​疑問に思っている人にとっては、おそらくpersistence.xmlJBossプロジェクトにあります。
アディソン

138

JPA 1.0プロバイダーとしてHibernateを使用すると、予約済みキーワードをバッククォートで囲むことでエスケープできます。

@Column(name="`open`")

これは、HiberateCoreから継承された構文です。

5.4。SQL引用識別子

マッピングドキュメントのバッククォートでテーブルまたは列の名前を囲むことにより、Hibernateに生成されたSQLの識別子を引用させることができます。HibernateはSQLダイアレクトに正しい引用スタイルを使用します。これは通常二重引用符ですが、SQL Serverは角かっこを使用し、MySQLはバッククォートを使用します。

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

JPA 2.0では、構文は標準化され、次のようになります。

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

参考文献

  • Hibernateリファレンスガイド
  • JPA2.0仕様
    • 2.13データベースオブジェクトの命名

関連する質問


そして私から感謝します。それは私が持っていた問題を解決しました。-ところでRefがで以下のようになります。docs.jboss.org/hibernate/stable/core/manual/en-US/html/...
スティーブ・

5
なぜ私がこれをしなければならないのか、なぜHibernateが私の代わりにこれを自動的に行わないのか理解できませんか?
ダニエルハリ2016年

@DanielHári多分あなたは私の答えをもっと「自動」だと思いますか?
Rafiek 2018

1
@Rafiek:そうそう、それは完璧な解決策であり、賛成です(y)。
ダニエルハリ

1
使用@Column(name="[open]")ははるかにきれいです:)
Waleed Abdalmajeed 2018年

16

予約されたキーワードを手動でエスケープする

JPAを使用している場合は、二重引用符でエスケープできます。

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

HibernateネイティブAPIを使用している場合は、バッククォートを使用してそれらをエスケープできます。

@Column(name = "`open`")

予約されたキーワードを自動的にエスケープする

予約済みのキーワードを自動的にエスケープする場合はtrue、Hibernate固有のhibernate.globally_quoted_identifiers構成プロパティに設定できます。

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

Yaml形式

spring:
  jpa:
    properties:
      hibernate:
        globally_quoted_identifiers: true

詳細については、この記事をご覧ください。


15

以下に示すように使用すると、機能するはずです

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

ゲッターではなくプライベートフィールドでこれを行っているだけですか?
ジェイクガストン

5
これはSQLServer固有です。
アルフレド

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

これは確かに機能します。休止状態を学習していたときに、同じ問題が発生しました。


4

いいえ-列名を変更します。

これはデータベース固有であり、そのような列を作成することはできません。結局、休止状態は最終的にDDLをデータベースに送信します。この列名で有効なDDLを作成できない場合、これは休止状態も作成できないことを意味します。DDLを書いていても、引用しても問題が解決するとは思いません。

どういうわけか名前をエスケープすることに成功したとしても、名前を変更してください。このデータベースでは機能しますが、別のデータベースでは機能しません。


それうまくいくかもしれませんstackoverflow.com/questions/285775/…を参照してください。OPの確認を待ちましょう。
ewernli 2010

1
これはデータベース固有ではありません!あなたは`とSQLのDialectに対応する、正しい引用スタイルにそれを翻訳休止状態でそれを逃れる
ダニエル・ケーファー

2

一部のJPA実装(たとえば、私が使用しているDataNucleus)は、識別子を自動的に引用するため、これを取得することはありません。


はい、Hibernateがヒットする回数を考えると、Hibernateがまだそのような基本的な機能を提供していないように見えることに驚いています(そして、誰かがこれが他の場所で可能であるとあえて言及したことで
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.