سؤال

ال JPA (API Java Persistence) لها طريقتان مختلفتان لتحديد مفاتيح الكيان المركبة: @IdClass و @EmbeddedId.

أنا أستخدم كلا التعليقات التوضيحية على كياناتي المعينة ، لكن اتضح أنهما فوضى كبيرة للأشخاص الذين ليسوا على دراية بهم JPA.

أريد تبني طريقة واحدة فقط لتحديد المفاتيح المركبة. أيهما هو الأفضل حقًا؟ لماذا ا؟

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

المحلول

أنا أعتبر ذلك @EmbeddedId ربما يكون أكثر مطوّلة لأنه مع @IdClass لا يمكنك الوصول إلى كائن المفتاح الأساسي بأكمله باستخدام أي مشغل للوصول إلى الحقل. باستخدام @EmbeddedId يمكنك أن تفعل مثل هذا:

@Embeddable class EmployeeId { name, dataOfBirth }
@Entity class Employee {
  @EmbeddedId EmployeeId employeeId;
  ...
}

هذا يعطي فكرة واضحة للحقول التي تجعل المفتاح المركب لأنه يتم تجميعها جميعًا في فئة يتم الوصول إليها في مشغل الوصول الميداني.

فرق آخر مع @IdClass و @EmbeddedId هو عندما يتعلق الأمر بكتابة HQL:

مع @IdClass انت تكتب:

select e.name from Employee e

ومع @EmbeddedId لديك لكتابة:

select e.employeeId.name from Employee e

عليك أن تكتب المزيد من النص لنفس الاستعلام. قد يجادل البعض بأن هذا يختلف عن لغة أكثر طبيعية مثل اللغة التي تروج لها IdClass. لكن في معظم الأوقات التي تتفهم من الاستعلام أن الحقل المعطى هو جزء من المفتاح المركب هو مساعدة لا تقدر بثمن.

نصائح أخرى

لقد اكتشفت مثيلًا اضطررت فيه إلى استخدام inmbeddedid بدلاً من corclass. في هذا السيناريو ، يوجد جدول انضمام يحتوي على أعمدة إضافية محددة. حاولت حل هذه المشكلة باستخدام IDClass لتمثيل مفتاح الكيان الذي يمثل صفوفًا صريحًا في جدول الانضمام. لم أستطع تشغيلها بهذه الطريقة. والحمد لله "Java Persistence with Hibernate" لديه قسم مخصص لهذا الموضوع. كان أحد الحلول المقترحة مشابهاً جدًا لي ولكنه يستخدم embeddedid بدلاً من ذلك. قمت بنمذجة الأشياء الخاصة بي بعد تصرفها الآن في الكتاب بشكل صحيح.

هناك ثلاث استراتيجيات لاستخدام مفتاح أساسي مركب:

  • ضع علامة على ذلك @Embeddable وأضف إلى خاصية الكيان من الفئة A @Id.
  • أضف إلى خاصية كيانك من الدرجة A @EmbeddedId.
  • أضف خصائص إلى فئة الكيان الخاصة بك لجميع حقولها ، ضع علامة عليها @Id، ووضع علامة على فئة الكيان الخاصة بك مع @IdClass, ، تزويد فئة الفئة الرئيسية الخاصة بك.

استخدام @Id مع فئة تحمل علامة @Embeddable هو النهج الأكثر طبيعية. ال @Embeddable يمكن استخدام TAG للقيم الرئيسية غير الابتدائية على أي حال. يسمح لك بمعالجة المفتاح الأساسي المركب كخاصية واحدة ، ويسمح بإعادة استخدام @Embeddable الفصل في الجداول الأخرى.

النهج الأكثر طبيعية هو استخدام @EmbeddedId بطاقة شعار. هنا ، لا يمكن استخدام فئة المفاتيح الأساسية في الجداول الأخرى لأنها ليست @Embeddable الكيان ، لكنه يسمح لنا بمعالجة المفتاح كسمة واحدة لبعض الفئات.

أخيرًا ، استخدام @IdClass و @Id تتيح لنا التعليقات التوضيحية تعيين فئة المفاتيح الأساسية المركبة باستخدام خصائص الكيان نفسه المقابل لأسماء الخصائص في الفئة الرئيسية. يجب أن تتوافق الأسماء (لا توجد آلية لتجاوز هذا) ، ويجب أن يحترم الطبقة الرئيسية الأساسية نفس الالتزامات كما هو الحال مع التقنيتين الأخريين. الميزة الوحيدة لهذا النهج هي قدرتها على "إخفاء" استخدام فئة المفاتيح الأساسية من واجهة الكيان المرفق. ال @IdClass يأخذ التعليق التوضيحي معلمة قيمة لنوع الفئة ، والتي يجب أن تكون الفئة المراد استخدامها كمفتاح أساسي مركب. يجب شرح الحقول التي تتوافق مع خصائص فئة المفاتيح الأساسية المراد استخدامها @Id.

المرجعي: http://www.apress.com/us/book/9781430228509

بقدر ما أعرف ما إذا كان PK المركب الخاص بك يحتوي @IdClass

مع @EmbeddedId عليك تحديد رسم الخرائط لعمود FK الخاص بك مرتين ، Onece في @Embeddedable ومرة واحدة مثل IE @ManyToOne أين @ManyToOne يجب أن تكون للقراءة فقط (@PrimaryKeyJoinColumn) لأنه لا يمكن أن يكون لديك عمود واحد في متغيرين (صراعات محتملة).
لذلك عليك تعيين FK الخاص بك باستخدام نوع بسيط في @Embeddedable.

على الموقع الآخر باستخدام @IdClass يمكن التعامل مع هذا الموقف أسهل بكثير كما هو موضح في المفاتيح الأولية من خلال علاقات OneToOne و ManyToone:

مثال JPA 2.0 ManyToone معرف التعليق

...
@Entity
@IdClass(PhonePK.class)
public class Phone {

    @Id
    private String type;

    @ManyToOne
    @Id
    @JoinColumn(name="OWNER_ID", referencedColumnName="EMP_ID")
    private Employee owner;
    ...
}

مثال فئة jpa 2.0 معرف

...
public class PhonePK {
    private String type;
    private long owner;

    public PhonePK() {}

    public PhonePK(String type, long owner) {
        this.type = type;
        this.owner = owner;
    }

    public boolean equals(Object object) {
        if (object instanceof PhonePK) {
            PhonePK pk = (PhonePK)object;
            return type.equals(pk.type) && owner == pk.owner;
        } else {
            return false;
        }
    }

    public int hashCode() {
        return type.hashCode() + owner;
    }
}

أعتقد أن الميزة الرئيسية هي أنه يمكننا استخدام @GeneratedValue للمعرف عند استخدام @IdClass؟ أنا متأكد من أننا لا نستطيع استخدام @GeneratedValue إلى عن على @EmbeddedId.

يجب ألا يحتوي المفتاح المركب على @Id الممتلكات متى @EmbeddedId يستخدم.

مع تضمينك ، يمكنك استخدام البند في HQL ، على سبيل المثال: FROM Entity WHERE id IN :ids عندما يكون المعرف عبارة FROM Entity WHERE idPartA = :idPartA0 AND idPartB = :idPartB0 .... OR idPartA = :idPartAN AND idPartB = :idPartBN

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