2008-09-01 33 views
5
@Entity 
@Inheritance(strategy = InheritanceType.SINGLE_TABLE) 
public class Problem { 
    @ManyToOne 
    private Person person; 
} 

@Entity 
@DiscriminatorValue("UP") 
public class UglyProblem extends Problem {} 

@Entity 
public class Person { 
    @OneToMany(mappedBy="person") 
    private List<UglyProblem> problems; 
} 

Tôi nghĩ rằng điều này khá rõ ràng những gì tôi đang cố gắng làm. Tôi mong đợi @ManyToOne người được thừa hưởng bởi lớp UglyProblem. Nhưng sẽ có một ngoại lệ nói một cái gì đó như: "Không có tài sản như vậy được tìm thấy trong lớp UglyProblem (mappedBy =" person ")".Tại sao @OneToMany không hoạt động với thừa kế trong Hibernate

Tất cả những gì tôi tìm thấy là this. Tôi không thể tìm thấy bài viết của Emmanuel Bernard giải thích lý do đằng sau điều này.


Thật không may, theo các tài liệu Hibernate "Properties từ superclasses không ánh xạ như @MappedSuperclass được bỏ qua."

Vâng, tôi nghĩ rằng điều này có nghĩa rằng nếu tôi có hai loại cổ phiếu này:

public class A { 
    private int foo; 
} 

@Entity 
public class B extens A { 
} 

sau đó trường foo sẽ không được ánh xạ cho lớp B. Trong đó có ý nghĩa. Nhưng nếu tôi có một cái gì đó như thế này:

@Entity 
public class Problem { 

@Id 
@GeneratedValue(strategy = GenerationType.AUTO) 
private Long id; 

private String name; 

public Long getId() { 
    return id; 
} 

public void setId(Long id) { 
    this.id = id; 
} 

public String getName() { 
    return name; 
} 

public void setName(String name) { 
    this.name = name; 
} 
} 

@Entity 
public class UglyProblem extends Problem { 

private int levelOfUgliness; 

public int getLevelOfUgliness() { 
    return levelOfUgliness; 
} 

public void setLevelOfUgliness(int levelOfUgliness) { 
    this.levelOfUgliness = levelOfUgliness; 
} 
} 

tôi hy vọng các UglyProblem lớp để có fileds idname và cả hai lớp được ánh xạ sử dụng cùng một bảng. (Trong thực tế, đây là chính xác những gì sẽ xảy ra, tôi vừa kiểm tra lại). Tôi đã nhận được bảng này:

CREATE TABLE "problem" (
    "DTYPE" varchar(31) NOT NULL, 
    "id" bigint(20) NOT NULL auto_increment, 
    "name" varchar(255) default NULL, 
    "levelOfUgliness" int(11) default NULL, 
    PRIMARY KEY ("id") 
) AUTO_INCREMENT=2; 

Trở lại với câu hỏi của tôi:

Tôi hy vọng người @ManyToOne được thừa hưởng bởi lớp UglyProblem.

Tôi hy vọng rằng vì tất cả các trường được ánh xạ khác được kế thừa và tôi không thấy bất kỳ lý do nào để làm ngoại lệ này cho các mối quan hệ ManyToOne.


Vâng, tôi đã thấy điều đó. Trong thực tế, tôi đã sử dụng giải pháp Chỉ đọc cho trường hợp của mình. Nhưng câu hỏi của tôi là "Tại sao ..." :). Tôi biết rằng có một lời giải thích được đưa ra bởi một thành viên của nhóm ngủ đông. Tôi đã không thể tìm thấy nó và đó là lý do tại sao tôi hỏi.

Tôi muốn tìm hiểu động cơ của quyết định thiết kế này.

(nếu bạn quan tâm như thế nào tôi đã phải đối mặt với vấn đề này: Tôi thừa hưởng một dự án được xây dựng bằng cách sử dụng ngủ đông 3. Đó là Jboss 4.0.something + hibernate đã có (bạn sẽ tải xuống tất cả cùng nhau). để Jboss 4.2.2 và tôi phát hiện ra rằng có được thừa kế ánh xạ của "@OneToMany mappedBy" và nó hoạt động tốt trên thiết lập cũ ...)

+0

Bạn nên bổ sung thêm chi tiết về chỉnh sửa của bạn vào ngày 04 Tháng Chín.Chỉ định Danh sách thay vì chỉ Danh sách trong ánh xạ @OneToMany (mappedBy = "person") thay đổi bản chất của vấn đề, vì tôi nghĩ rằng trước đây chúng tôi giả định bạn muốn ánh xạ một Người vào danh sách Sự cố (không phải là Ugl –

Trả lời

4

Tôi nghĩ đó là quyết định khôn ngoan của nhóm Hibernate. Họ có thể ít arrogante và làm cho nó rõ ràng lý do tại sao nó được thực hiện theo cách này, nhưng đó chỉ là cách Emmanuel, Chris và Gavin làm việc. :)

Hãy cố gắng hiểu vấn đề. Tôi nghĩ rằng khái niệm của bạn là "nói dối". Firts bạn nói rằng nhiều Vấn đề s được liên kết với Mọi người. Nhưng, sau đó bạn nói rằng một trong số Người có nhiều UglyProblem s (và không liên quan đến khác Vấn đề s). Đã xảy ra sự cố với thiết kế đó.

Hãy tưởng tượng cách nó sẽ được ánh xạ tới cơ sở dữ liệu. Bạn có một thừa kế bảng duy nhất, vì vậy:

  _____________ 
      |__PROBLEMS__|   |__PEOPLE__| 
      |id <PK>  |   |   | 
      |person <FK> | -------->|   | 
      |problemType |   |_________ | 
      -------------- 

như thế nào ngủ đông sẽ thực thi các cơ sở dữ liệu để làm Vấn đề chỉ liên quan đến dân nếu problemType nó bằng UP? Đó là một vấn đề rất khó giải quyết. Vì vậy, nếu bạn muốn loại quan hệ này, mỗi phân lớp phải nằm trong bảng riêng của nó. Đó là những gì @MappedSuperclass thực hiện.

PS .: Xin lỗi vì bản vẽ xấu xí: D

1

tôi nghĩ rằng bạn cần phải chú thích vấn đề siêu lớp của bạn với @MappedSuperclass thay vì @Entity.

4

Thật không may, theo Hibernate documentation "Các thuộc tính từ các siêu lớp không được ánh xạ dưới dạng @MappedSuperclass đều bị bỏ qua". Tôi chạy lên chống lại điều này quá. Giải pháp của tôi là đại diện cho thừa kế mong muốn thông qua giao diện chứ không phải là các bean thực thể.

Trong trường hợp của bạn, bạn có thể định nghĩa như sau:

public interface Problem { 
    public Person getPerson(); 
} 

public interface UglyProblem extends Problem { 
} 

Sau đó, thực hiện các giao diện sử dụng một lớp cha trừu tượng và hai lớp con thực thể:

@MappedSuperclass 
public abstract class AbstractProblemImpl implements Problem { 
    @ManyToOne 
    private Person person; 

    public Person getPerson() { 
     return person; 
    } 
} 

@Entity 
public class ProblemImpl extends AbstractProblemImpl implements Problem { 
} 

@Entity 
public class UglyProblemImpl extends AbstractProblemImpl implements UglyProblem { 
} 

Là một lợi ích bổ sung, nếu bạn mã sử dụng các giao diện chứ không phải là các thực thể thực tế mà thực hiện các giao diện đó, nó làm cho nó dễ dàng hơn để thay đổi ánh xạ bên dưới sau này (ít nguy cơ phá vỡ khả năng tương thích).

0

Tôi đã tìm ra cách thực hiện vấn đề bản đồ OneToMany.

Trong lớp dẫn xuất UglyProblem từ bài đăng gốc. Phương thức gọi lại cần phải ở trong lớp dẫn xuất chứ không phải lớp cha.

@Entity 
@Inheritance(strategy = InheritanceType.SINGLE_TABLE) 
@ForceDiscriminator 
public class Problem { 

} 

@Entity 
@DiscriminatorValue("UP") 
public class UglyProblem extends Problem { 
    @ManyToOne 
    private Person person; 
} 

@Entity 
public class Person { 
    @OneToMany(mappedBy="person") 
    private List<UglyProblem> problems; 
} 

Tìm thấy nước sốt bí mật để sử dụng Hibernate ít nhất. http://docs.jboss.org/hibernate/stable/annotations/api/org/hibernate/annotations/ForceDiscriminator.html @ForceDiscriminator làm cho @OneToMany tôn vinh người phân biệt đối xử

Yêu cầu chú thích ngủ đông.

5

Trong trường hợp của tôi, tôi muốn sử dụng kiểu kế thừa SINGLE_TABLE, vì vậy việc sử dụng @MappedSuperclass không phải là một tùy chọn.

gì hoạt động, mặc dù không phải rất sạch sẽ, là thêm Hibernate độc ​​quyền @Where khoản để hiệp hội @OneToMany để buộc các loại trong các truy vấn:

@OneToMany(mappedBy="person") 
@Where(clause="DTYPE='UP'") 
private List<UglyProblem> problems; 
+0

Các giải pháp thay thế cho ' @ Where' cho eclipseLink hoặc JPA nói chung sẽ được nhiều đánh giá cao – Odys

+0

Hi Odys, trong EclipseLink bạn chỉ đơn giản là không cần phải chỉ định bất cứ điều gì. Thực thể với field1. UglyPerson uglyPerson; và field2 BeutifulPerfoson beutifulPerson; Trong eclipselink, anh ta tự động biết nhìn BeuftifulPerson của bạn @DescriminatorValue ("PRETTY_PERSON") và tìm đúng thứ. Hibernate không biết điều này, và buộc bạn phải sử dụng @ Mệnh đề WHERE: Eclipselink được thông minh phân tích một lớp học hiearchy và giải quyết trên Lập bản đồ eToMany. – 99Sono

+0

Trong Ecliipselink chỉ cần đảm bảo rằng các thực thể của bạn là một phần của một lớp học hàng hải có riêng của nó thích hợp; @DiscriminatorValue ("BEAUTIFUL_PERON") descriminator và thêm vào các lớp cơ sở nếu một cái gì đó thực thể của bạn như: @DiscriminatorColumn (name = "ENTITY_CLASS", descriminatorType = string) và bạn có thể dễ dàng sử dụng @Inheritance (SINGLE_TABLE) Với Hibernate, bạn đang khá khó khăn về điều này, vì bạn cần phải xác định một WHERE clasuse, và liên tục duy trì vị từ với ENTITY_CLASS cho mỗi phần tử con trong cấu trúc phân cấp. Vì vậy, ở đây eclipselink là con đường phía trước. – 99Sono

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