org.postgresql.util.PSQLException: 错误:列 user0_.id 不存在 - Hibernate

46

我有一个模型类,使用Hibernate映射到PostgreSQL数据库。我的模型类如下:

@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中的数据库如下所示:

database

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


你正在使用的模式名称是什么? - Youcef LAIDANI
模式名称为 myapp - kovac
9个回答

67

解决方案

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. USER关键字是PostgreSQL中的保留关键字 请查看

+----------+-----------+----------+-----------+---------+
| Key Word |PostgreSQL |SQL:2003  | SQL:1999  | SQL-92  |
+----------+-----------+----------+-----------+---------+
|  ....        ....       ....       ....       ....    |
+----------+-----------+----------+-----------+---------+
| USER     |  reserved |reserved  | reserved  | reserved|
+----------+-----------+----------+-----------+---------+
  1. 为了区分DtoEntity,最好在实体名称末尾使用“Entity”,例如UserEntity

2
感谢您更新答案。我不能公开实际的架构,因为其中包含一些商业信息。但是您的建议解决了问题 :) - kovac
1
没有问题 @swdon,你想要另一个解决方案还是什么? - Youcef LAIDANI
1
不,我按照您的原始答案操作,现在没有任何问题。一切都按预期工作。我们可以关闭这个线程了。非常感谢您的帮助! - kovac
1
谢谢兄弟,我的问题是在列名中使用大写字母。 - Sajeer Babu
1
我每次都会被这个狡猾的USER关键字所迷惑。 - gdrt
显示剩余2条评论

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所说,请勿在表名或列名中使用大写字母,否则会出现异常。

当您需要从实体类自动生成表格或反之亦然时,这个约定变得更加重要。


5

我已经尝试了这个方法,但仍然遇到了问题:[select u1_0.id from public.user u1_0 where u1_0.email=? fetch first ? rows only] [ERROR: relation "public.user" does not exist] - Om Gupta

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

2

我使用像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 在这种情况下,user被保留用于PostgreSQLSQL:2003SQL:1999SQL-92

1

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

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


1
改变
@Table(name="USER")

@Table(name"/"USER/"")

USER是一个保留字,所以它需要使用"字符。


0
除了之前所有正确的答案,我想说注释 @Column 和 @GeneratedValue 的定位也很重要。你希望这两个注释都在特定字段或getter方法上方,但不是分别放置(不是一个注释在getter上方,另一个在字段上方)。至少对我来说这样做是有效的。

0

我通过将列名从nameLikeThis更改为name_like_this来解决了这个问题。

ALTER TABLE table RENAME nameLikeThis to name_like_this;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接