2009-05-29 28 views
30

Ho una vista del database che produce un set di risultati che non ha una chiave primaria vera. Voglio usare Hibernate/Persistence per mappare questo set di risultati su oggetti Java. Naturalmente, poiché non esiste il PK, non posso decorare alcun campo con @Id.Sospensione/persistenza senza @Id

Durante la distribuzione, Hibernate lamenta la mancanza dello @Id. Come posso aggirare questo?

risposta

23

Se esiste una combinazione di colonne che rende una riga univoca, modellare una classe di chiavi primaria attorno alla combinazione di colonne. Se non lo è, sei praticamente sfortunato, ma dovresti riesaminare il design della vista poiché probabilmente non ha senso.

Ci sono un paio diversi approcci:

@Entity 
public class RegionalArticle implements Serializable { 

    @Id 
    public RegionalArticlePk getPk() { ... } 
} 

@Embeddable 
public class RegionalArticlePk implements Serializable { ... } 

Oppure:

@Entity 
public class RegionalArticle implements Serializable { 

    @EmbeddedId 
    public RegionalArticlePk getPk() { ... } 
} 

public class RegionalArticlePk implements Serializable { ... } 

I dettagli sono qui: http://docs.jboss.org/ejb3/app-server/HibernateAnnotations/reference/en/html_single/index.html#d0e1517

Ecco un post che descrive un problema simile: http://www.theserverside.com/discussions/thread.tss?thread_id=22638

0

È possibile verificare se esiste un ID logico e fornire le informazioni di mappatura di conseguenza. Hibernate non controlla il database per l'esistenza di una chiave primaria definita.

6

Per ogni entità, è necessario designare almeno uno dei seguenti:

  • uno @Id
  • multipla @Id e un @IdClass (per una chiave primaria composta)
  • EmbeddedId

quindi forse è possibile creare una chiave primaria composta, contenente più campi?

-1

Anche se non è esattamente quello che stai chiedendo, ecco un piccolo trucco che uso. Chiedi alla query di selezionare "rownum" e definire "rownum" come colonna ID nel modello. Questo renderà ogni riga univoca per Hibernate.

+0

questo causerà problemi se la cache è usato – NimChimpsky

2

Invece di cercare soluzioni alternative in Hibernate, potrebbe essere più semplice aggiungere un fittizio nella vista del database. Supponiamo di avere una vista di PostgreSQL con due colonne e nessuna di esse è unica (e non esiste una chiave primaria come Postgres non consente di rendere PK o altri vincoli sulle viste) ex.

| employee_id | project_name | 
|:------------|:-------------| 
| 1   | Stack01  | 
| 1   | Jira01  | 
| 1   | Github01  | 
| 2   | Stack01  | 
| 2   | Jira01  | 
| 3   | Jira01  | 
------------------------------ 

che è rappresentato dalla seguente query:

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 

Possiamo aggiungere fittizio id utilizzando row_number():

SELECT row_number() OVER (ORDER BY subquery.employee_id) AS row_id 

come in questo esempio:

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; 

E il tavolo assomiglierà a quello s:

| row_id  | employee_id | project_name | 
|:------------|:------------|:-------------| 
| 1   | 1   | Stack01  | 
| 2   | 1   | Jira01  | 
| 3   | 1   | Github01  | 
| 4   | 2   | Stack01  | 
| 5   | 2   | Jira01  | 
| 6   | 3   | Jira01  | 
------------------------------------------- 

Ora possiamo usare row_id come @Id in JPA/Hibernate/primavera dei dati:

@Id 
@Column(name = "row_id") 
private Integer id; 

come nell'esempio:

@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. 

} 
+0

È difficile vedere che questa è una vittoria di chiarezza sopra l'ID incorporato sopra a meno che non sia effettivamente necessario un ID univoco. Ci sono anche considerazioni sulle prestazioni? –

Problemi correlati