真の主キーを持たない結果セットを生成するデータベースビューがあります。 Hibernate/Persistenceを使用してこの結果セットをJavaオブジェクトにマップします。もちろん、PKがないため、@Id
でフィールドを装飾できません。
デプロイ時に、Hibernateは欠落している@Id
について文句を言います。どうすればこれを回避できますか?
行を一意にする列の組み合わせがある場合は、列の組み合わせを中心に主キークラスをモデル化します。ない場合は、基本的に運が悪いのですが、ビューのデザインを再検討する必要があります。
いくつかの異なるアプローチがあります:
@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つを指定する必要があります。
それで、複数のフィールドを含む複合主キーを作成できますか?
Hibernateで回避策を検索する代わりに、データベースビューにダミーIDを追加する方が簡単な場合があります。 2つの列を持つ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()を使用してダミーIDを追加できます。
SELECT 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で@Idとしてrow_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.
}
「Id」キーとして2つのキーを持つ例を次に示します。 https://Gist.github.com/3796379
次のように@EmbeddedIdを使用できます。
@EmbeddedId
public Id getId() {
return id;
}
public void setId(Id id) {
this.id = id;
}
ビューの作成に使用する選択を変更します。
SELECT
ROWNUM ID, -- or use nextval of some sequence
-- other columns
FROM
TABLE
そして、「ID」を主キーとしてマップします。
論理的なIDがあるかどうかを確認し、それに応じてマッピング情報を提供できます。 Hibernateは定義された主キーの存在についてデータベースをチェックしません。