سؤال

@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;
}

أعتقد أنه من الواضح جدًا ما أحاول القيام به.أتوقع أن يتم توريث شخص @ManyToOne بواسطة فئة UglyProblem.ولكن سيكون هناك استثناء يقول شيئًا مثل:"لم يتم العثور على مثل هذه الخاصية في فئة UglyProblem (mappedBy = "person")".

كل ما وجدته هو هذا.لم أتمكن من العثور على مشاركة إيمانويل برنارد التي تشرح الأسباب وراء ذلك.


لسوء الحظ، وفقًا لوثائق السبات "يتم تجاهل الخصائص من الفئات الفائقة التي لم يتم تعيينها كـ @MappedSuperclass."

حسنًا، أعتقد أن هذا يعني أنه إذا كان لدي هذين الفئتين:

public class A {
    private int foo;
}

@Entity
public class B extens A {
}

ثم الميدان foo لن يتم تعيينها للفئة B.وهو أمر منطقي.ولكن إذا كان لدي شيء مثل هذا:

@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;
}
}

أتوقع أن يكون لدى فئة UglyProblem ملفات id و name وسيتم تعيين كلا الفئتين باستخدام نفس الجدول.(في الواقع، هذا ما يحدث بالضبط، لقد تحققت للتو مرة أخرى).لقد حصلت على هذا الجدول:

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;

أعود إلى سؤالي:

أتوقع أن يتم توريث شخص @ManyToOne بواسطة فئة UglyProblem.

أتوقع ذلك لأن جميع الحقول المعينة الأخرى موروثة ولا أرى أي سبب لإجراء هذا الاستثناء لعلاقات ManyToOne.


نعم، رأيت ذلك.في الحقيقة، لقد استخدمت حل القراءة فقط لحالتي.لكن سؤالي كان "لماذا..." :).أعلم أن هناك تفسيرًا قدمه أحد أعضاء فريق السبات.لم أتمكن من العثور عليه ولهذا السبب سألت.

أريد أن أعرف الدافع وراء قرار التصميم هذا.

(إذا كنت مهتمًا بكيفية مواجهة هذه المشكلة:لقد ورثت مشروعًا تم إنشاؤه باستخدام السبات 3.لقد كان Jboss 4.0.something + hibernate موجودًا بالفعل (يمكنك تنزيله معًا).كنت أنقل هذا المشروع إلى Jboss 4.2.2 واكتشفت أن هناك تعيينات موروثة لـ "@OneToMany MappedBy" وأنها تعمل بشكل جيد على الإعداد القديم...)

هل كانت مفيدة؟

المحلول

أعتقد أنه قرار حكيم اتخذه فريق السبات.يمكن أن يكونوا أقل غطرسة وأن يوضحوا سبب تنفيذ الأمر بهذه الطريقة، ولكن هذه هي الطريقة التي يعمل بها إيمانويل وكريس وجافين.:)

دعونا نحاول فهم المشكلة.أعتقد أن مفاهيمك "تكذب".أولا تقول أن الكثير مشكلةترتبط الناس.ولكن، بعد ذلك تقول ذلك شخص لديك الكثير مشكلة قبيحةs (ولا علاقة لها بغيرها مشكلةس).هناك خطأ ما في هذا التصميم.

تخيل كيف سيتم تعيينها إلى قاعدة البيانات.لديك وراثة جدول واحد، لذلك:

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

كيف سيتم وضع السبات لفرض إنشاء قاعدة البيانات مشكلة تتعلق فقط الناس إذا كان type.problemType يساوي UP؟هذه مشكلة صعبة للغاية لحلها.لذا، إذا كنت تريد هذا النوع من العلاقات، يجب أن تكون كل فئة فرعية في جدولها الخاص.وهذا ما @MappedSuperclass يفعل.

ملاحظة.:آسف على الرسم القبيح :D

نصائح أخرى

في حالتي كنت أرغب في استخدام نوع الوراثة SINGLE_TABLE، لذلك لم يكن استخدام @MappedSuperclass خيارًا.

ما ينجح، على الرغم من أنه ليس نظيفًا جدًا، هو إضافة ملكية السبات @أين جملة إلى اقتران @OneToMany لفرض النوع في الاستعلامات:

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

لسوء الحظ، وفقا للسبات توثيق "يتم تجاهل خصائص من الفئات الفائقة التي لم يتم تعيينها كـ appedsuperClass." ركضت ضد هذا أيضا.كان الحل الذي توصلت إليه هو تمثيل الميراث المطلوب من خلال الواجهات بدلاً من وحدات الكيان نفسها.

في حالتك، يمكنك تحديد ما يلي:

public interface Problem {
    public Person getPerson();
}

public interface UglyProblem extends Problem {
}

ثم قم بتنفيذ هذه الواجهات باستخدام فئة فائقة مجردة وفئتين فرعيتين للكيان:

@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 {
}

كميزة إضافية، إذا قمت بالتعليمات البرمجية باستخدام الواجهات بدلاً من وحدات الكيان الفعلية التي تنفذ تلك الواجهات، فإن ذلك يجعل من السهل تغيير التعيينات الأساسية لاحقًا (أقل خطر كسر التوافق).

أعتقد أنك بحاجة إلى التعليق الخاص بك مشكلة فئة فائقة مع @MappedSuperclass بدلاً من @كيان.

لقد اكتشفت كيفية حل مشكلة OneToMany MappedBy.

في الفئة المشتقة UglyProblem من المنشور الأصلي.يجب أن تكون طريقة رد الاتصال في الفئة المشتقة وليس في الفئة الأصل.

@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;
}

وجدت الصلصة السرية لاستخدام السبات على الأقل. http://docs.jboss.org/hibernate/stable/annotations/api/org/hibernate/annotations/ForceDiscriminator.html @ForceDiscriminator يجعل @OneToMany يكرم المُميز

يتطلب التعليقات التوضيحية للإسبات.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top