Введение в полиморфизм с использованием баз данных в NoSQL с использованием Jakarta NoSQL

Полиморфизм — это основополагающая концепция объектно-ориентированного программирования, позволяяя рассматривать объекты разных типов как экземпляры общего суперкласса. Эта гибкость имеет важное значение для создания систем, которые могут быть легко расширяены и поддерживаены. Традиционные SQL-базы данных в сочетании с Jakarta Persistence (JPA) могут обрабатывать полиморфизные данные, но NoSQL-базы данных имеют особенные преимущества. В отличие от SQL-баз данных, которые требуют строгих схем, NoSQL-базы данных используют безсхемный метод, который по сути поддерживает динамические и гибкие структуры данных. Эта гибкость становится особенно привлекательной, когда она интегрируется с Jakarta NoSQL, инструментом, который обеспечивает надежное поддержку определения и управления полиморфизных полей через пользовательские конвертеры.

Во многих корпоративных приложениях существует общая необходимость управлять различными типами объектов данных. Например, электронная торговля может обрабатывать различные способы оплаты, такие как кредитные карты, цифровые кошельки и банковские переводы, у каждого из них есть свои специфические атрибуты. Аналогично, системы управления активами в крупных корпорациях имеют дело с разными типами активов, такими как недвижимость, техника и интеллектуальная собственность, у каждого из них есть свои уникальные свойства. Системы здравоохранения должны приспосабливать разные типы данных, от персональной информации до медицинских записей и результатов анализов. Использование NoSQL-баз данных с полиморфизными полями может хранить и управлять эти разнообразие типы данных более гомогейненно. Безсхемный характер NoSQL-баз данных позволяет их легче адаптироваться к изменяющимся требованиям, чем относительно баз данных.

Этот учебник покажет, как использовать Jakarta NoSQL для управления полиморфными полями с помощью пользовательских конвертеров. Мы включим пример кода для интеграции REST-сервисов с использованием Helidon и Oracle NoSQL. Этот пример продемонстрирует практическое применение полиморфизма для эффективного управления различными типами данных в среде NoSQL базы данных без схемы.

Использование полиморфизма с NoSQL и Jakarta NoSQL

Этот учебник исследует возможности NoSQL и отсутствие схемы в мире Java с использованием Oracle NoSQL, Java Helidon и Rest API. Мы создадим сущность Machine, где будет предоставлено поле engine, которое мы конвертируем в JSON. Благодаря естественной гибкости 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

Следующий шаг – настройка и запуск Oracle NoSQL. Чтобы упростить задачу, мы будем использовать Docker, но важно отметить, что Oracle NoSQL также поддерживает облачное развертывание на инфраструктуре Oracle:

Shell

 

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

Используя Docker, мы упрощаем процесс настройки и гарантируем, что наш экземпляр Oracle NoSQL будет работать в контролируемой среде. Такая настройка обеспечивает практический подход для целей разработки и тестирования, подчеркивая гибкость развертывания Oracle NoSQL в различных средах, включая облачную инфраструктуру.

После настройки конфигурации и базы данных следующий шаг включает определение Entity и создание реализации Converter. В этом примере мы продемонстрируем бесшовную интеграцию Jakarta NoSQL и Jakarta JSON-B, показывая, как различные спецификации Jakarta могут эффективно работать вместе.

Начальным шагом является определение сущности Machine, которая включает в себя полиморфное поле Engine.

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;

    // Геттеры и сеттеры
}

Далее мы определяем класс Engine, указывая типы и реализации с помощью JsonbTypeInfo для обработки полиморфизма:

Java

 

@JsonbTypeInfo(
        key = "type",
        value = {
                @JsonbSubtype(alias = "gas", type = GasEngine.class),
                @JsonbSubtype(alias = "electric", type = ElectricEngine.class)
        }
)
@JsonbVisibility(FieldAccessStrategy.class)
public abstract class Engine {
    // Общие атрибуты движка

    // Геттеры и сеттеры
}

Конвертер движка может меняться в зависимости от провайдера; он может работать как 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 NoSQL и Jakarta JSON-B обеспечивает гибкость и эффективность в управлении различными типами данных. Благодаря использованию независимости схемы NoSQL, этот подход упрощает разработку и усиливает адаптивность приложения. Для полного примера и исходного кода посетите soujava/helidon-oracle-json-types.

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