Tôi đang mất mát ở đây, và có lẽ đó là điều hiển nhiên vì chuyên môn Hibernate của tôi yếu hơn các khu vực khác.Hibernate hoán đổi lớp nhúng để di chuyển dữ liệu hiện có
Trong mã cũ có một lớp Hibernate @Entity
Foo
. Một trong những thuộc tính của nó là thế này:
private OldBar bar = new OldBar();
OldBar
là một lớp @Embeddable
có sử dụng một cột duy nhất, foobar
:
@Embeddable
public class OldBar {
private String fooBar;
@Column(length = 10, nullable = false)
private String getFooBar() {
return fooBar;
}
@SuppressWarnings("unused")
private void setFooBar(String fooBar) {
this.fooBar = fooBar;
}
}
Vấn đề gốc là tôi cần phải làm một cái gì đó với OldBar.fooBar
, nhưng thiết kế ban đầu có những hạn chế và có lĩnh vực này riêng tư, ngăn cản tôi phân lớp nó, vì vậy tôi phải tạo ra một lớp khác, NewBar
, để thay thế một trường khác và truy cập vào trường riêng. Tôi nghĩ rằng kể từ khi NewBar
cũng là Embeddable
và có cùng @Column
định, tôi chỉ có thể trao đổi trên lĩnh vực này trong lớp Foo
:
private NewBar bar = new NewBar();
tôi muốn làm điều này bởi vì tôi có dữ liệu hiện có trong cột foobar
, và Tôi muốn minh bạch sử dụng dữ liệu này với NewBar
thay vì OldBar
.
Thông qua nhật ký theo dõi Tôi đã thấy rằng Foo()
được tạo, với phiên bản mặc định là NewBar()
, như người ta mong đợi, khi hàm tạo được gọi. Tuy nhiên, do mã thời gian gọi Foo.getBar()
, vì một số lý do, bar
là null
! Tôi giả sử Hibernate được thiết lập nó để null
vì lý do nào đó --- nhưng tại sao Hibernate không đọc dữ liệu từ cột foobar
và tạo một thể hiện của NewBar
? Tại sao nó hoạt động trở lại khi tôi đặt OldBar
trở lại tại vị trí của NewBar
? Chắc chắn không có gì trong cơ sở dữ liệu chính nó nói rằng các lớp học @Embeddable
được ánh xạ tới cột, là có?
Cập nhật: Điều này trở nên lạ và lạ. Đôi khi tôi sẽ để mã qua đêm, và ngày hôm sau nó hoạt động! Hoặc ngày hôm sau nó không hoạt động! Bây giờ nó không hoạt động (nghĩa là, thuộc tính foobar
được đặt thành null
thay vì giá trị trong cơ sở dữ liệu), vì vậy tôi đã tạo lớp ExactCopyOfOldBar
và đặt nó ở vị trí OldBar
. Nó hoạt động tốt! Vì vậy, tôi chuyển về NewBar
--- chỉ hoàn tác các thay đổi tạm thời của tôi. Nó vẫn hoạt động, khi nó chưa từng xảy ra! Có một số loại bộ nhớ cache nơi Hibernate serializes giá trị và không nhận được chúng từ cơ sở dữ liệu? Điều này rất kỳ quặc.
Cập nhật: Bây giờ tôi không còn có thể nhận được NewBar
để làm việc. Tôi tạo ra OtherBar
, về cơ bản giống với NewBar
ngoại trừ nó có tên khác, và tôi cắm nó vào và nó hoạt động, đọc chính xác chuỗi được nhúng. Tôi chuyển trở lại thành NewBar
và tôi lại nhận được null
. Chuyện gì vậy?
Lưu ý rằng Foo
đang được nạp thông qua net.databinder.auth.hib.AuthDataApplication.getUser(String username)
, mà đơn giản là đủ:
return (DataUser) Databinder.getHibernateSession().createCriteria(getUserClass())
.add(Restrictions.eq("username", username)).uniqueResult();
tôi đã xác minh hơn và hơn nữa rằng Foo
(người dùng) bảng có một hàng duy nhất với các dữ liệu chính xác, và quan trọng nhất là trường foobar
có dữ liệu. Tại sao Hibernate trả lại cho tôi một số Foo
với một trường null
foobar
? Tại sao chỉ cần chuyển đổi từ NewBar
sang OtherBar
làm cho nó bắt đầu hoạt động trở lại? Tại sao nó hoạt động cả ngày và sau đó ngừng làm việc sau khi tôi đã để nó qua đêm?
Tôi giả định điều này là đúng, nhưng bạn không nói điều đó: Có phải 'Foo.bar' được đánh dấu là' @ Nhúng 'không? –
@Tim Pote: Trên thực tế, đủ kỳ lạ, trong mã di sản ban đầu (đang hoạt động), nó được _not_ đánh dấu là '@ Embedded'. Tôi đã thử nó có và không có '@ Embedded' khi tôi thay đổi hình thức' OldBar' thành 'NewBar', và nó đã không tạo sự khác biệt. –
@Tim Pote: Tôi đã học được từ Hibernate [documentation] (http://docs.jboss.org/hibernate/annotations/3.5/reference/en/html_single/) rằng "... nếu loại thuộc tính được chú thích là @Embeddable, nó được ánh xạ dưới dạng @Embedded, "về mặt kỹ thuật, phần' @ Embedded' là tùy chọn. –