문제

레거시 데이터베이스 테이블에는 C1, C2, C3, C100 또는 M1, M2, M3, M100과 같은 번호가 매겨진 열이 있습니다.
이 열은 BLOB 데이터를 나타냅니다.

이 데이터베이스에서는 아무것도 변경할 수 없습니다.

JPA Embeddable을 사용하여 모든 열을 단일 필드에 매핑합니다.그런 다음 포함하는 동안 100개의 재정의 주석을 사용하여 이름을 재정의합니다.

최근에 우리는 Hibernate로 전환했고 다음과 같은 것을 발견했습니다. 사용자 컬렉션 유형 그리고 복합사용자 유형.그러나 나는 나와 가까운 사용 사례를 찾지 못했습니다.

열 묶음을 컬렉션에 매핑할 수 있도록 Hibernate를 사용하여 일부 사용자 유형을 구현하는 것이 가능합니까? 추가 문의 없이?

편집하다:
아시다시피 열 이름은 테이블마다 다를 수 있습니다.이 유형을 사용할 때마다 모든 @Columns를 지정할 필요 없이 "LegacyArray"와 같은 유형을 만들고 싶습니다.하지만 대신에 나는

  @Type(type = "LegacyArrayUserType",
        parameters =
   {
      @Parameter(name = "prefix", value = "A"),
      @Parameter(name = "size", value = "128")
   })
   List<Integer> legacyA;

  @Type(type = "LegacyArrayUserType",
        parameters =
   {
      @Parameter(name = "prefix", value = "B"),
      @Parameter(name = "size", value = "64")
   })
   List<Integer> legacyB;
도움이 되었습니까?

해결책

나는 이것을 할 몇 가지 방법을 생각할 수 있습니다.

1. 정규화 된 테이블 구조를 시뮬레이션하는 수집 정보에 대한 뷰를 작성하고이를 컬렉션으로 최대 절전 모드로 매핑하십시오.

기존 테이블이 호출되었다고 가정합니다 primaryentity, 나는 다음과 유사한 뷰를 만들 것입니다.

-- untested SQL...
create view childentity as
(select primaryentity_id, c1 from primaryentity union
select primaryentity_id, c2 from primaryentity union
select primaryentity_id, c3 from primaryentity union
--...
select primaryentity_id, c100 from primaryentity)

이제 최대 절전 모드의 관점에서 childentity 외국 키가있는 정규화 된 테이블입니다. primarykey. 매핑 이것은 매우 간단해야하며 여기에서 다루어집니다.

이 접근법의 이점 :

  • 최대 절전 모드의 관점에서 테이블은 정규화되며 상당히 간단한 매핑입니다.
  • 기존 테이블에 대한 업데이트가 없습니다

단점 :

  • 데이터는 읽기 전용이며 귀하의 견해를 업데이트 가능한 방식으로 정의 할 수 있다고 생각하지 않습니다 (틀릴 수 있습니다).
  • 데이터베이스를 변경 해야하는 경우 많은보기를 만들어야 할 수도 있습니다.

또는 DBA가 데이터베이스에보기를 추가 할 수 없거나 업데이트를 수행 해야하는 경우 :


2. 최대 절전 모드를 사용하십시오 동적 모델 매핑 시설 C1, C2, C3 특성을 지도, 당신에게 코드를 가지고 있습니다 다오 레이어 맵과 컬렉션 속성 사이에 적절한 대화를 수행합니다.

나는 이것을 직접 한 적이 없지만, 최대 절전 모드는 당신이 테이블을 해시 맵에 매핑 할 수 있다고 생각합니다. 동적 인 최대 절전 모드가 어떻게이를 수행 할 수 있는지 잘 모르겠습니다 (즉, 단순히 테이블 이름을 지정하고 최대 절전 모드가 모든 열을 자동으로 매핑 할 수 있습니까?).

그러나이 접근법을 사용하는 경우 사용하십시오. 데이터 액세스 객체 패턴 및 내부 구현 (해시 맵 사용)이 클라이언트 코드에 숨겨져 있는지 확인하십시오. 또한 컬렉션의 크기가 사용 가능한 열 수를 초과하지 않는지 데이터베이스에 작성하기 전에 확인하십시오.

이 접근법의 이점 :

  • 데이터베이스를 전혀 변경하지 않습니다
  • 데이터는 업데이트 가능합니다
  • O/R 매핑은 비교적 간단합니다

단점 :

  • 적절한 유형을 매핑하기 위해 DAO 층의 많은 배관
  • 미래에 변할 수있는 실험 최대 절전 모드 기능을 사용합니다.

다른 팁

개인적으로 디자인이 망가지는거 같아요 첫 번째 정규형 관계형 데이터베이스의 경우.C101이나 M101이 필요하면 어떻게 되나요?스키마를 다시 변경하시겠습니까?나는 그것이 매우 방해가 된다고 생각한다.

믹스에 Hibernate를 추가하면 상황은 더욱 악화됩니다.C101이나 M101을 추가한다는 것은 Java 객체, Hibernate 매핑, 모든 것을 변경해야 한다는 것을 의미합니다.

C, M 테이블과 1:m 관계가 있는 경우 행을 추가하면 방금 인용한 사례를 처리할 수 있습니다.Java 객체에 Collection<C> 또는 Collection<M>이 포함되어 있습니다.당신의 Hibernate 매핑은 변경되지 않는 일대다입니다.

권장되지 않는 디자인이기 때문에 귀하의 경우에 맞는 Hibernate 예제를 볼 수 없는 이유일 수도 있습니다.

꼭 해야 한다면 아마도 살펴보아야 할 것입니다. 최대 절전 모드 구성 요소 매핑.

업데이트:이것이 유산이라는 사실은 정당하게 언급됩니다.첫 번째 정규 형식을 언급하는 이유는 질문을 게시한 사람과 마찬가지로 나중에 이 질문을 찾을 수 있는 다른 사람들에게도 중요합니다.나는 이 디자인이 "좋다"고 조용히 주장하는 방식으로 질문에 대답하고 싶지 않습니다.

찾고 있는 것의 이름을 아는 것이 검색할 때 핵심이 될 수 있기 때문에 Hibernate 컴포넌트 매핑을 지적하는 것은 적절합니다.Hibernate는 객체 모델이 매핑하는 관계형 모델보다 더 세밀하게 세분화되도록 허용합니다.비정규화된 스키마(예: 더 큰 Person 개체의 일부인 Name 및 Address 개체)를 자유롭게 모델링할 수 있습니다.그것은 그들이 그러한 기술을 부여하는 이름입니다.다른 예를 찾는 데도 도움이 될 수 있습니다.

여기서 당신의 문제를 오해한다면 죄송합니다. 최대 절전 모드에 대해 많이 모릅니다. 그러나 데이터베이스에서 선택하는 동안 원하는 것과 같은 것을 얻기 위해 연결 할 수 없습니까?

처럼:

SELECT whatever
     , C1||C2||C3||C4||...||C100 AS CDATA
     , M1||M2||M3||M4||...||M100 AS MDATA
FROM ...
WHERE ...

(물론, 연결 연산자는 RDBMS에 따라 다릅니다.)

[편집] 나는 CompositeUserType. 여기에 예가 있습니다.."Java Persistence With Hibernate" 책의 228f 페이지에도 좋은 예가 있습니다.

이를 통해 많은 열을 Java의 단일 객체로 처리할 수 있습니다.

매핑은 다음과 같습니다.

@org.hibernate.annotations.Columns(columns = {
    @Column(name="C1"),
    @Column(name="C2"),
    @Column(name="C3"),
    ...
})
private List<Integer> c;

Hibernate는 일반 쿼리 중에 모든 열을 한 번에 로드합니다.

귀하의 경우 목록의 int 값을 고정된 수의 열에 복사해야 합니다. nullSafeSet.유사 코드:

for (int i=1; i<numColumns; i++)
    if (i < list.size())
        resultSet.setInt(index+i, list.get(i));
    else
        resultSet.setNull(index+i, Hibernate.INTEGER.sqlType());

~ 안에 nullSafeGet 열이 NULL인 경우 목록을 생성하고 요소 추가를 중지해야 합니다.추가 안전을 위해 열 수를 초과하여 증가하는 것을 허용하지 않는 고유한 목록 구현을 만드는 것이 좋습니다. ArrayList 그리고 재정의 ensureCapacity()).

[EDIT2] 모든 @Column 주석을 입력하지 않으려면 해당 주석에 대한 코드 생성기를 사용하세요.이는 이름과 번호를 지정하고 @Column(...)을 System.out에 인쇄하는 스크립트만큼 간단할 수 있습니다.스크립트가 실행된 후 데이터를 소스에 잘라내어 붙여넣기만 하면 됩니다.

유일한 다른 해결책은 런타임에 해당 정보를 구축하기 위해 내부 Hibernate API에 액세스하는 것이지만 해당 API는 내부이므로 많은 것들이 비공개입니다.Java 리플렉션을 사용할 수 있으며 setAccessible(true) 그러나 그 코드는 아마도 다음 Hibernate 업데이트에서는 살아남지 못할 것입니다.

당신이 사용할 수있는 UserTypes 주어진 수의 열을 원하는 모든 유형에 매핑합니다. 컬렉션의 예를 들어 (예를 들어)가 항상 알려진 수의 항목으로 크기가 제한되는 경우 컬렉션 일 수 있습니다.

최대 절전 모드를 사용한 지 얼마되지 않아서 (> 3 년) 꽤 녹슬었지만 매우 쉬운 일을 기억합니다. 당신의 BespokeUserType 수업이 통과됩니다 ResultSet 에게 수화 시키다 그것으로부터 당신의 대상.

나도 최대 절전 모드를 사용한 적이 없습니다.

해석 된 언어로 작은 프로그램을 작성하는 것이 좋습니다 (예 : 파이썬) 명령 인 것처럼 문자열을 실행할 수 있습니다. 수동으로하고 싶은 일을하는 데 지루한 작업을 수행하는 진술을 구축 할 수 있습니다.

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