2012-11-28 33 views
8

Câu hỏi cơ bản: Tại sao các đối tượng @Embedded luôn được khởi tạo?@Đối tượng được nhúng tự động không được tự động hóa nếu nó không có trường dữ liệu cơ bản

Quan sát thú vị là Ebean không khởi tạo các đối tượng @Embedded nếu những đối tượng này không chứa kiểu dữ liệu cơ bản (int, boolean ...) hoặc không được chạm vào trước đó. Ví dụ:

@Entity 
public class Embedder { 
    // getNotAutoInstantiated() will return null if this field was not touched before 
    @Embedded 
    private NotAutoInstantiated notAutoInstantiated = new NotAutoInstantiated(); 
    // getAutoInstantiated() will always return an instance! 
    @Embedded 
    private AutoInstantiated autoInstantiated = new AutoInstantiated(); 
} 

@Embeddable 
public class AutoInstantiated { 
    // theKey is why this embedded object is always instantiated 
    private int theKey; 
    private String field1;  
} 

@Embeddable 
public class NotAutoInstantiated { 
    private String field2;  
} 
+0

Bạn có thể đang gặp sự cố với xung đột tên trường giữa nhiều đối tượng được nhúng. Thông thường, nhà cung cấp JPA ánh xạ các trường đối tượng được nhúng vào các cột trong bảng cha. Nếu tên trường được nhúng dài, bạn có thể kết thúc với tên trường rút gọn trong cơ sở dữ liệu và do đó va chạm trong tên cột. – Zagrev

+0

Ví dụ có thể là lừa dối. Các tên ngắn hơn nhiều trong mã của tôi và chúng không bắt đầu bằng cùng một tiền tố. Nhưng ngay cả trong ví dụ, các trường bắt đầu bằng "không" và "tự động", vì vậy việc cắt ngắn sẽ không phải là vấn đề lớn. – allprog

+0

Thực ra, tôi đã suy nghĩ về "trường" và "trường". – Zagrev

Trả lời

3

Tôi không nghĩ rằng spec JPA rõ ràng mô tả những gì sẽ xảy ra khi tính một @Embedded đối tượng là tất cả vô, nhưng ít nhất một số hiện thực đối xử với một đối tượng với thuộc tính null như một đối tượng null, mà là những gì bạn đang thấy.

Điều này có vẻ như thực hiện hợp lý. Chắc chắn nó đã được hữu ích trong mã của tôi (sử dụng Hibernate), nếu tôi đặt một đối tượng @Embedded thành null, tôi muốn nó vẫn giữ nguyên khi tôi tải một phiên bản đã tồn tại.

Trong ví dụ của bạn, lớp AutoInstantiated không bao giờ có thể được coi là rỗng, vì thuộc tính nguyên thủy theKey không bao giờ có thể rỗng.

+0

Thật không may, tình hình tồi tệ hơn thế. Ebean có vẻ không nhất quán với hành vi này. Chúng tôi có một mô hình dữ liệu khá phức tạp, trong đó các trường @Embedded giống như AutoInstantiated thực sự được tự động khởi tạo ở hầu hết các địa điểm. Nhưng có một nơi mà điều này không xảy ra.Chúng tôi không thể tìm thấy sự khác biệt của cái đó. Cách tiếp cận "để trống" không phải là cách tốt nhất đối với tôi vì nó đòi hỏi một kiểm tra null khác. Đây là thực hành tồi tệ nhất trong Java. Nó có thể dễ dàng tránh được trong những trường hợp như vậy ... – allprog

3

Bạn có thể muốn kiểm tra:

https://hibernate.atlassian.net/browse/HHH-7610

Đặc biệt, kể từ 5.1:

static final String CREATE_EMPTY_COMPOSITES_ENABLED 

Enable instantiation of composite/embedded objects when all of its 
attribute values are null. The default (and historical) behavior is that a null reference 
will be used to represent the composite when all of its attributes are null 
@since 5.1 
@see Constant Field Values 

Đặt hibernate.create_empty_composites.enabled tài sản cho đúng và thì đấy!

+0

Cảm ơn, điều này là tốt để biết. Tuy nhiên, câu hỏi có liên quan đến EBean. Hibernate có lẽ vượt trội về nhiều mặt, nhưng Ebean phù hợp hơn với các dự án nhỏ. – allprog

1

Tôi vừa gặp vấn đề tương tự với Hibernate. Câu hỏi ban đầu, về "lý do" được trả lời.

Nhưng để nói về một giải pháp, tôi chỉ sử dụng một phương pháp @PostLoad, vì vậy trong lớp Embedder cái gì đó như:

@PostLoad 
private void initData() { 
    if(notAutoInstantiated == null) { 
    notAutoInstantiated = new NotAutoInstantiated(); 
    } 
} 

Cập nhật:

Cảnh báo! Mã trên đang hoạt động, nhưng có tác dụng phụ không mong muốn! Ngay sau khi bạn nạp đối tượng của bạn với con trỏ null từ cơ sở dữ liệu, nó được đánh dấu là dơ bẩn, vì mã tải bài đăng này! Trong trường hợp của tôi, các tác dụng phụ này dẫn đến một lệnh cập nhật SQL từ một chuỗi, chỉ nên tải dữ liệu và số giờ tìm kiếm lỗi này!

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