Спящий режим/постоянство без @Id
У меня есть представление базы данных, которое дает набор результатов, который не имеет истинного первичного ключа. Я хочу использовать Hibernate/Persistence для сопоставления этого набора результатов с объектами Java. Конечно, поскольку нет ПК, я не могу украсить любое поле с помощью @Id
.
При развертывании Hibernate жалуется на отсутствие @Id
. Как я могу обойти это?
Ответы
Ответ 1
Если существует комбинация столбцов, которая делает уникальную строку, моделируйте класс первичного ключа вокруг комбинации столбцов. Если этого не происходит, вам в основном не повезло - но вы должны пересмотреть дизайн представления, поскольку он, вероятно, не имеет смысла.
Существует несколько разных подходов:
@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://docs.jboss.org/ejb3/app-server/HibernateAnnotations/reference/en/html_single/index.html#d0e1517
Здесь размещена публикация, которая описывает аналогичную проблему: http://www.theserverside.com/discussions/thread.tss?thread_id=22638
Ответ 2
Для каждого объекта вы должны указать хотя бы одно из следующего:
- one @Id
- несколько @Id и @IdClass (для составного первичного ключа)
- @EmbeddedId
возможно, вы можете создать составной первичный ключ, содержащий несколько полей?
Ответ 3
Вот пример, который имеет 2 ключа как "Id": https://gist.github.com/3796379
Ответ 4
Вместо поиска обходных путей в Hibernate может быть проще добавить фиктивный идентификатор в представлении базы данных. Предположим, что мы имеем представление PostgreSQL с двумя столбцами, и ни одно из них не является уникальным (и нет первичного ключа, поскольку Postgres не позволяет делать PK или любые другие ограничения на представления) ex.
| 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
Мы можем добавить фиктивный 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 Данные:
@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.
}
Ответ 5
Вы можете проверить, есть ли логический логический идентификатор и соответствующим образом отображать информацию сопоставления. Hibernate не будет проверять базу данных на наличие определенного первичного ключа.
Ответ 6
В то время как не совсем то, о чем вы просите, вот небольшой трюк, который я использую. Попросите выбрать "rownum" и определите "rownum" в качестве столбца ID в модели. Это эффективно сделает каждую строку уникальной для Hibernate.