문제

JPA에는 엔티티 클래스 내에서 열거 모음을 매핑하는 방법이 있습니까? 아니면 유일한 해결책은 다른 도메인 클래스로 열거를 래핑하고 컬렉션을 매핑하는 데 사용하는 것입니까?

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

다른 팁

Andy의 답변의 링크는 JPA 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;

설명 된대로 게으른 하중을 피하기 위해서는 열망하는 부하가 필요합니다. 여기.

java.util.regularenumset의 약간의 수정을 사용하여 지속적인 열거를 사용하고 있습니다.

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

장점 :

  • 코드에 세트하는 유형의 안전하고 성능 열거로 작업 (참조 java.util.EnumSet 설명을 위해)
  • 세트는 데이터베이스에서 하나의 숫자 열입니다.
  • 모든 것이 평범한 JPA입니다 (공급자별로 특정 사항 없음 사용자 정의 유형)
  • 다른 솔루션과 비교하여 동일한 유형의 새로운 분야의 쉽고 짧은 선언

단점 :

  • 코드 복제 (RegularEnumSet 그리고 PersistentEnumSet 거의 동일합니다)
    • 당신은 결과를 포장 할 수 있습니다 EnumSet.noneOf(enumType) 당신의 PersistenEnumSet, 선언하다 AccessType.PROPERTY 반사를 사용하여 읽고 쓰는 두 가지 액세스 방법을 제공합니다. elements 필드
  • 지속적인 세트에 저장 해야하는 모든 열거 클래스에 추가 세트 클래스가 필요합니다.
    • 귀하의 지속성 제공 업체가 공개 생성자없이 임베드블을 지원하는 경우 추가 할 수 있습니다. @Embeddable 에게 PersistentEnumSet 추가 클래스를 떨어 뜨립니다 (... interests = new PersistentEnumSet<>(InterestsEnum.class);)
  • 당신은 an을 사용해야합니다 @AttributeOverride, 내 예에서 주어진대로, 당신이 둘 이상이있는 경우 PersistentEnumSet 귀하의 엔티티에서 (그렇지 않으면 둘 다 동일한 열 "요소"에 저장됩니다)
  • 의 접근 values() 생성자에 반사되는 것은 최적이 아니지만 (특히 성능을 볼 때) 다른 두 옵션에는 단점도 있습니다.
    • 와 같은 구현 EnumSet.getUniverse() a를 사용합니다 sun.misc 수업
    • 매개 변수로 값 배열을 제공하는 것은 주어진 값이 올바른 값이 아닐 위험이 있습니다.
  • 최대 64 개의 값을 가진 열거 만 지원됩니다 (실제로 단점입니까?)
    • 대신 BigInteger를 사용할 수 있습니다
  • 기준 쿼리 또는 JPQL에서 요소 필드를 사용하기는 쉽지 않습니다.
    • 데이터베이스가 지원하는 경우 바이너리 연산자 또는 적절

JPA 컬렉션은 일대일 또는 다수의 관계를 나타내며 다른 엔티티 만 포함 할 수 있습니다. 죄송하지만, 그 열거를 엔티티에 감싸 야합니다. 당신이 그것에 대해 생각한다면, 당신은 어쨌든이 정보를 저장하려면 일종의 ID 필드와 외국 키가 필요합니다. 그것은 당신이 쉼표로 구분 된 목록을 문자열로 보관하는 것과 같은 미친 일을하지 않는 한입니다 (이것을하지 마십시오!).

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top