使用 Jakarta NoSQL 的数据库引擎介绍 NoSQL 中的多态性

多态性是面向对象编程中的一个基本概念,允许将不同类型的对象视为同一超类的实例。这种灵活性对于创建易于扩展和维护的系统至关重要。虽然传统的SQL数据库结合Jakarta Persistence(JPA)可以处理多态数据,但NoSQL数据库具有明显优势。不同于需要严格模式定义的SQL数据库,NoSQL数据库采用无模式的方法,天然支持动态和灵活的数据结构。当与Jakarta NoSQL集成时,这种灵活性特别吸引人。Jakarta NoSQL是一个工具,它通过自定义转换器为定义和管理多态字段提供稳健的支持。

在许多企业应用程序中,存在管理不同类型数据对象的常见需求。例如,电子商务平台可能需要处理各种支付方式,如信用卡、数字钱包和银行转账,每种支付方式都有特定的属性。类似地,大型公司的资产管理系统处理不同类型的资产,如房地产、机械和知识产权,每种资产都有独特的属性。医疗保健系统必须容纳各种数据类型,从个人信息到医疗记录和测试结果。利用NoSQL数据库的多态字段可以存储和管理这些多样化的数据类型。NoSQL数据库的无模式性质使其比关系数据库更容易适应不断变化的需求。

这个教程将展示如何使用Jakarta NoSQL来管理多态字段,并使用自定义转换器。我们将包括集成使用Helidon和Oracle NoSQL的REST服务的示例代码。这个示例将演示在无模式NoSQL数据库环境中有效管理各种数据类型的多态性的实际应用。

使用NoSQL和Jakarta NoSQL的多态性

这个教程将探讨在Java世界中使用Oracle NoSQL、Java Helidon和Rest API的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

下一步是配置和运行 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 {
    // 通用引擎属性

    // 获取器和设置器
}

引擎转换器可能因提供者而异;它可以作为 StringMap<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中按类型搜索,并且实现分页很容易。有关分页技术的更多信息,请参考本文

插入一些数据后,您可以探索并了解搜索的工作原理。

  • 获取带有分页的机器
  • 获取所有机器
  • 获取气体机器

最后的想法

使用Jakarta NoSQL和Jakarta JSON-B将多态性与NoSQL数据库集成,提供了灵活性和效率来管理不同类型的数据。通过利用NoSQL的无模式特性,这种方法简化了开发并增强了应用程序的适应性。有关完整的示例和源代码,请访问soujava/helidon-oracle-json-types

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