我有一个数据库视图,它产生的结果集没有真正的主键。我想使用Hibernate / Persistence将此结果集映射到Java对象。当然,因为没有PK,我无法用@Id
装饰任何字段。
部署时,Hibernate会抱怨缺少@Id
。我该如何解决这个问题?
答案 0 :(得分:26)
如果列的组合使行唯一,则在列组合周围建模主键类。如果没有,你基本上没有运气 - 但你应该重新审视视图的设计,因为它可能没有意义。
有几种不同的方法:
@Entity
public class RegionalArticle implements Serializable {
@Id
public RegionalArticlePk getPk() { ... }
}
@Embeddable
public class RegionalArticlePk implements Serializable { ... }
或者:
@Entity
public class RegionalArticle implements Serializable {
@EmbeddedId
public RegionalArticlePk getPk() { ... }
}
public class RegionalArticlePk implements Serializable { ... }
这是一篇描述类似问题的帖子:http://www.theserverside.com/discussions/thread.tss?thread_id=22638
答案 1 :(得分:6)
答案 2 :(得分:4)
不是在Hibernate中搜索变通方法,而是在数据库视图中添加虚拟id可能更容易。让我们假设我们有两列的PostgreSQL视图,并且它们都不是唯一的(并且没有主键,因为Postgres不允许对视图进行PK或任何其他约束)。
| 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
我们可以使用row_number():
添加虚拟IDSELECT row_number() OVER (ORDER BY subquery.employee_id) AS row_id
就像在这个例子中一样:
CREATE OR REPLACE VIEW someschema.vw_emp_proj_his AS
SELECT row_number() OVER (ORDER BY subquery.employee_id) AS row_id,
subquery.employee_id,
subquery.project_name
FROM
(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;
表格如下:
| 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;
与示例中一样:
@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.
}
答案 3 :(得分:1)
以下示例包含2个键作为“Id”键:https://gist.github.com/3796379
答案 4 :(得分:0)
您可以检查是否存在逻辑明智的id并相应地提供映射信息。 Hibernate不会检查数据库是否存在已定义的主键。
答案 5 :(得分:0)
修改用于创建视图的选择内容
SELECT
ROWNUM ID, -- or use nextval of some sequence
-- other columns
FROM
TABLE
并映射“ ID”作为主键。
答案 6 :(得分:0)
您可以按如下方式使用@EmbeddedId:
@EmbeddedId
public Id getId() {
return id;
}
public void setId(Id id) {
this.id = id;
}
答案 7 :(得分:0)
根据Hibernate用户指南,建议使用pk,因此,即使您正在数据库中不包含pk的现有项目中工作,也可以将pk列添加到相关的数据库表中并进行映射Java实体。
休眠建议如下:
我们建议您在持久性类上声明统一命名的标识符属性,并使用包装器(即非原始)类型(例如Long或Integer)。
有关pk和休眠机制的更多详细信息,请访问here
答案 8 :(得分:-1)
虽然不完全是你所要求的,但这是我使用的一个小技巧。让查询选择" rownum"并定义" rownum"作为模型中的ID列。这将有效地使每一行都是Hibernate独有的。