2009-05-29 34 views
30

Tôi có chế độ xem cơ sở dữ liệu mang lại tập hợp kết quả không có khóa chính đúng. Tôi muốn sử dụng Hibernate/Persistence để ánh xạ tập kết quả này lên các đối tượng Java. Tất nhiên, vì không có PK, tôi không thể trang trí bất kỳ trường nào với @Id.Hibernate/persistence mà không có @Id

Khi triển khai, Hibernate than phiền về số thiếu @Id. Làm thế nào tôi có thể làm việc xung quanh điều này?

Trả lời

23

Nếu có sự kết hợp các cột tạo thành một hàng duy nhất, hãy tạo mô hình một lớp khóa chính xung quanh kết hợp các cột. Nếu không có, bạn về cơ bản không may mắn - nhưng bạn nên xem xét lại thiết kế của quan điểm vì nó có lẽ không có ý nghĩa.

Có một vài phương pháp khác nhau:

@Entity 
public class RegionalArticle implements Serializable { 

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

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

Hoặc:

@Entity 
public class RegionalArticle implements Serializable { 

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

public class RegionalArticlePk implements Serializable { ... } 

Các chi tiết đang ở đây: http://docs.jboss.org/ejb3/app-server/HibernateAnnotations/reference/en/html_single/index.html#d0e1517

Dưới đây là một gửi bài mô tả một vấn đề tương tự: http://www.theserverside.com/discussions/thread.tss?thread_id=22638

0

Bạn có thể kiểm tra xem có id logic khôn ngoan không và cung cấp thông tin bản đồ cho phù hợp. Hibernate sẽ không kiểm tra cơ sở dữ liệu cho sự tồn tại của một khóa chính được xác định.

6

Đối với từng đối tượng, bạn phải chỉ định ít nhất một trong các cách sau:

  • một @Id
  • nhiều @ id và một @IdClass (cho một khóa chính composite)
  • @EmbeddedId

vì vậy có thể bạn có thể tạo khóa chính kết hợp, chứa nhiều trường?

-1

Mặc dù không chính xác những gì bạn đang yêu cầu, đây là mẹo nhỏ mà tôi sử dụng. Có truy vấn chọn "rownum" và xác định "rownum" làm cột ID của bạn trong mô hình. Điều đó sẽ có hiệu quả làm cho mỗi hàng duy nhất để Hibernate.

+0

này sẽ gây ra vấn đề nếu bộ nhớ cache được sử dụng – NimChimpsky

2

Thay vì tìm kiếm cách giải quyết trong Hibernate, có thể dễ dàng thêm id giả trong chế độ xem cơ sở dữ liệu của bạn. Giả sử rằng chúng ta có chế độ xem PostgreSQL với hai cột và không có cột nào là duy nhất (và không có khóa chính nào vì Postgres không cho phép tạo PK hoặc bất kỳ ràng buộc nào khác trên các khung nhìn).

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

nào được đại diện bởi các truy vấn sau đây:

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 

Chúng ta có thể thêm id giả sử dụng row_number():

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

như trong ví dụ này:

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; 

Và bảng sẽ trông giống như thi 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  | 
------------------------------------------- 

Bây giờ chúng ta có thể sử dụng row_id như @ id trong JPA/Hibernate/Dữ liệu mùa xuân:

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

Giống như trong ví dụ:

@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

Thật khó để thấy đây là một chiến thắng rõ ràng hơn embededId ở trên trừ khi bạn thực sự cần một id duy nhất. Có cân nhắc về hiệu suất không? –

Các vấn đề liên quan