真の主キーを持たない結果セットを生成するデータベース ビューがあります。Hibernate/Persistence を使用して、この結果セットを Java オブジェクトにマップしたいと考えています。もちろん、PKがないので、どのフィールドも で飾ることはできません@Id
。
デプロイするとき、Hibernate は欠落について不平を言い@Id
ます。どうすればこれを回避できますか?
真の主キーを持たない結果セットを生成するデータベース ビューがあります。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
論理的なIDがあるかどうかを確認し、それに応じてマッピング情報を提供できます。Hibernate は、定義された主キーの存在についてデータベースをチェックしません。
次のように @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」を主キーとしてマップします。
あなたが求めているものとは正確には異なりますが、ここに私が使用するちょっとしたトリックがあります. クエリで「rownum」を選択し、「rownum」をモデルの ID 列として定義します。これにより、事実上、すべての行が Hibernate に固有のものになります。