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

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

我有一个模型 class 使用休眠映射到 postgres 数据库。我的模型 class 是:

@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 如何将 class 属性映射到 table 列?它是仅基于 @Column(name="username") 进行匹配,还是也尝试基于数据类型和约束条件进行匹配,例如 unique/auto-increment?

##解决方案

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

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

@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所说不要在table名称或列名称中使用Upper_case字母否则你会得到这个异常。

当您必须 自动生成 来自实体 类 的 table 或反之亦然时,此约定变得更加重要。

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

在您的 POJO class Id 字段中。这个东西解决了我的错误。

应在实体 class 上添加架构名称。 对于此示例,当架构名称为 public

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

查看下面的 PostgreSQL 管理视图

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

我发现使用像 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(并将数据 table 从 user 重命名为 sessionxuser 以解决此问题.

架构仍然是 public

因为一些名字像 mycoolappuserusermycoolapp 这样的前缀或后缀可以避免这样的麻烦。

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

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

在这种情况下,user 保留用于 PostgreSQLSQL:2003SQL:1999SQL-92

尝试从 pg 管理控制台 (drop table schema_name.table_name) 删除 table 并确保您的实体 class 是正确的 annotated.For 示例 @Table(name = "table_name", schema = "schema_name") 在实体 class

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