Java 没有@Id 的休眠/持久性
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/925818/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Hibernate/persistence without @Id
提问by
I have a database view that yields a result set that has no true primary key. I want to use Hibernate/Persistence to map this result set onto Java objects. Of course, because there is no PK, I cannot decorate any field with @Id
.
我有一个数据库视图,它产生一个没有真正主键的结果集。我想使用 Hibernate/Persistence 将此结果集映射到 Java 对象。当然,因为没有PK,我不能用@Id
.装饰任何字段。
When deploying, Hibernate complains about the missing @Id
. How can I work around this?
部署时,Hibernate 会抱怨缺少@Id
. 我该如何解决这个问题?
采纳答案by Edward Q. Bridges
If there's a combination of columns that makes a row unique, model a primary key class around the combination of columns. If there isn't, you're basically out of luck -- but you should reexamine the design of the view since it probably doesn't make sense.
如果存在使行唯一的列组合,请围绕列组合建模主键类。如果没有,那么您基本上就不走运了——但是您应该重新检查视图的设计,因为它可能没有意义。
There are a couple different approaches:
有几种不同的方法:
@Entity
public class RegionalArticle implements Serializable {
@Id
public RegionalArticlePk getPk() { ... }
}
@Embeddable
public class RegionalArticlePk implements Serializable { ... }
Or:
或者:
@Entity
public class RegionalArticle implements Serializable {
@EmbeddedId
public RegionalArticlePk getPk() { ... }
}
public class RegionalArticlePk implements Serializable { ... }
The details are here: http://docs.jboss.org/ejb3/app-server/HibernateAnnotations/reference/en/html_single/index.html#d0e1517
详细信息在这里:http: //docs.jboss.org/ejb3/app-server/HibernateAnnotations/reference/en/html_single/index.html#d0e1517
Here's an posting that describes a similar issue: http://www.theserverside.com/discussions/thread.tss?thread_id=22638
这是描述类似问题的帖子:http: //www.theserverside.com/discussions/thread.tss?thread_id=22638
回答by rudolfson
You could check if there is logic wise an id and provide mapping information accordingly. Hibernate will not check the database for existence of a defined primary key.
您可以检查是否有逻辑明智的 id 并相应地提供映射信息。Hibernate 不会检查数据库是否存在定义的主键。
回答by Fortega
For each entity, you must designate at least one of the following:
对于每个实体,您必须至少指定以下一项:
- one @Id
- multiple @Id and an @IdClass (for a composite primary key)
- @EmbeddedId
- 一个@Id
- 多个@Id 和一个@IdClass(对于复合主键)
- @EmbeddedId
so maybe you can create a composite primary key, containing multiple fields?
所以也许您可以创建一个包含多个字段的复合主键?
回答by rogerdpack
Here is an example that has 2 keys as "Id" keys: https://gist.github.com/3796379
这是一个将 2 个键作为“Id”键的示例:https: //gist.github.com/3796379
回答by Stacy Mobley
While not exactly what you're asking for, here's a little trick I use. Have the query select "rownum" and define "rownum" as your ID column in the model. That will effectively make every row unique to Hibernate.
虽然不完全是你所要求的,但这是我使用的一个小技巧。让查询选择“rownum”并将“rownum”定义为模型中的 ID 列。这将有效地使每一行对于 Hibernate 都是唯一的。
回答by luke
Instead of searching for workarounds in Hibernate it might be easier to add dummy id in your database view. Let's assume that we have PostgreSQL view with two columns and none of them is unique (and there is no primary key as Postgres doesn't allow to make PK or any other constraints on views) ex.
与在 Hibernate 中搜索解决方法不同,在数据库视图中添加虚拟 ID 可能更容易。假设我们有包含两列的 PostgreSQL 视图,并且它们都不是唯一的(并且没有主键,因为 Postgres 不允许对视图进行 PK 或任何其他约束)例如。
| employee_id | project_name |
|:------------|:-------------|
| 1 | Stack01 |
| 1 | Jira01 |
| 1 | Github01 |
| 2 | Stack01 |
| 2 | Jira01 |
| 3 | Jira01 |
------------------------------
Which is represented by the following query:
由以下查询表示:
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
We can add dummy id using row_number():
我们可以使用 row_number() 添加虚拟 ID:
SELECT row_number() OVER (ORDER BY subquery.employee_id) AS row_id
like in this example:
就像在这个例子中:
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;
And the table will look like this:
该表将如下所示:
| row_id | employee_id | project_name |
|:------------|:------------|:-------------|
| 1 | 1 | Stack01 |
| 2 | 1 | Jira01 |
| 3 | 1 | Github01 |
| 4 | 2 | Stack01 |
| 5 | 2 | Jira01 |
| 6 | 3 | Jira01 |
-------------------------------------------
Now we can use row_id as @Id in JPA/Hibernate/Spring Data:
现在我们可以在 JPA/Hibernate/Spring Data 中使用 row_id 作为 @Id:
@Id
@Column(name = "row_id")
private Integer id;
Like in the example:
就像在这个例子中:
@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.
}
回答by Peter S.
Modify your select used for view creation:
修改用于创建视图的选择:
SELECT
ROWNUM ID, -- or use nextval of some sequence
-- other columns
FROM
TABLE
and map "ID" as primary key.
并将“ID”映射为主键。
回答by Victoria Serkov
you could just use @EmbeddedId as follows:
你可以使用 @EmbeddedId 如下:
@EmbeddedId
public Id getId() {
return id;
}
public void setId(Id id) {
this.id = id;
}
回答by Semih Okan Pehlivan
According to Hibernate user guide, using the pk is recommended so even if you are working with the existing project that doesn't contain the pk in the database side, you can add the pk column to the related database table and map it with the Java entities.
根据 Hibernate 用户指南,建议使用 pk,因此即使您正在处理数据库端不包含 pk 的现有项目,您也可以将 pk 列添加到相关的数据库表中并使用 Java 映射它实体。
The hibernate recommendation was like that:
休眠建议是这样的:
We recommend that you declare consistently-named identifier attributes on persistent classes and that you use a wrapper (i.e., non-primitive) type (e.g. Long or Integer).
我们建议您在持久类上声明一致命名的标识符属性,并使用包装器(即非原始)类型(例如 Long 或 Integer)。
For more detail about pk and Hibernate mechanism, please visit here
有关 pk 和 Hibernate 机制的更多详细信息,请访问此处