문제

내가 객체 데이터베이스를 사용하는 것에 대해 계속 혼란 스러웠던 한 가지는 DB4O 일반적으로 SQL/PL-SQL에 의해 처리되는 복잡한 마이그레이션을 처리하는 방법입니다.

예를 들어 My_Users라는 관계형 데이터베이스에 테이블이 있다고 상상해보십시오. 원래 "full_name"이라는 열이 있었는데, 이제 소프트웨어가 v2에 있으므로이 열을 제거하고 빈 공간에서 전체 이름을 분할하고 "First_name"이라는 열에 첫 번째 부분을 넣고 열에 두 번째 부분을 넣습니다. last_name으로 명명되었습니다. SQL에서는 "First_name"과 "Second_name"열을 간단히 채우고 "full_name"이라는 원래 열을 제거합니다.

DB4O와 같은 방법으로 어떻게해야합니까? user.class의 모든 객체를 찾는 스크립트를 작성하는 Java 프로그램을 작성하고 first_name 및 last_name을 설정하는 동안 full_name을 null로 설정하십시오. 다음 SVN 커밋을 할 때 full_name에 해당하는 필드/Bean-Property가 없을 때 이것이 문제가 될까요? "스키마"가 변경되는 프로덕션 애플리케이션에서 사용하는 것처럼 보입니다. 버전 X에서 버전 X+1으로 데이터를 마이그레이션 한 다음 버전 X+2에서는 실제로 내가하려는 속성을 제거하는 스크립트를 작성하려고합니다. 더 이상 내 유형의 일부가 아닌 속성을 수정하기 위해 Java 스크립트를 작성할 수 없으므로 버전 X+1을 제거하십시오.

문제의 일부는 RDBMS가 간단한 사례 무의미한 문자열 기반 이름을 기반으로하는 객체를 해결하는 것 같습니다. /setter/field는 런타임에로드 된 클래스의 구성원이 아니므로 본질적으로 동일한 스크립트에 코드의 2 개 버전이 있어야합니다 (HMM, 사용자 정의 클래스 로더는 통증처럼 들립니다). 다른 패키지 (지저분한 소리) 또는 내가 언급 한 버전 x+1 x+2 전략을 사용합니다 (더 많은 계획이 필요합니다). 아마도 DB4O 문서에서 얻지 못한 분명한 해결책이있을 것입니다.

어떤 아이디어? 바라건대 이것은 의미가 있습니다.

도움이 되었습니까?

해결책

먼저 DB4O는 'Simple'을 처리합니다. 필드를 자동으로 추가하거나 제거하는 것과 같은 시나리오. 필드를 추가 할 때 기존의 모든 객체에는 기본값이 저장되어 있습니다. 필드를 제거하면 기존 객체의 데이터가 여전히 데이터베이스에 있으며 여전히 액세스 할 수 있습니다. 이름 변경 필드 등이 있습니다 특별한 'Refactoring'호출.

이제 시나리오는 다음과 같은 일을합니다.

  1. 필드 'full_name'을 제거하고 새 필드를 추가하십시오 'First_name'및 'second_name'
  2. 모든 '주소'를 반복하십시오
  3. 'StoredClass'-Api를 통해 이전 필드에 액세스하십시오
  4. 분할, 변경, 업데이트 등 값. 새 필드에 새 값을 설정하고 개체를 저장하십시오.

우리가 '주소'클래스가 있다고 가정 해 봅시다. 'full_name'필드가 제거되었습니다. 이제 우리는 그것을 'FirstName'과 'Surname'에 복사하지 않아야합니다. 그런 다음 이렇게 갈 수 있습니다 (Java) :

    ObjectSet<Address> addresses = db.query(Address.class);
    StoredField metaInfoOfField = db.ext().storedClass(Address.class).storedField("full_name", String.class);
    for (Address address : addresses) {
        String fullName = (String)metaInfoOfField.get(address);
        String[] splitName = fullName.split(" ");
        address.setFirstname(splitName[0]);
        address.setSurname(splitName[1]);
        db.store(address);
    }

당신이 제안했듯이, 당신은 각 버전-펌프에 대해 마이그레이션 코드를 작성합니다. 필드는 더 이상 수업의 일부가 아니며 위와 같은 'Storedfield'-api로 액세스해야합니다.

당신은 모든 '저장된'클래스 목록을 ObjectContainer.ext().storedClasses(). 와 함께 StoredClass.getStoredFields() 모든 상점 필드 목록을 얻을 수 있습니다. Mather는 수업에 더 이상 필드가 존재하지 않습니다. 클래스가 더 이상 존재하지 않으면 여전히 객체를 가져 와서 'genericobject'클래스를 통해 액세스 할 수 있습니다.

업데이트 : 데이터베이스가 다중 버전 단계에서 마이그레이션 해야하는 복잡한 시나리오.

예를 들어, 버전 v3에서 주소는 완전히 다르게 보입니다. 따라서 V1에서 V2의 '마이그레이션 스크립트'에는 더 이상 필요한 필드가 없습니다 (내 예에서는 FirstName 및 Surename). 나는 이것을 처리 할 수있는 여러 가지 가능성이 있다고 생각합니다.

  1. (이 아이디어에 대한 Java를 가정합니다. 확실히 .NET에는 동등한 것이 있습니다). 마이그레이션 단계를 만들 수 있습니다 그루비 스크립트. 따라서 각 스크립트는 각 스크립트가 다른 스크립트를 방해하지 않습니다. 그런 다음 마이그레이션에 필요한 클래스를 '클래스'를 정의합니다. 따라서 각 마이그레이션에는 자체 마이그레이션 계급이 있습니다. 와 함께 별명 그루비 마이그레이션 클래스를 실제 자바 클래스에 묶을 것입니다.
  2. 복잡한 시나리오에 대한 리팩토링 클래스 생성. 또한이 클래스를 묶습니다 별명.

다른 팁

나는 내 인생에서 너무 많은 데이터를 리팩터링하지 않았기 때문에 여기서 약간의 야생 샷을하고 있습니다.

당신은 이상한 비교를하고 있습니다 : DB를 '뜨거운 이동'하고 싶다면 아마도 x+1, x+2 당신이 묘사 한 버전화 접근법이지만, 나는 정말로 모른다 - 나는 DB 전문가가 아니기 때문에 SQL로 이것을하는 방법을 모른다.

그러나 'Cold'를 마이그레이션하는 경우 이전 데이터에서 새 객체를 인스턴스화하여 새 개체를 저장하고 매장의 각 개체에 대한 이전 객체를 삭제하여 한 단계로 수행 할 수 있습니다. 보다 DB4O 참조.

그러나 솔직히 : RDBMS의 동일한 프로세스도 복잡합니다. 실제로 작업을 수행하기 위해 제약 체크를 비활성화해야합니다 (및 아마도 트리거 등). -세상 사례. 결국, 문자열 분할은 너무 쉽게 이득이 거의 없을 것입니다.

SQL에서 나는 단순히 "First_name"및 "second_name"열을 채 웁니다.

예, a 단순한 문자열 분할 작업, 가능합니다 간단히 그렇게. 그러나 일반적인 리팩토링 시나리오에서는 SQL로 쉽게 표현되지 않을 수 있고 복잡한 계산이 필요하거나 외부 데이터 소스가 필요할 수있는 크고 복잡한 규칙 세트를 기반으로 객체를 재 구조화합니다.

그렇게하려면 코드도 작성해야합니다.

결국, 나는 두 프로세스에서 너무 큰 차이를 보지 못합니다. 당신은 항상 라이브 데이터에주의를 기울여야하며, 두 경우 모두 백업을 할 것입니다. 리팩토링은 재미 있지만 지속성은 까다 롭기 때문에 동기화하는 것은 어쨌든 도전입니다.

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