سؤال

هل هناك طريقة في JPA إلى الخريطة مجموعة من Enums داخل الكيان الصف ؟ أو الحل الوحيد هو التفاف التعداد مع مجال آخر الصف واستخدامها لتعيين جمع ؟

@Entity
public class Person {
    public enum InterestsEnum {Books, Sport, etc...  }
    //@???
    Collection<InterestsEnum> interests;
}

أنا باستخدام السبات JPA التنفيذ ، ولكن بالطبع يفضل تنفيذ الملحد الحل.

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

المحلول

وباستخدام السبات يمكنك القيام به

@CollectionOfElements(targetElement = InterestsEnum.class)
@JoinTable(name = "tblInterests", joinColumns = @JoinColumn(name = "personID"))
@Column(name = "interest", nullable = false)
@Enumerated(EnumType.STRING)
Collection<InterestsEnum> interests;

نصائح أخرى

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

@Entity
public class Person {
    @ElementCollection(targetClass=InterestsEnum.class)
    @Enumerated(EnumType.STRING) // Possibly optional (I'm not sure) but defaults to ORDINAL.
    @CollectionTable(name="person_interest")
    @Column(name="interest") // Column name in person_interest
    Collection<InterestsEnum> interests;
}

وكنت قادرا على تحقيق ذلك بهذه الطريقة بسيطة:

@ElementCollection(fetch = FetchType.EAGER)
Collection<InterestsEnum> interests;
مطلوب

وتحميل حرصا من أجل تجنب تحميل كسول inizializing الخطأ كما أوضح <لأ href = "https://stackoverflow.com/questions/11746499/solve-failed-to-lazily-initialize-a-collection-of- الدور استثناء "> هنا .

أنا باستخدام تعديل طفيف جافا.util.RegularEnumSet إلى استمرار EnumSet:

@MappedSuperclass
@Access(AccessType.FIELD)
public class PersistentEnumSet<E extends Enum<E>> 
    extends AbstractSet<E> {
  private long elements;

  @Transient
  private final Class<E> elementType;

  @Transient
  private final E[] universe;

  public PersistentEnumSet(final Class<E> elementType) {
    this.elementType = elementType;
    try {
      this.universe = (E[]) elementType.getMethod("values").invoke(null);
    } catch (final ReflectiveOperationException e) {
      throw new IllegalArgumentException("Not an enum type: " + elementType, e);
    }
    if (this.universe.length > 64) {
      throw new IllegalArgumentException("More than 64 enum elements are not allowed");
    }
  }

  // Copy everything else from java.util.RegularEnumSet
  // ...
}

هذه الفئة هي الآن قاعدة من التعداد مجموعات:

@Embeddable
public class InterestsSet extends PersistentEnumSet<InterestsEnum> {
  public InterestsSet() {
    super(InterestsEnum.class);
  }
}

وأن مجموعة يمكنني استخدامها في بلدي الكيان:

@Entity
public class MyEntity {
  // ...
  @Embedded
  @AttributeOverride(name="elements", column=@Column(name="interests"))
  private InterestsSet interests = new InterestsSet();
}

المزايا:

  • العمل مع نوع آمنة و performant التعداد المحددة في التعليمات البرمجية الخاصة بك (انظر java.util.EnumSet للحصول على وصف)
  • مجموعة واحدة فقط الرقمية عمود في قاعدة البيانات
  • كل شيء عادي JPA (أي مزود محددة أنواع مخصصة)
  • من السهل (قصيرة) إعلان حقول جديدة من نفس النوع ، بالمقارنة مع الحلول الأخرى

السلبيات:

  • رمز الازدواجية (RegularEnumSet و PersistentEnumSet هي تقريبا نفس)
    • يمكنك التفاف نتيجة EnumSet.noneOf(enumType) في PersistenEnumSet, تعلن AccessType.PROPERTY و توفر طرق الوصول التي تستخدم انعكاس قراءة وكتابة elements المجال
  • مجموعة إضافية من الدرجة المطلوبة لكل التعداد الفئة التي يجب أن يتم تخزينها في استمرار تعيين
    • إذا كان استمرار مزود يدعم embeddables دون منشئ العام ، @Embeddable إلى PersistentEnumSet وإسقاط دراسية إضافية (... interests = new PersistentEnumSet<>(InterestsEnum.class);)
  • يجب عليك استخدام @AttributeOverride, كما في بلدي على سبيل المثال ، إذا كان لديك أكثر من واحد PersistentEnumSet في كيان (وإلا كلاهما سيكون المخزنة على نفس العمود "العناصر")
  • وصول values() مع التفكير في منشئ ليس الأمثل (لا سيما عند النظر في الأداء) ، ولكن اثنين من الخيارات الأخرى لها سلبياتها أيضا:
    • تنفيذ مثل EnumSet.getUniverse() يجعل من استخدام sun.misc الدرجة
    • توفير قيم مجموعة المعلمة وقد المخاطر التي تعطى القيم غير الصحيحة منها
  • فقط enums مع ما يصل إلى 64 القيم معتمدة (هل هذا حقا عيب?)
    • هل يمكن استخدام BigInteger بدلا من ذلك
  • ليس من السهل أن استخدام العناصر الميدانية في معايير الاستعلام أو JPQL
    • هل يمكن استخدام ثنائي المشغلين أو قناع بت عمود مع وظائف مناسبة ، إذا كانت قاعدة البيانات الخاصة بك يدعم ذلك

والمجموعات في JPA تشير الى واحد لكثير أو كثير إلى كثير من العلاقات وأنها يمكن أن تحتوي فقط على الكيانات الأخرى. آسف، ولكن كنت بحاجة إلى التفاف تلك تتضمن التعدادات في كيان. إذا كنت تفكر في ذلك، وكنت بحاجة الى بعض النوع من حقل معرف ومفتاح خارجي لتخزين هذه المعلومات على أي حال. وهذا هو ما لم تفعل شيئا مثل مجنون متجر قائمة مفصولة بفواصل في سلسلة (لا تفعل هذا!).

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