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 模式中自动检查。
##良好做法
- 不要在 PostgreSQL 中的
database
、schema
、tables
或 columns
的名称中使用大写字母.否则你应该用引号来转义这个名字,这会导致语法错误,所以你可以使用 :
@Table(name="table_name", schema = "schema_name")
^^^^^^^^^^ ^^^^^^^^^^^
- 关键字 USER 是 PostgreSQL 中的保留关键字 take a look at
+----------+-----------+----------+-----------+---------+
| Key Word |PostgreSQL |SQL:2003 | SQL:1999 | SQL-92 |
+----------+-----------+----------+-----------+---------+
| .... .... .... .... .... |
+----------+-----------+----------+-----------+---------+
| USER | reserved |reserved | reserved | reserved|
+----------+-----------+----------+-----------+---------+
- 为了区分 Dto 和 Entity 最好在实体名称的末尾使用实体,例如
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
。
因为一些名字像 mycoolappuser
或 usermycoolapp
这样的前缀或后缀可以避免这样的麻烦。
在下面找到一个列表,其中包含防止用作 table、列和进一步自定义名称的保留关键字和文字。
https://www.postgresql.org/docs/8.1/sql-keywords-appendix.html
在这种情况下,user
保留用于 PostgreSQL
、SQL:2003
、SQL:1999
和 SQL-92
。
尝试从 pg 管理控制台 (drop table schema_name.table_name
) 删除 table 并确保您的实体 class 是正确的 annotated.For 示例 @Table(name = "table_name", schema = "schema_name")
在实体 class
除了前面所有的正确答案之外,我想说的是注解@Column和@GeneratedValue的定位也很重要。您希望将这两个注释都放在特定字段或 getter 方法之上,但不要分开( 而不是 一个注释在 getter 上方,另一个在字段上方).它至少对我有用。
我有一个模型 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 模式中自动检查。
##良好做法
- 不要在 PostgreSQL 中的
database
、schema
、tables
或columns
的名称中使用大写字母.否则你应该用引号来转义这个名字,这会导致语法错误,所以你可以使用 :
@Table(name="table_name", schema = "schema_name")
^^^^^^^^^^ ^^^^^^^^^^^
- 关键字 USER 是 PostgreSQL 中的保留关键字 take a look at
+----------+-----------+----------+-----------+---------+
| Key Word |PostgreSQL |SQL:2003 | SQL:1999 | SQL-92 |
+----------+-----------+----------+-----------+---------+
| .... .... .... .... .... |
+----------+-----------+----------+-----------+---------+
| USER | reserved |reserved | reserved | reserved|
+----------+-----------+----------+-----------+---------+
- 为了区分 Dto 和 Entity 最好在实体名称的末尾使用实体,例如
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
。
因为一些名字像 mycoolappuser
或 usermycoolapp
这样的前缀或后缀可以避免这样的麻烦。
在下面找到一个列表,其中包含防止用作 table、列和进一步自定义名称的保留关键字和文字。
https://www.postgresql.org/docs/8.1/sql-keywords-appendix.html
在这种情况下,user
保留用于 PostgreSQL
、SQL:2003
、SQL:1999
和 SQL-92
。
尝试从 pg 管理控制台 (drop table schema_name.table_name
) 删除 table 并确保您的实体 class 是正确的 annotated.For 示例 @Table(name = "table_name", schema = "schema_name")
在实体 class
除了前面所有的正确答案之外,我想说的是注解@Column和@GeneratedValue的定位也很重要。您希望将这两个注释都放在特定字段或 getter 方法之上,但不要分开( 而不是 一个注释在 getter 上方,另一个在字段上方).它至少对我有用。