객체 지속성 및 Java

객체 내구성 또는 지속성 은 데이터베이스에 객체를 저장하는 문제와 관련하여 자주 사용되는 용어입니다. 지속성은 트랜잭션 무결성으로 작동 할 것으로 예상되며 엄격한 조건이 적용됩니다. (트랜잭션 처리에 대한 자세한 내용은이 기사의 리소스 섹션을 참조하십시오.) 반면에 표준 언어 라이브러리 및 패키지를 통해 제공되는 언어 서비스에는 종종 트랜잭션 제약이 없습니다.

이 기사에서 볼 수 있듯이 간단한 Java 지속성은 언어 자체에서 비롯 될 가능성이 높고 정교한 데이터베이스 기능은 데이터베이스 공급 업체에서 제공 할 것이라는 증거가 있습니다.

어떤 물체도 섬이 아닙니다

현실 세계에서는 다른 물체와의 관계가없는 물체를 거의 찾을 수 없습니다. 개체는 개체 모델의 구성 요소입니다 . 객체 내구성 문제는 객체가 서로 관계에 의해 상호 연결되어 있다는 관찰을하면 객체 모델 내구성 및 분포 문제를 초월합니다.

데이터 스토리지에 대한 관계형 접근 방식은 유형별로 데이터를 집계하는 경향이 있습니다. 테이블의 행은 디스크에있는 동일한 유형의 개체의 물리적 집계를 나타냅니다. 객체 간의 관계는 여러 테이블에서 공유되는 키로 표현됩니다. 데이터베이스 구성을 통해 관계형 데이터베이스는 때때로 함께 사용될 가능성이있는 테이블을 데이터베이스 세그먼트와 같은 동일한 논리 파티션에 함께 배치 (또는 클러스터링 ) 할 수 있도록 허용 하지만 데이터베이스에 오브젝트 관계를 저장하는 메커니즘이 없습니다. 따라서 개체 모델을 구성하기 위해 이러한 관계는 테이블 조인 이라고하는 프로세스에서 런타임에 기존 키로 구성됩니다 . 이것은 관계형 데이터베이스의 잘 알려진 속성입니다.데이터 독립성 . 거의 모든 개체 데이터베이스 변형은 기존 관계형 데이터베이스에 비해 복잡한 개체 관계를 포함하는 시스템의 성능을 향상시키는 몇 가지 메커니즘을 제공합니다.

쿼리하거나 탐색하려면?

디스크에 개체를 저장할 때 탐색 액세스를 더 잘 수용하기 위해 관련 개체를 함께 배치하거나, ​​조건 자 기반 액세스 (쿼리)를 용이하게하기 위해 유형별로 개체를 집계하는 테이블과 같은 컬렉션에 개체를 저장하는 선택에 직면합니다. . 영구 저장소에서 개체의 공동 배치는 관계형 및 개체 지향 데이터베이스가 크게 다른 영역입니다. 쿼리 언어의 선택은 고려해야 할 또 다른 영역입니다. SQL (Structured Query Language) 및 그 확장은 술어 기반 액세스 메커니즘을 가진 관계형 시스템을 제공했습니다. OQL (Object Query Language)은 ODMG에 의해 표준화 된 SQL의 객체 변형이지만이 언어에 대한 지원은 현재 부족합니다. 다형성 메서드는 개체 컬렉션에 대한 의미 쿼리를 구성 할 때 전례없는 우아함을 제공합니다. 예를 들면다형성 행동을 상상해보십시오.acccount라고했습니다 isInGoodStanding. 양호한 상태의 모든 계정에 대해 Boolean true를 반환하고 그렇지 않으면 false를 반환 할 수 있습니다. 이제 inGoodStanding양호한 상태의 모든 계정에 대해 비즈니스 규칙에 따라 다르게 구현 되는 계정 모음을 쿼리하는 우아함을 상상해보십시오 . 다음과 같이 보일 수 있습니다.

setOfGoodCustomers = setOfAccounts.query(account.inGoodStanding());

기존의 여러 개체 데이터베이스는 C ++ 및 Smalltalk에서 이러한 쿼리 스타일을 처리 할 수 ​​있지만 더 큰 (예 : 500GB 이상) 컬렉션과 더 복잡한 쿼리 식에 대해서는 처리하기가 어렵습니다. Oracle 및 Informix와 같은 여러 관계형 데이터베이스 회사는 곧 동일한 결과를 얻기 위해 다른 SQL 기반 구문을 제공 할 것입니다.

지속성과 유형

객체 지향 언어 애호가는 지속성과 유형이 객체의 직교 속성이라고 말할 것입니다. 즉, 하나의 속성이 다른 속성에 영향을 주어서는 안되기 때문에 동일한 유형의 영구 및 임시 객체가 동일 할 수 있습니다. 대체보기는 지속성이 지속 가능한 개체에 의해서만 지원되는 동작이며 특정 동작은 지속성 개체에만 적용될 수 있습니다. 후자의 접근 방식은 지속 가능한 객체가 영구 스토리지에서 자신을 저장하고 검색하도록 지시하는 방법을 요구하는 반면, 전자는 종종 가상 메모리 시스템을 확장하여 애플리케이션에 전체 객체 모델을 원활하게 볼 수 있도록합니다.

정규화 및 언어 독립성

언어에서 동일한 유형의 객체는 인터페이스가 나타나는 순서에 관계없이 동일한 레이아웃의 영구 저장소에 저장되어야합니다. 개체 레이아웃을이 공통 형식으로 변환하는 프로세스를 집합 적으로 개체 표현의 표준화라고합니다. 정적 유형 (Java가 아님)을 사용하는 컴파일 된 언어에서 동일한 언어로 작성되었지만 다른 시스템에서 컴파일 된 객체는 영구 저장소에 동일하게 표시되어야합니다.

정규화의 확장은 언어 독립적 인 객체 표현을 다룹니다. 객체가 언어 독립적 인 방식으로 표현 될 수있는 경우 동일한 객체의 다른 표현이 동일한 영구 저장소를 공유 할 수 있습니다.

이 작업을 수행하는 한 가지 메커니즘은 IDL (인터페이스 정의 언어)을 통해 추가 수준의 간접 지정을 도입하는 것입니다. 개체 데이터베이스 인터페이스는 IDL 및 해당 데이터 구조를 통해 만들 수 있습니다. IDL 스타일 바인딩의 단점은 두 가지입니다. 첫째, 추가 수준의 간접 변환에는 항상 추가 수준의 변환이 필요하므로 시스템의 전체 성능에 영향을줍니다. 둘째, 특정 공급 업체에 고유하고 애플리케이션 개발자에게 유용 할 수있는 데이터베이스 서비스의 사용을 제한합니다.

유사한 메커니즘은 SQL 확장을 통해 개체 서비스를 지원하는 것입니다. 관계형 데이터베이스 공급 업체와 소규모 개체 / 관계형 공급 업체는이 접근 방식을지지합니다. 그러나 이러한 기업들이 오브젝트 스토리지를위한 프레임 워크를 형성하는 데 얼마나 성공적 일지는 아직 알 수 없습니다.

그러나 질문은 남아 있습니다. 객체 지속성은 객체 동작의 일부입니까 아니면 별도의 인터페이스를 통해 객체에 제공되는 외부 서비스입니까? 개체 컬렉션과 쿼리 방법은 어떻습니까? 관계형, 확장 된 관계형 및 객체 / 관계형 접근 방식은 언어 간의 분리를 옹호하는 경향이 있지만 객체 데이터베이스와 Java 언어 자체는 지속성을 언어의 본질적인 것으로 간주합니다.

직렬화를 통한 네이티브 Java 지속성

객체 직렬화는 스트림에 대한 Java 객체 및 기본 요소의 저장 및 검색을위한 Java 언어 별 메커니즘입니다. C ++ 객체를 직렬화하기위한 상용 타사 라이브러리가 한동안 존재했지만 C ++는 객체 직렬화를위한 기본 메커니즘을 제공 한 적이 없다는 점에 주목할 가치가 있습니다. Java의 직렬화를 사용하는 방법은 다음과 같습니다.

// 스트림 (예 : 파일)에 "foo"쓰기

// 1 단계. 출력 스트림 생성

// 즉, 바이트를 수신 할 버킷을 만듭니다.

FileOutputStream out = new FileOutputStream ( "fooFile");

// 2 단계. ObjectOutputStream 생성

// 즉, 호스를 만들고 머리를 양동이에 넣습니다.

ObjectOutputStream os = 새로운 ObjectOutputStream (out)

// 3 단계. 스트림에 문자열과 객체 쓰기

// 즉, 스트림이 버킷으로 흐르도록합니다.

os.writeObject ( "foo");

os.writeObject (new Foo ());

// 4 단계. 데이터를 대상으로 플러시합니다.

os.flush ();

Writeobject메서드는 foo와 전 이적 클로저, 즉 그래프 내에서 foo에서 참조 할 수있는 모든 객체를 직렬화합니다. 스트림 내에는 직렬화 된 개체의 복사본이 하나만 존재합니다. 개체에 대한 다른 참조는 공간을 절약하고 순환 참조를 방지하기 위해 개체 핸들로 저장됩니다. 직렬화 된 객체는 상속 계층 구조의 각 클래스 필드가 뒤에 오는 클래스로 시작합니다.

// 스트림에서 객체 읽기

// 1 단계. 입력 스트림 생성

FileInputStream in = new FileInputStream ( "fooFile");

// 2 단계. 객체 입력 스트림 생성

ObjectInputStream ins = new ObjectInputStream (in);

// 3 단계. 읽고있는 내용 파악

문자열 fooString = (문자열) ins.readObject ();

Foo foo = (Foo) s.readObject ();

객체 직렬화 및 보안

기본적으로 직렬화는 스트림에서 비 정적 및 비 일시적 필드를 쓰고 읽습니다. 이 특성은 비공개 임시로 직렬화되지 않을 수있는 필드를 선언하여 보안 메커니즘으로 사용할 수 있습니다. 클래스가 전혀 직렬화되지 않을 수 writeObject있고 readObject메서드를 구현하여 NoAccessException.

트랜잭션 무결성을 통한 지속성 : JDBC 소개

X / Open의 SQL CLI (Client Level Interface) 및 Microsoft의 ODBC 추상화를 모델로 한 Java 데이터베이스 연결 (JDBC)은 기본 데이터베이스 관리 시스템 (DBMS)과 독립적 인 데이터베이스 연결 메커니즘을 제공하는 것을 목표로합니다. 데이터베이스 액세스를위한 충분한 유연성을 제공하는 타사 도구 공급 업체 및 애플리케이션을 제공하는 최소한 ANSI SQL-2 엔트리 레벨 API를 지원해야합니다.

JDBC는 나머지 Java 시스템과 일치하도록 설계되었습니다. 공급 업체는 ODBC보다 더 강력한 형식의 API를 작성하는 것이 좋습니다. 따라서 컴파일 타임에 더 많은 정적 형식 검사가 가능합니다.

다음은 가장 중요한 JDBC 인터페이스에 대한 설명입니다.

  • java.sql.Driver.Manager 드라이버로드를 처리하고 새 데이터베이스 연결을 지원합니다.

  • java.sql.Connection 특정 데이터베이스에 대한 연결을 나타냅니다.

  • java.sql.Statement 주어진 연결에서 SQL 문을 실행하기위한 컨테이너 역할을합니다.

  • java.sql.ResultSet 결과 집합에 대한 액세스를 제어합니다.

여러 가지 방법으로 JDBC 드라이버를 구현할 수 있습니다. 가장 간단한 방법은 드라이버를 ODBC에 대한 브리지로 빌드하는 것입니다. 이 접근 방식은 고성능이 필요하지 않은 도구 및 응용 프로그램에 가장 적합합니다. 보다 확장 가능한 디자인은 게시 된 프로토콜을 통해 DBMS 서버에 액세스하는 JDBC 네트워크 드라이버를 제공하여 DBMS 서버에 대한 추가 수준의 간접적 수준을 도입합니다. 그러나 가장 효율적인 드라이버는 DBMS 독점 API에 직접 액세스합니다.

개체 데이터베이스 및 Java 지속성

업계에서 진행중인 많은 프로젝트는 객체 수준에서 Java 지속성을 제공합니다. 그러나이 글을 쓰는 현재, Object Design의 PSE (Persistent Storage Engine)와 PSE Pro는 사용 가능한 유일한 완전한 Java 기반의 객체 지향 데이터베이스 패키지입니다 (적어도 내가 알고있는). PSE 및 PSE Pro에 대한 자세한 내용은 리소스 섹션을 확인하십시오.

Java 개발은 특히 개발 프로세스 타임 라인에서 소프트웨어 공급 업체를위한 전통적인 개발 패러다임에서 벗어났습니다. 예를 들어 PSE와 PSE Pro는 이기종 환경에서 개발되었습니다. 그리고 개발 프로세스에 연결 단계가 없기 때문에 개발자는 서로 독립적으로 다양한 기능 구성 요소를 만들 수 있었으며, 결과적으로 더 좋고 안정적인 객체 지향 코드가 생성되었습니다.

PSE Pro에는 시스템 오류로 인해 중단 된 트랜잭션에서 손상된 데이터베이스를 복구하는 기능이 있습니다. 이 추가 된 기능을 담당하는 클래스는 PSE 릴리스에 없습니다. 두 제품간에 다른 차이점은 없습니다. 이러한 제품을 "dribbleware"라고 부르며 새로운 구성 요소를 연결하여 기능을 향상시키는 소프트웨어 릴리스입니다. 그리 멀지 않은 미래에 대규모 단일 소프트웨어를 구매하는 개념은 과거의 일이 될 것입니다. Java 컴퓨팅과 함께 사이버 공간의 새로운 비즈니스 환경을 통해 사용자는 필요한 개체 모델 (개체 그래프)의 일부만 구매할 수 있으므로 최종 제품이 더욱 컴팩트 해집니다.

PSE는 개발자가 클래스 파일을 만든 후 사후 처리하고 주석을 달아 작동합니다. PSE의 관점에서 개체 그래프의 클래스는 지속 가능하거나 지속적으로 인식됩니다. 영구 가능 클래스는 지속될 수 있지만 영구 인식 클래스는 영구 객체에서 작동 할 수 있습니다. 지속성이 특정 클래스에 대해 바람직한 동작이 아닐 수 있기 때문에 이러한 구분이 필요합니다. 클래스 파일 포스트 프로세서는 클래스를 다음과 같이 수정합니다.