2010-08-02 7 views
5

Tôi có một ứng dụng sử dụng Hibernate để lưu giữ dữ liệu, với Spring ở trên cùng (để đo tốt). Cho đến gần đây, đã có một lớp liên tục trong các ứng dụng, A:Thực tiễn không tốt là sử dụng DiscriminatorFormula để di chuyển cơ sở dữ liệu Hibernate?

@Entity 
public class A { 
    @Id 
    @Column(unique = true, nullable = false, updatable = false) 
    @GeneratedValue(strategy = GenerationType.IDENTITY) 
    private long id; 
    public String name; 
} 

Tôi có kể từ khi bổ sung thêm một lớp con của A, gọi là B:

@Entity 
public class B extends A { 
    public String description; 
} 

Sau khi thêm B, tôi có thể bây giờ không tải của một . Ngoại lệ sau đã bị ném:

class org.springframework.orm.hibernate3.HibernateObjectRetrievalFailureException :: Object with id: 1 was not of the specified subclass: A (Discriminator: null); nested exception is org.hibernate.WrongClassException: Object with id: 1 was not of the specified subclass: A (Discriminator: null) 

Tôi đã thêm chú thích và thuộc tính sau vào B và dường như đã giải quyết được sự cố. Đây có phải là cách đúng để giải quyết vấn đề không?

... 
@DiscriminatorFormula("(CASE WHEN dtype IS NULL THEN 'A' ELSE dtype END)") 
public class A { 
    private String dtype = this.getClass().getSimpleName(); 
    ... 

Trả lời

2

(...) Cho đến gần đây, đã có một lớp liên tục trong các ứng dụng, A:

Với các đại diện cơ sở dữ liệu sau đây:

ID NAME 
-- ---- 
1 foo 
2 bar 

tôi kể từ đó đã thêm một lớp con của A, được gọi là B (...)

Và bạn không chỉ định chú thích Inheritance để sử dụng chiến lược lập bản đồ SINGLE_TABLE. Và Trong chiến lược này, tất cả các lớp trong một hệ thống phân cấp được ánh xạ tới một bảng duy nhất. Bảng này có một cột phục vụ như một "cột phân biệt đối xử", nghĩa là một cột có giá trị xác định lớp con cụ thể mà cá thể được đại diện bởi hàng thuộc về.

Bảng sau đó trở thành:

ID NAME DTYPE 
-- ---- ----- 
1 foo NULL 
2 bar NULL 

đâu DTYPE là tên mặc định của cột được sử dụng cho bộ phân biệt.

Sau khi thêm B, giờ đây tôi không thể tải A. Ngoại lệ sau được ném (...)

Thật vậy, vì giá trị hiện tại có giá trị rỗng trong cột phân biệt, nhà cung cấp không biết phân lớp nào sẽ khởi tạo.

Tôi đã thêm chú thích và thuộc tính sau vào B và dường như đã giải quyết được sự cố. Đây có phải là cách đúng để giải quyết vấn đề không?

Đó là một cách nhưng nó xâm nhập (thực thể của bạn không nên biết cột dtype) và Hibernate cụ thể. Nói cách khác, đó là một hack.

Đối với tôi, cách "đúng" để giải quyết này sẽ được cập nhật DTYPE cột ghi A hiện có để thiết lập các giá trị cho 'A' (với Hibernate, giá trị mặc định giá trị cho tên tổ chức):

UPDATE A SET DTYPE='A' WHERE DTYPE=NULL 

Bằng cách này, Hibernate sẽ có thể tải chúng đúng cách.

+0

cảm ơn câu trả lời chi tiết. Rất tiếc, tôi sẽ không có quyền truy cập trực tiếp vào tất cả các lượt cài đặt của ứng dụng, vì vậy tôi muốn thay đổi giản đồ này xảy ra một cách minh bạch cho người dùng. Tôi đã thử thêm DiscriminatorFormula mà không xác định rõ ràng trường dtype, nhưng điều này không làm việc. Nó cảm thấy như một hack khi tôi đã làm nó - đó là lý do tại sao tôi hỏi. – Armand

+1

@Alison Bạn được chào đón. Tôi đã cho bạn IMO là giải pháp "lý tưởng". Nếu nó không phù hợp trong ngữ cảnh của bạn, nếu bạn không thể cung cấp kịch bản di chuyển cho người dùng của bạn (điều đó sẽ thực hiện 'UPDATE' sau khi' ALTER' khác) - hoặc thậm chí là công cụ di chuyển tự động tốt hơn - thì giải pháp của bạn có thể chấp nhận được. Ít nhất nó hoạt động. Và bây giờ bạn biết nó là một hack một :) –

+0

-) Tôi đã tìm thấy thông tin về di cư trong Hibernate/Spring khá khó để đi qua, không may. – Armand