【问题标题】:Is it illegitimate to name an JPA entity "Group"?将 JPA 实体命名为“组”是否非法?
【发布时间】:2011-03-10 01:27:58
【问题描述】:

我正在开发一个 JEE6 应用程序,使用 JPA 2.0 和 Hibernate 3.5.2-Final 作为提供者(以及 MySQL 5.1.41)。我的应用服务器是 Glassfish V3.0.1。 我已经有一个包含一些实体和关系的工作 CRUD 应用程序。

现在我添加了一个名为“组”的(非常简单的)实体。实体类如下所示:

package model
//Imports...
@Entity
public class Group {
  @Id @GeneratedValue
  private Long id;

  @NotNull
  private String name;

  //Getters and Setters
}

当然我也把它加到了persistence.xml中,比如<class>model.Group</class>。我的 persistence.xml 在部署时删除并重新创建所有表。

因此,当我部署我的应用程序时,会生成我所有实体的表,但表组除外。在休眠日志中,我发现了以下错误(这不会阻止应用程序的部署)

[#|2010-06-30T11:54:29.862+0200|INFO|glassfish3.0.1|org.hibernate.cfg.AnnotationBinder|_ThreadID=11;_ThreadName=Thread-1;|Binding entity from annotated class: model.Group|#]
[#|2010-06-30T11:54:29.862+0200|INFO|glassfish3.0.1|org.hibernate.cfg.annotations.EntityBinder|_ThreadID=11;_ThreadName=Thread-1;|Bind entity model.Group on table Group|#]
[#|2010-06-30T11:54:33.773+0200|SEVERE|glassfish3.0.1|org.hibernate.tool.hbm2ddl.SchemaExport|_ThreadID=11;_ThreadName=Thread-1;|Unsuccessful: create table Group (id bigint not null auto_increment, name varchar(255) not null, primary key (id))|#]
[#|2010-06-30T11:54:33.773+0200|SEVERE|glassfish3.0.1|org.hibernate.tool.hbm2ddl.SchemaExport|_ThreadID=11;_ThreadName=Thread-1;|You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'Group (id bigint not null auto_increment, name varchar(255) not null, primary ke' at line 1|#]
[#|2010-06-30T11:54:54.883+0200|INFO|glassfish3.0.1|org.hibernate.cfg.AnnotationBinder|_ThreadID=25;_ThreadName=Thread-1;|Binding entity from annotated class: model.Group|#]
[#|2010-06-30T11:54:54.884+0200|INFO|glassfish3.0.1|org.hibernate.cfg.annotations.EntityBinder|_ThreadID=25;_ThreadName=Thread-1;|Bind entity model.Group on table Group|#]
[#|2010-06-30T11:54:58.402+0200|SEVERE|glassfish3.0.1|org.hibernate.tool.hbm2ddl.SchemaExport|_ThreadID=25;_ThreadName=Thread-1;|Unsuccessful: create table Group (id bigint not null auto_increment, name varchar(255) not null, primary key (id))|#]
[#|2010-06-30T11:54:58.403+0200|SEVERE|glassfish3.0.1|org.hibernate.tool.hbm2ddl.SchemaExport|_ThreadID=25;_ThreadName=Thread-1;|You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'Group (id bigint not null auto_increment, name varchar(255) not null, primary ke' at line 1|#]

现在,当我将实体重命名为“MyGroup”之类的名称(属性保持不变)时,相应地更改 persistence.xml,并重新部署我的应用程序,成功创建了“MyGroup”表!我在日志中发现以下几行表明 MyGroup 已正确创建:

[#|2010-06-30T11:58:51.456+0200|INFO|glassfish3.0.1|org.hibernate.cfg.AnnotationBinder|_ThreadID=11;_ThreadName=Thread-1;|Binding entity from annotated class: model.MyGroup|#]
[#|2010-06-30T11:58:51.456+0200|INFO|glassfish3.0.1|org.hibernate.cfg.annotations.EntityBinder|_ThreadID=11;_ThreadName=Thread-1;|Bind entity model.MyGroup on table MyGroup|#]
[#|2010-06-30T11:59:21.569+0200|INFO|glassfish3.0.1|org.hibernate.cfg.AnnotationBinder|_ThreadID=25;_ThreadName=Thread-1;|Binding entity from annotated class: model.MyGroup|#]
[#|2010-06-30T11:59:21.569+0200|INFO|glassfish3.0.1|org.hibernate.cfg.annotations.EntityBinder|_ThreadID=25;_ThreadName=Thread-1;|Bind entity model.MyGroup on table MyGroup|#]

有人知道问题是什么吗? 好的,我可以将 Group 重命名为 MyGroup,但我真的很想知道这里发生了什么。我现在应该有什么限制,比如“不要调用实体组”吗?但是如果是这样,为什么我的错误如此不清楚?

【问题讨论】:

    标签: hibernate orm jpa java-ee-6 jpa-2.0


    【解决方案1】:

    如果您告诉 JPA 提供者对它们进行转义,您可以为数据库对象名称使用保留关键字。如规范的以下部分所述,这已在 JPA 2.0 中标准化:

    2.13 数据库对象的命名

    (...)

    要指定分隔标识符,一个 以下方法必须是 使用:

    • 可以指定所有数据库标识符用于一个 持久性单元被视为 通过指定分隔标识符 <delimited-identifiers/> 元素 在persistence-unit-defaults 内 对象/关系 xml 的元素 映射文件。如果 <delimited-identifiers/> 元素是 指定,它不能被覆盖。

    • 可以基于每个名称指定一个名称 数据库对象将被解释 作为分隔标识符如下:

      • 使用注释,名称被指定为分隔标识符 将名称包含在 double 中 引号,其中内部引号是 逃脱,例如, @Table(name="\"customer\"")
      • 何时 使用 XML,名称被指定为 使用双精度分隔标识符 引号,例如,<table name="&quot;customer&quot;"/>

    所以 JPA 2.0 的方式是像这样指定Table

    @Entity
    @Table(name="\"Group\"")
    public class Group {
      @Id @GeneratedValue
      private Long id;
    
      @NotNull
      private String name;
    
      //Getters and Setters
    }
    

    Hibernate 绝对支持这一点(参见 HHH-4553),这里没有泄漏抽象。

    【讨论】:

      【解决方案2】:

      Group 是 MySQL 数据库中的保留字,请参阅here

      package model
      //Imports...
      @Entity
      @Table(name = "group_table")
      public class Group {
        @Id @GeneratedValue
        private Long id;
      
        @NotNull
        private String name;
      
        //Getters and Setters
      }
      

      编辑 如果您想使用数据库实例中保留的字词,请参阅 @Pascals 对 JPA 2.0 方式的回答。

      【讨论】:

        【解决方案3】:

        您可以使用以下@Table 注释来引用“组”关键字:

        @Entity
        @Table(name = "`group`")
        public class Group {
        ...
        }
        

        我知道这是对一个老问题的回答,但我认为它可能会对某人有所帮助。

        【讨论】:

          【解决方案4】:

          对于一些 JPA 实现,您可以使用具有类似名称的类,并且 JPA 实现会在任何 SQL 中“引用”名称(因为它是 Paul Whelan 指出的保留字),所以它被接受。 DataNucleus 当然允许这个没问题。

          【讨论】:

          • 有趣。那么这不是Hibernate中的一个错误吗?在我看来,它确实应该被引用,或者至少应该有一个 Hibernate 的明确例外。
          • 我不能说竞争软件中的某些东西是否是错误(它超出了 JPA 规范 fwiw),但更愿意让该软件的用户来决定是否当周围有没有这种限制的替代方案并且有明确的方式为其提供支持时,他们认为这种行为是可以接受的
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-02-20
          • 1970-01-01
          • 1970-01-01
          • 2014-08-05
          • 2011-04-05
          • 2012-06-23
          相关资源
          最近更新 更多