我有一个数据库视图,它产生的结果集没有真正的主键。我想使用Hibernate/Persistence将这个结果集Map到Java对象上。当然,因为没有PK,我不能用@Id装饰任何字段。在部署时,Hibernate会抱怨缺少@Id。我该如何解决这个问题?
@Id
pqwbnv8z1#
如果存在使行唯一的列组合,则围绕列组合建模主键类。如果没有,基本上您就不走运了--但是您应该重新检查视图的设计,因为它可能没有意义。有几种不同的方法:
@Entitypublic class RegionalArticle implements Serializable { @Id public RegionalArticlePk getPk() { ... }}@Embeddablepublic class RegionalArticlePk implements Serializable { ... }
@Entity
public class RegionalArticle implements Serializable {
public RegionalArticlePk getPk() { ... }
}
@Embeddable
public class RegionalArticlePk implements Serializable { ... }
或者:
@Entitypublic class RegionalArticle implements Serializable { @EmbeddedId public RegionalArticlePk getPk() { ... }}public class RegionalArticlePk implements Serializable { ... }
@EmbeddedId
详情如下:https://docs.jboss.org/ejb3/app-server/HibernateAnnotations/reference/en/html_single/index.html#d0e1517这里有一个帖子描述了一个类似的问题:http://www.theserverside.com/discussions/thread.tss?thread_id=22638
iezvtpos2#
与其在Hibernate中寻找解决方法,不如在数据库视图中添加dummy id。让我们假设我们有一个PostgreSQL视图,它有两个列,没有一个是唯一的(没有主键,因为PostgreSQL不允许对视图进行PK或任何其他约束)。
| employee_id | project_name ||:------------|:-------------|| 1 | Stack01 || 1 | Jira01 || 1 | Github01 || 2 | Stack01 || 2 | Jira01 || 3 | Jira01 |------------------------------
| employee_id | project_name |
|:------------|:-------------|
| 1 | Stack01 |
| 1 | Jira01 |
| 1 | Github01 |
| 2 | Stack01 |
| 2 | Jira01 |
| 3 | Jira01 |
------------------------------
它由以下查询表示:
CREATE OR REPLACE VIEW someschema.vw_emp_proj_his AS SELECT DISTINCT e.employee_id, pinf.project_name FROM someschema.project_info pinf JOIN someschema.project_employee pe ON pe.proj_id = pinf.proj_id JOIN someschema.employees e ON e.employee_id = pe.emloyee_id
CREATE OR REPLACE VIEW someschema.vw_emp_proj_his AS
SELECT DISTINCT e.employee_id,
pinf.project_name
FROM someschema.project_info pinf
JOIN someschema.project_employee pe ON pe.proj_id = pinf.proj_id
JOIN someschema.employees e ON e.employee_id = pe.emloyee_id
我们可以使用row_number()添加虚拟id:
SELECT row_number() OVER (ORDER BY subquery.employee_id) AS row_id
就像这个例子:
CREATE OR REPLACE VIEW someschema.vw_emp_proj_his ASSELECT row_number() OVER (ORDER BY subquery.employee_id) AS row_id, subquery.employee_id, subquery.project_nameFROM (SELECT DISTINCT e.employee_id, pinf.project_name FROM someschema.project_info pinf JOIN someschema.project_employee pe ON pe.proj_id = pinf.proj_id JOIN someschema.employees e ON e.employee_id = pe.emloyee_id ) subquery;
SELECT row_number() OVER (ORDER BY subquery.employee_id) AS row_id,
subquery.employee_id,
subquery.project_name
FROM
(SELECT DISTINCT e.employee_id,
JOIN someschema.employees e ON e.employee_id = pe.emloyee_id ) subquery;
这个表看起来像这样:
| row_id | employee_id | project_name ||:------------|:------------|:-------------|| 1 | 1 | Stack01 || 2 | 1 | Jira01 || 3 | 1 | Github01 || 4 | 2 | Stack01 || 5 | 2 | Jira01 || 6 | 3 | Jira01 |-------------------------------------------
| row_id | employee_id | project_name |
|:------------|:------------|:-------------|
| 1 | 1 | Stack01 |
| 2 | 1 | Jira01 |
| 3 | 1 | Github01 |
| 4 | 2 | Stack01 |
| 5 | 2 | Jira01 |
| 6 | 3 | Jira01 |
-------------------------------------------
现在我们可以在JPA/Hibernate/Spring Data中使用row_id作为@Id:
@Id@Column(name = "row_id")private Integer id;
@Column(name = "row_id")
private Integer id;
例如:
@Entity@Table(schema = "someschema", name = "vw_emp_proj_his")public class EmployeeProjectHistory { @Id @Column(name = "row_id") private Integer id; @Column(name = "employee_id") private Integer employeeId; @Column(name = "project_name") private String projectName;//Getters, setters etc.}
@Table(schema = "someschema", name = "vw_emp_proj_his")
public class EmployeeProjectHistory {
@Column(name = "employee_id")
private Integer employeeId;
@Column(name = "project_name")
private String projectName;
//Getters, setters etc.
bjg7j2ky3#
对于每个实体,您必须至少指定以下内容之一:
所以也许你可以创建一个复合主键,包含多个字段?
y0u0uwnf4#
下面是一个有两个键作为“Id”键的例子:https://gist.github.com/3796379
vmpqdwk35#
您可以检查是否有逻辑明智的id,并提供相应的Map信息。Hibernate不会检查数据库是否存在已定义的主键。
rryofs0p6#
修改用于创建视图的选择:
SELECT ROWNUM ID, -- or use nextval of some sequence -- other columnsFROM TABLE
SELECT
ROWNUM ID, -- or use nextval of some sequence
-- other columns
TABLE
并将“ID”Map为主键。
mnowg1ta7#
你可以使用@EmbeddedId,如下所示:
@EmbeddedIdpublic Id getId() { return id;}public void setId(Id id) { this.id = id;}
public Id getId() {
return id;
public void setId(Id id) {
this.id = id;
xwbd5t1u8#
根据Hibernate用户指南,建议使用pk,因此即使您正在使用数据库端不包含pk的现有项目,您也可以将pk列添加到相关的数据库表并将其与Java实体Map。Hibernate的建议是这样的:我们建议您在持久化类上声明一致命名的标识符属性,并使用 Package 器(即非原始)类型(例如长或短)。关于pk和Hibernate机制的更多细节,请访问这里
ymdaylpp9#
虽然这不是你想要的,但我有个小技巧。让查询选择“rownum”并将“rownum”定义为模型中的ID列。这将有效地使每一行对Hibernate都是唯一的。
9条答案
按热度按时间pqwbnv8z1#
如果存在使行唯一的列组合,则围绕列组合建模主键类。如果没有,基本上您就不走运了--但是您应该重新检查视图的设计,因为它可能没有意义。
有几种不同的方法:
或者:
详情如下:https://docs.jboss.org/ejb3/app-server/HibernateAnnotations/reference/en/html_single/index.html#d0e1517
这里有一个帖子描述了一个类似的问题:http://www.theserverside.com/discussions/thread.tss?thread_id=22638
iezvtpos2#
与其在Hibernate中寻找解决方法,不如在数据库视图中添加dummy id。让我们假设我们有一个PostgreSQL视图,它有两个列,没有一个是唯一的(没有主键,因为PostgreSQL不允许对视图进行PK或任何其他约束)。
它由以下查询表示:
我们可以使用row_number()添加虚拟id:
就像这个例子:
这个表看起来像这样:
现在我们可以在JPA/Hibernate/Spring Data中使用row_id作为@Id:
例如:
bjg7j2ky3#
对于每个实体,您必须至少指定以下内容之一:
所以也许你可以创建一个复合主键,包含多个字段?
y0u0uwnf4#
下面是一个有两个键作为“Id”键的例子:https://gist.github.com/3796379
vmpqdwk35#
您可以检查是否有逻辑明智的id,并提供相应的Map信息。Hibernate不会检查数据库是否存在已定义的主键。
rryofs0p6#
修改用于创建视图的选择:
并将“ID”Map为主键。
mnowg1ta7#
你可以使用@EmbeddedId,如下所示:
xwbd5t1u8#
根据Hibernate用户指南,建议使用pk,因此即使您正在使用数据库端不包含pk的现有项目,您也可以将pk列添加到相关的数据库表并将其与Java实体Map。
Hibernate的建议是这样的:
我们建议您在持久化类上声明一致命名的标识符属性,并使用 Package 器(即非原始)类型(例如长或短)。
关于pk和Hibernate机制的更多细节,请访问这里
ymdaylpp9#
虽然这不是你想要的,但我有个小技巧。让查询选择“rownum”并将“rownum”定义为模型中的ID列。这将有效地使每一行对Hibernate都是唯一的。