不带@Id的Hibernate/persistence

w1jd8yoj  于 2023-10-23  发布在  其他
关注(0)|答案(9)|浏览(133)

我有一个数据库视图,它产生的结果集没有真正的主键。我想使用Hibernate/Persistence将这个结果集Map到Java对象上。当然,因为没有PK,我不能用@Id装饰任何字段。
在部署时,Hibernate会抱怨缺少@Id。我该如何解决这个问题?

pqwbnv8z

pqwbnv8z1#

如果存在使行唯一的列组合,则围绕列组合建模主键类。如果没有,基本上您就不走运了--但是您应该重新检查视图的设计,因为它可能没有意义。
有几种不同的方法:

  1. @Entity
  2. public class RegionalArticle implements Serializable {
  3. @Id
  4. public RegionalArticlePk getPk() { ... }
  5. }
  6. @Embeddable
  7. public class RegionalArticlePk implements Serializable { ... }

或者:

  1. @Entity
  2. public class RegionalArticle implements Serializable {
  3. @EmbeddedId
  4. public RegionalArticlePk getPk() { ... }
  5. }
  6. public class RegionalArticlePk implements Serializable { ... }

详情如下: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

展开查看全部
iezvtpos

iezvtpos2#

与其在Hibernate中寻找解决方法,不如在数据库视图中添加dummy id。让我们假设我们有一个PostgreSQL视图,它有两个列,没有一个是唯一的(没有主键,因为PostgreSQL不允许对视图进行PK或任何其他约束)。

  1. | employee_id | project_name |
  2. |:------------|:-------------|
  3. | 1 | Stack01 |
  4. | 1 | Jira01 |
  5. | 1 | Github01 |
  6. | 2 | Stack01 |
  7. | 2 | Jira01 |
  8. | 3 | Jira01 |
  9. ------------------------------

它由以下查询表示:

  1. CREATE OR REPLACE VIEW someschema.vw_emp_proj_his AS
  2. SELECT DISTINCT e.employee_id,
  3. pinf.project_name
  4. FROM someschema.project_info pinf
  5. JOIN someschema.project_employee pe ON pe.proj_id = pinf.proj_id
  6. JOIN someschema.employees e ON e.employee_id = pe.emloyee_id

我们可以使用row_number()添加虚拟id:

  1. SELECT row_number() OVER (ORDER BY subquery.employee_id) AS row_id

就像这个例子:

  1. CREATE OR REPLACE VIEW someschema.vw_emp_proj_his AS
  2. SELECT row_number() OVER (ORDER BY subquery.employee_id) AS row_id,
  3. subquery.employee_id,
  4. subquery.project_name
  5. FROM
  6. (SELECT DISTINCT e.employee_id,
  7. pinf.project_name
  8. FROM someschema.project_info pinf
  9. JOIN someschema.project_employee pe ON pe.proj_id = pinf.proj_id
  10. JOIN someschema.employees e ON e.employee_id = pe.emloyee_id ) subquery;

这个表看起来像这样:

  1. | row_id | employee_id | project_name |
  2. |:------------|:------------|:-------------|
  3. | 1 | 1 | Stack01 |
  4. | 2 | 1 | Jira01 |
  5. | 3 | 1 | Github01 |
  6. | 4 | 2 | Stack01 |
  7. | 5 | 2 | Jira01 |
  8. | 6 | 3 | Jira01 |
  9. -------------------------------------------

现在我们可以在JPA/Hibernate/Spring Data中使用row_id作为@Id:

  1. @Id
  2. @Column(name = "row_id")
  3. private Integer id;

例如:

  1. @Entity
  2. @Table(schema = "someschema", name = "vw_emp_proj_his")
  3. public class EmployeeProjectHistory {
  4. @Id
  5. @Column(name = "row_id")
  6. private Integer id;
  7. @Column(name = "employee_id")
  8. private Integer employeeId;
  9. @Column(name = "project_name")
  10. private String projectName;
  11. //Getters, setters etc.
  12. }
展开查看全部
bjg7j2ky

bjg7j2ky3#

对于每个实体,您必须至少指定以下内容之一:

  • 一个@ID
  • 多个@Id和一个@IdClass(用于复合主键)
  • @EmbeddedId

所以也许你可以创建一个复合主键,包含多个字段?

y0u0uwnf

y0u0uwnf4#

下面是一个有两个键作为“Id”键的例子:https://gist.github.com/3796379

vmpqdwk3

vmpqdwk35#

您可以检查是否有逻辑明智的id,并提供相应的Map信息。Hibernate不会检查数据库是否存在已定义的主键。

rryofs0p

rryofs0p6#

修改用于创建视图的选择:

  1. SELECT
  2. ROWNUM ID, -- or use nextval of some sequence
  3. -- other columns
  4. FROM
  5. TABLE

并将“ID”Map为主键。

mnowg1ta

mnowg1ta7#

你可以使用@EmbeddedId,如下所示:

  1. @EmbeddedId
  2. public Id getId() {
  3. return id;
  4. }
  5. public void setId(Id id) {
  6. this.id = id;
  7. }
xwbd5t1u

xwbd5t1u8#

根据Hibernate用户指南,建议使用pk,因此即使您正在使用数据库端不包含pk的现有项目,您也可以将pk列添加到相关的数据库表并将其与Java实体Map。
Hibernate的建议是这样的:
我们建议您在持久化类上声明一致命名的标识符属性,并使用 Package 器(即非原始)类型(例如长或短)。
关于pk和Hibernate机制的更多细节,请访问这里

ymdaylpp

ymdaylpp9#

虽然这不是你想要的,但我有个小技巧。让查询选择“rownum”并将“rownum”定义为模型中的ID列。这将有效地使每一行对Hibernate都是唯一的。

相关问题