Jakarta NoSQL를 사용하여 NoSQL 데이터베이스 엔진의 다형성 이해

다형성, 객체 지향 프로그래밍의 기본 개념을 통해 다양한 유형의 객체를 공통 슈퍼클래스의 인스턴스로 처리할 수 있습니다. 이러한 유연성은 쉽게 확장하고 유지 관리할 수 있는 시스템을 만드는 데 필수적입니다. JPA(Jakarta Persistence)와 결합된 기존 SQL 데이터베이스는 다형성 데이터를 처리할 수 있지만 NoSQL 데이터베이스는 뚜렷한 이점을 제공합니다. 엄격한 스키마 정의가 필요한 SQL 데이터베이스와 달리 NoSQL 데이터베이스는 스키마 없는 접근 방식을 취하므로 본질적으로 동적이며 유연한 데이터 구조를 지원합니다. 이러한 유연성은 다음과 통합될 때 특히 매력적입니다. Jakarta NoSQL, 사용자 정의 변환기를 통해 다형성 필드를 정의하고 관리하기 위한 강력한 지원을 제공하는 도구입니다.

많은 기업 애플리케이션에서 다양한 유형의 데이터 객체를 관리해야 하는 공통적인 필요가 있습니다. 예를 들어, 전자상거래 플랫폼은 신용카드, 디지털 지갑, 은행 송금 등 각기 다른 속성을 가진 다양한 결제 방식을 처리할 수 있습니다. 마찬가지로, 대기업의 자산 관리 시스템은 부동산, 기계, 지적 재산권 등 각각 고유한 속성을 가진 다양한 유형의 자산을 다룹니다. 의료 시스템은 개인 정보부터 의료 기록 및 검사 결과에 이르는 다양한 데이터 유형을 수용해야 합니다. 다형성 필드를 가진 NoSQL 데이터베이스를 사용하면 이러한 다양한 데이터 유형을 통합하여 저장하고 관리할 수 있습니다. NoSQL 데이터베이스의 스키마리스 특성 덕분에 관계형 데이터베이스보다 변화하는 요구 사항에 더 쉽게 적응할 수 있습니다.

이 튜토리얼에서는 Jakarta NoSQL을 사용하여 사용자 정의 변환기를 사용하여 다형성 필드를 관리하는 방법을 보여줍니다. 통합을 위한 샘플 코드가 포함됩니다. Helidon 및 Oracle NoSQL을 사용한 REST 서비스. 이 예에서는 스키마가 없는 NoSQL 데이터베이스 환경에서 다양한 데이터 유형을 효율적으로 관리하기 위해 다형성을 실제로 적용하는 방법을 보여줍니다.

NoSQL과 Jakarta NoSQL을 사용한 다형성 관리

이 자습서에서는 Oracle NoSQL, Java Helidon, REST API를 사용하여 Java 세계의 NoSQL 및 스키마 없는 기능을 탐구합니다. Machine 엔터티를 생성하여 JSON으로 변환할 engine 필드를 제공합니다. Oracle NoSQL의 자연스러운 유연성과 스키마 없는 설계 덕분에 이 접근 방식이 원활하게 작동합니다.

Helidon 프로젝트를 생성하는 첫 번째 단계는 Helidon Starter를 사용하는 것입니다: Helidon Starter.

Microprofile 호환 프로젝트를 생성한 다음, 다음 단계는 Oracle NoSQL 드라이버를 포함하는 것입니다: Oracle NoSQL Driver.

속성 파일에서 로컬로 실행할 것이므로 두 개의 속성이 필요합니다: 하나는 호스트 연결을 정의하고 다른 하나는 데이터베이스 이름을 정의합니다:

Properties files

 

jnosql.document.database=machines
jnosql.oracle.nosql.host=http://localhost:8080

또한 포트를 8181로 업데이트합니다:

Properties files

 

server.port=8181

Shell

 

docker run -d --name oracle-instance -p 8080:8080 ghcr.io/oracle/nosql:latest-ce

도커를 사용하면 설정 과정을 간소화하고 Oracle NoSQL 인스턴스가 제어된 환경에서 실행되도록 할 수 있습니다. 이 설정은 Oracle 인프라를 포함한 다양한 환경에 Oracle NoSQL을 배포하는 실용적인 접근 방식을 제공합니다.

구성 및 데이터베이스 설정 후 다음 단계는 Entity를 정의하고 Converter 구현을 만드는 것입니다. 이 예에서는 Jakarta NoSQL과 Jakarta JSON-B의 seamless 통합을 보여줍니다.

첫 번째 단계는 다형성 Engine 필드를 포함하는 Machine 엔티티를 정의하는 것입니다.

Java

 


@Entity
@JsonbVisibility(FieldAccessStrategy.class)
public class Machine {

    @Id
    private String id;

    @Column
    @Convert(EngineConverter.class)
    private Engine engine;

    @Column
    private String manufacturer;

    @Column
    private int year;

    // Getters and setters
}

다음으로 JsonbTypeInfo를 사용하여 다형성을 처리하는 Engine 클래스를 정의합니다.

Java

 

@JsonbTypeInfo(
        key = "type",
        value = {
                @JsonbSubtype(alias = "gas", type = GasEngine.class),
                @JsonbSubtype(alias = "electric", type = ElectricEngine.class)
        }
)
@JsonbVisibility(FieldAccessStrategy.class)
public abstract class Engine {
    // Common engine attributes

    // Getters and setters
}

엔진 변환기는 공급업체에 따라 달라질 수 있으며 String, Map<String, Object>, BSON 등으로 작동할 수 있습니다.

구성 및 데이터베이스 설정 후 다음 단계는 애플리케이션과 데이터베이스 브리지를 만드는 것입니다. Eclipse JNoSQL은 Jakarta NoSQL과 Jakarta Data 두 가지 사양을 단일 인터페이스로 통합하여 이를 달성합니다. 주석은 필요한 단계를 처리합니다.

먼저 MachineRepository 인터페이스를 정의합니다:

Java

 

@Repository
public interface MachineRepository extends BasicRepository<Machine, String> {

    @Query("from Machine where engine.type = :type")
    List<Machine> findByType(@Param("type") String type);
}

이 저장소 인터페이스를 사용하면 JSON 데이터 내에서 직접 요소를 검색할 수 있으며 엄격한 구조를 만들지 않고도 확장할 수 있습니다.

다음으로 이 리소스를 노출하는 컨트롤러를 정의합니다:

Java

 


@Path("/machines")
@ApplicationScoped
public class MachineResource {

    private static final Logger LOGGER = Logger.getLogger(MachineResource.class.getName());

    public static final Order<Machine> ORDER_MANUFACTURER = Order.by(Sort.asc("manufacturer"));

    private final MachineRepository repository;

    @Inject
    public MachineResource(@Database(DatabaseType.DOCUMENT) MachineRepository repository) {
        this.repository = repository;
    }

    @GET
    public List<Machine> getMachines(@QueryParam("page") @DefaultValue("1") int page, @QueryParam("page_size") @DefaultValue("10") int pageSize) {
        LOGGER.info("Get machines from page " + page + " with page size " + pageSize);
        Page<Machine> machines = this.repository.findAll(PageRequest.ofPage(page).size(pageSize), ORDER_MANUFACTURER);
        return machines.content();
    }

    @GET
    @Path("gas")
    public List<Machine> getGasMachines() {
        return this.repository.findByType("gas");
    }

    @GET
    @Path("electric")
    public List<Machine> getElectricMachines() {
        return this.repository.findByType("electric");
    }

    @GET
    @Path("{id}")
    public Machine get(@PathParam("id") String id) {
        LOGGER.info("Get machine by id " + id);
        return this.repository.findById(id)
                .orElseThrow(() -> new WebApplicationException("Machine not found with id: " + id, Response.Status.NOT_FOUND));
    }

    @PUT
    public void save(Machine machine) {
        LOGGER.info("Saving a machine " + machine);
        this.repository.save(machine);
    }
}

이 컨트롤러는 유형별 머신 가져오기 및 페이징을 포함한 머신 관리를 위한 엔드포인트를 노출합니다.

마지막으로 애플리케이션을 실행하고 다음 curl 명령을 사용하여 데이터를 삽입합니다:

Shell

 

curl --location --request PUT 'http://localhost:8181/machines' \
--header 'Content-Type: application/json' \
--data '{
"id": "1",
"model": "Thunderbolt V8",
"engine": {
"type": "gas",
"horsepower": 450
},
"manufacturer": "Mustang",
"year": 2021,
"weight": 1600.0
}'

curl --location --request PUT 'http://localhost:8181/machines' \
--header 'Content-Type: application/json' \
--data '{
    "id": "2",
    "model": "Eagle Eye EV",
    "engine": {
        "type": "electric",
        "horsepower": 300
    },
    "manufacturer": "Tesla",
    "year": 2022,
    "weight": 1400.0
}'

curl --location --request PUT 'http://localhost:8181/machines' \
--header 'Content-Type: application/json' \
--data '{
    "id": "3",
    "model": "Road Runner GT",
    "engine": {
        "type": "gas",
        "horsepower": 400
    },
    "manufacturer": "Chevrolet",
    "year": 2020,
    "weight": 1700.0
}'

curl --location --request PUT 'http://localhost:8181/machines' \
--header 'Content-Type: application/json' \
--data '{
    "id": "4",
    "model": "Solaris X",
    "engine": {
        "type": "electric",
        "horsepower": 350
    },
    "manufacturer": "Nissan",
    "year": 2023,
    "weight": 1350.0
}'

curl --location --request PUT 'http://localhost:8181/machines' \
--header 'Content-Type: application/json' \
--data '{
    "id": "5",
    "model": "Fusion Hybrid 2024",
    "engine": {
        "type": "electric",
        "horsepower": 320
    },
    "manufacturer": "Toyota",
    "year": 2024,
    "weight": 1450.0
}'

이 설정을 통해 JSON 내에서 유형별로 검색할 수 있으며 페이징도 쉽게 구현할 수 있습니다. 페이징 기술에 대한 자세한 내용은 이 기사를 참조하십시오.

데이터가 삽입되면 검색 작동 방식을 탐색하고 이해할 수 있습니다.

  • 페이지 매김이 있는 머신 가져오기
  • 모든 머신 가져오기
  • 가스 머신 가져오기

최종 생각

자카르타 NoSQL 및 Jakarta JSON-B를 사용하여 다형성을 NoSQL 데이터베이스와 통합하면 다양한 데이터 유형을 관리할 수 있는 유연성과 효율성을 제공합니다. 이 접근 방식은 스키마가 없는 NoSQL의 특성을 활용함으로써 개발을 간소화하고 애플리케이션 적응성을 향상시킵니다. 전체 예제 및 소스 코드는 soujava/helidon-oracle-json-types에서 확인할 수 있습니다.

Source:
https://dzone.com/articles/intro-to-polymorphism-with-db-engines-in-nosql