Вместо поиска обходных путей в Hibernate может быть проще добавить фиктивный идентификатор в представление базы данных. Давайте предположим, что у нас есть представление 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 ():
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 |
-------------------------------------------
Теперь мы можем использовать row_id как @Id в JPA / Hibernate / Spring Data:
@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.
}