【问题标题】:org.postgresql.util.PSQLException: ERROR: column user0_.id does not exist - Hibernateorg.postgresql.util.PSQLException:错误:列 user0_.id 不存在 - 休眠
【发布时间】:2018-01-28 15:44:36
【问题描述】:

我有一个使用 hibernate 映射到 postgres 数据库的模型类。我的模型类是:

@Entity
@Table(name="USER")
public class User {

    @Id 
    @GeneratedValue
    @Column(name="id")
    private long id;

    @Column(name="username", unique=true)
    private String username;

    @Column(name="email")
    private String email;

    @Column(name="created")
    private Timestamp created;

    public User(long id, String username, String email) {
        this.id = id;
        this.username = username;
        this.email = email;
    }
}

我尝试使用以下查询检索用户名为“adam”的用户:

tx = session.beginTransaction();
TypedQuery<User> query = session.createQuery("FROM User u WHERE u.username = :username", User.class).setParameter("username", "adam");
user = query.getSingleResult();

我得到一个例外:

org.postgresql.util.PSQLException: ERROR: column user0_.id does not exist

我的 bash shell 数据库如下所示:

hibernate 如何将类属性映射到表列?它是仅基于@Column(name="username") 匹配,还是也尝试基于数据类型和约束(例如唯一/自动增量)进行匹配?

【问题讨论】:

  • 您使用的 shcema 的名称是什么?
  • 架构名称是myapp

标签: java postgresql hibernate jpa entity


【解决方案1】:

##解决方案

PostgreSQL 中,您必须像这样指定架构的名称:

@Table(name="table_name", schema = "myapp")
                          ^^^^^^^^^^^^^^^^

##长篇大论

你遇到了这个错误:

org.postgresql.util.PSQLException: ERROR: column user0_.id does not exist

因为当你在 PostgreSQL 中创建数据库时,它会创建一个名为 public 的默认架构,所以当你没有在 Entity 中指定名称时,然后 Hibernate将自动检查 public 架构。


##良好做法

  1. 不要在 PostgreSQL 中在 databaseschematablescolumns 的名称中使用大写字母。否则,您应该使用引号转义此名称,这可能会导致语法错误,因此您可以使用:

@Table(name="table_name", schema = "schema_name")
             ^^^^^^^^^^             ^^^^^^^^^^^
  1. 关键字USERPostgreSQL中的保留关键字take a look at

+----------+-----------+----------+-----------+---------+
| Key Word |PostgreSQL |SQL:2003  | SQL:1999  | SQL-92  |
+----------+-----------+----------+-----------+---------+
|  ....        ....       ....       ....       ....    |
+----------+-----------+----------+-----------+---------+
| USER     |  reserved |reserved  | reserved  | reserved|
+----------+-----------+----------+-----------+---------+
  1. DtoEntity 之间的区别最好在实体名称末尾使用实体,例如 UserEntity

【讨论】:

  • 感谢您更新答案。我无法放置实际架构,因为它包含一些业务信息。但是你的建议解决了这个问题:)
  • 没问题@swdon你想要另一个解决方案还是什么?
  • 不,我按照你原来的答案,现在没有问题。一切都按预期工作。我们可以关闭线程。非常感谢您的帮助!
  • 谢谢兄弟,在列名中使用大写字母是我的问题
  • 我每次都喜欢这个鬼鬼祟祟的 USER 关键字?
【解决方案2】:

除了前面所有的正确答案,我想说的是@Column和@GeneratedValue注解的定位也很重要。您希望将这两个注释都放在特定字段或 getter 方法之上,但不能分开(不是一个注释在 getter 之上,另一个在字段之上)。至少对我有用。

【讨论】:

    【解决方案3】:

    尝试从 pg 管理控制台 (drop table schema_name.table_name) 删除表并确保您的实体类已正确注释。例如实体类上的 @Table(name = "table_name", schema = "schema_name")

    【讨论】:

      【解决方案4】:

      我使用user 之类的通用名称在应用程序中制造了麻烦。

      我遇到了与此处报告的相同问题,使用以下简单实体。

      import javax.persistence.Column;
      import javax.persistence.Entity;
      import javax.persistence.GeneratedValue;
      import javax.persistence.GenerationType;
      import javax.persistence.Id;
      import javax.persistence.SequenceGenerator;
      
      @Entity
      public class User implements Serializable {
      
          private static final long serialVersionUID = 6843302791607583447L;
      
          @Id
          @SequenceGenerator(name = "user_id_seq", sequenceName = "user_id_seq", allocationSize = 1)
          @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "user_id_seq")
          private Long id;
      
          @Column
          private String name;
      
          @Column
          private String password;
      
          @Override
          public String toString() {
              return name;
          }
      
          public Long getId() {
              return id;
          }
      
          public String getName() {
              return name;
          }
      
          public void setName(final String name) {
              this.name = name;
          }
      
          public String getPassword() {
              return password;
          }
      
          public void setPassword(final String password) {
              this.password = password;
          }
      
      }
      

      我所做的只是将实体从 User 重命名为 Sessionxuser(并将数据表从 user 重命名为 sessionxuser 以解决此问题。

      架构仍然是 public

      由于前缀或后缀一些名称,如 mycoolappuserusermycoolapp,以避免此类麻烦。

      在下面查找包含保留关键字和文字的列表,以防止用作表、列和进一步自定义的名称。

      https://www.postgresql.org/docs/8.1/sql-keywords-appendix.html

      在这种情况下,userPostgreSQLSQL:2003SQL:1999SQL-92 保留。

      【讨论】:

        【解决方案5】:

        应在 Entity 类上添加模式名称。 对于此示例,当架构名称为 public 时

        @Table(name = "user", schema = "public")
        

        查看下面的 PostgreSQL 管理视图

        有关 SpringBoot Java 和 Postgre SQL 连接的更多信息,请参见此处: https://cmsoftwaretech.wordpress.com/2020/04/25/springboot-thymleaf-using-postgresql/

        【讨论】:

          【解决方案6】:

          使用:@GeneratedValue(strategy = GenerationType.IDENTITY)

          在您的 POJO 类 Id 字段中。这件事解决了我的错误。

          【讨论】:

            【解决方案7】:

            对于遇到此异常的人,在 postgres 中,每当您编写实体类时,请尝试将其与正确的架构(您的表所在的位置)相关联,如下所示:

            @Entity
            @Table(name = "user", schema = "users_details")
            public class User implements Serializable{
            
                @Column(name = "id")
                Long id;    //long is not recommended
            
               // Other data
            }
            

            正如@YCF_L 所说,不要在表名或列名中使用大写字母,否则你会得到这个异常。

            当您必须从实体类自动生成表或反之亦然的情况下,此约定变得更加重要。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2017-03-05
              • 1970-01-01
              • 2011-05-28
              相关资源
              最近更新 更多