Спящий режим/постоянство без @Id - программирование
Подтвердить что ты не робот

Спящий режим/постоянство без @Id

У меня есть представление базы данных, которое дает набор результатов, который не имеет истинного первичного ключа. Я хочу использовать Hibernate/Persistence для сопоставления этого набора результатов с объектами Java. Конечно, поскольку нет ПК, я не могу украсить любое поле с помощью @Id.

При развертывании Hibernate жалуется на отсутствие @Id. Как я могу обойти это?

4b9b3361

Ответ 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

возможно, вы можете создать составной первичный ключ, содержащий несколько полей?

Ответ 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.