如何在 JPA 中映射名称为保留字的实体字段
Posted
技术标签:
【中文标题】如何在 JPA 中映射名称为保留字的实体字段【英文标题】:How to map an entity field whose name is a reserved word in JPA 【发布时间】:2011-01-14 12:49:33 【问题描述】:@Column(name="open")
在休眠中使用 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 在创建表时使用带引号的标识符。
除了重命名字段之外,关于如何处理这个问题的任何想法?
【问题讨论】:
参见例如hibernate.onjira.com/browse/HHH-1272 【参考方案1】:否 - 更改列名。
这是特定于数据库的,您不能创建这样的列。毕竟hibernate最终将DDL发送到数据库。如果你不能用这个列名创建一个有效的 DDL,这意味着 hibernate 也不能。即使您正在编写 DDL,我也不认为引用会解决问题。
即使您以某种方式成功逃脱了名称 - 更改它。它可以与这个数据库一起工作,但不能与另一个数据库一起工作。
【讨论】:
这可能有效。见***.com/questions/285775/…。让我们等待OP的确认。 这不是特定于数据库的!您使用 ` 对其进行转义,然后休眠将其转换为 SQL 方言的正确引用样式【参考方案2】:如果你按如下所示使用它应该可以工作
@Column(name="[order]")
private int order;
【讨论】:
您只是在私有字段上而不是在 getter 上执行此操作? 这是特定于 sqlserver 的。【参考方案3】:使用 Hibernate 作为 JPA 1.0 提供者,您可以通过将保留关键字括在反引号中来对其进行转义:
@Column(name="`open`")
这是继承自 Hiberate Core 的语法:
5.4. SQL quoted identifiers
你可以强制 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\"")
参考文献
休眠参考指南 5.4. SQL quoted identifiers JPA 2.0 规范 2.13 数据库对象的命名相关问题
Hibernate, MySQL and table named “Repeat” - strange behaviour Automatic reserved word escaping for Hibernate tables and columns【讨论】:
感谢我。它解决了我遇到的一个问题。顺便说一句 - 参考现在在:docs.jboss.org/hibernate/stable/core/manual/en-US/html/… 我不明白为什么我必须这样做,为什么 Hibernate 不自动而不是我这样做??? @DanielHári 也许你觉得我的回答更“自动”? @Rafiek:哦,是的,这是完美的解决方案,赞成 (y)。 使用@Column(name="[open]")
更漂亮:)【参考方案4】:
一些 JPA 实现(例如我使用的 DataNucleus)会自动为您引用标识符,因此您永远不会得到这个。
【讨论】:
是的,令人惊讶的是,考虑到人们被它击中的次数,Hibernate 似乎仍然没有提供这样一个基本功能(有人甚至因为你敢于在其他地方提到这可能而对你投了反对票)跨度> 【参考方案5】:@Column(name="\"open\"")
这肯定会起作用,我在学习休眠时也遇到了同样的问题。
【讨论】:
【参考方案6】:遇到了同样的问题,但使用了名为 Transaction
的表名。如果你设置
hibernate.globally_quoted_identifiers=true
然后所有的数据库标识符都会被引用。
在这里找到我的答案 Special character in table name hibernate giving error
并在此处找到所有可用设置 https://docs.jboss.org/hibernate/orm/5.2/userguide/html_single/appendices/Configurations.html
虽然找不到更好的文档。
在我的情况下,设置在我的 Spring 属性文件中。如 cmets 中所述,它也可以在其他与休眠相关的配置文件中。
【讨论】:
这不是默认设置吗? SQL 可能变得不可读,并且使用关键字作为名称是不应该鼓励的不好的做法。我想……? 好的。我宁愿整天使用转义的保留字作为名称,而不是不合适的名称。 是的,你可以说 Hibernate 提供的抽象只关心而不是它是如何在技术上实现的。但是,如果您还使用 Flyway 或 Liquibase 之类的工具,那么当您需要考虑可能存在保留字时,它会增加复杂性。这是我迁移架构时的经验。 对于那些想知道需要在哪里设置的人,它可能在您的persistence.xml
中用于 JBoss 项目。【参考方案7】:
手动转义保留关键字
如果你使用的是 JPA,你可以用双引号转义:
@Column(name = "\"open\"")
如果您使用的是 Hibernate 原生 API,那么您可以使用反引号对它们进行转义:
@Column(name = "`open`")
自动转义保留关键字
如果要自动转义保留关键字,可以将Hibernate特有的hibernate.globally_quoted_identifiers
配置属性设置为true
:
<property
name="hibernate.globally_quoted_identifiers"
value="true"
/>
Yaml 格式
spring:
jpa:
properties:
hibernate:
globally_quoted_identifiers: true
【讨论】:
【参考方案8】:还有另一种选择:hibernate.auto_quote_keyword
哪个
指定是否自动引用任何被视为关键字的名称。
<property name="hibernate.auto_quote_keyword" value="true" />
Yaml
spring:
jpa:
properties:
hibernate:
auto_quote_keyword: true
【讨论】:
我发现这比 global_quoted_identifiers 更好,因为它只引用保留关键字而不是每个标识符。以上是关于如何在 JPA 中映射名称为保留字的实体字段的主要内容,如果未能解决你的问题,请参考以下文章
如何在同一个数据库表上映射两个 JPA 或 Hibernate 实体