Polymorphismus, ein grundlegendes Konzept der objektorientierten Programmierung, ermöglicht es, Objekte unterschiedlichen Typs als Instanzen einer gemeinsamen Oberklasse zu behandeln. Diese Flexibilität ist unerlässlich, um Systeme zu schaffen, die sich leicht erweitern und pflegen lassen. Während herkömmliche SQL-Datenbanken in Kombination mit Jakarta Persistence (JPA) polymorphe Daten verarbeiten können, bieten NoSQL-Datenbanken deutliche Vorteile. Im Gegensatz zu SQL-Datenbanken, die strenge Schemadefinitionen erfordern, verfolgen NoSQL-Datenbanken einen schemafreien Ansatz und unterstützen von Natur aus dynamische und flexible Datenstrukturen. Diese Flexibilität wird besonders attraktiv, wenn sie mit Jakarta NoSQL integriert wird, einem Tool, das robuste Unterstützung für die Definition und Verwaltung von polymorphen Feldern durch benutzerdefinierte Konverter bietet.
In vielen Unternehmensanwendungen besteht die allgemeine Notwendigkeit, verschiedene Arten von Datenobjekten zu verwalten. Zum Beispiel kann eine E-Commerce-Plattform verschiedene Zahlungsmethoden wie Kreditkarten, digitale Geldbörsen und Banküberweisungen mit jeweils spezifischen Attributen verwalten. In ähnlicher Weise befassen sich Vermögensverwaltungssysteme in großen Unternehmen mit verschiedenen Arten von Vermögenswerten wie Immobilien, Maschinen und geistigem Eigentum, die jeweils einzigartige Eigenschaften aufweisen. Systeme im Gesundheitswesen müssen verschiedene Datentypen aufnehmen, von persönlichen Informationen bis hin zu medizinischen Aufzeichnungen und Testergebnissen. Die Verwendung von NoSQL-Datenbanken mit polymorphen Feldern kann diese verschiedenen Datentypen zusammenhängend speichern und verwalten. Da NoSQL-Datenbanken schemaunabhängig sind, lassen sie sich auch leichter an veränderte Anforderungen anpassen als relationale Datenbanken.
Diese Anleitung zeigt, wie Sie Jakarta NoSQL verwenden, um polymorphe Felder mit benutzerdefinierten Konvertern zu verwalten. Wir werden Beispielcode für die Integration von REST-Diensten mit Helidon und Oracle NoSQL aufnehmen. Dieses Beispiel wird die praktische Anwendung von Polymorphismus beim effizienten Verwalten verschiedener Datentypen in einer schemafreien NoSQL-Datenbank-Umgebung zeigen.
Verwendung von Polymorphismus mit NoSQL und Jakarta NoSQL
Diese Anleitung wird die NoSQL- und schemafreien Fähigkeiten in der Java-Welt mit Oracle NoSQL, Java Helidon und Rest-API untersuchen. Wir werden eine Machine
-Entität erstellen, bei der wir ein engine
-Feld in JSON umwandeln werden. Dank der natürlichen Flexibilität von Oracle NoSQL und seinem schemafreien Design funktioniert dieser Ansatz nahtlos.
Der erste Schritt besteht darin, das Helidon-Projekt zu erstellen, bei dem Sie den Helidon-Starter verwenden können: Helidon Starter.
Nach der Erstellung eines Microprofile-konformen Projekts ist der nächste Schritt, den Oracle NoSQL-Treiber einzubinden: Oracle NoSQL-Treiber.
In der Eigenschaftendatei müssen wir, da wir lokal laufen werden, zwei Eigenschaften definieren: eine für die Hostverbindung und eine für den Datenbanknamen:
jnosql.document.database=machines
jnosql.oracle.nosql.host=http://localhost:8080
Aktualisieren Sie außerdem den Port auf 8181:
server.port=8181
Der nächste Schritt besteht darin, Oracle NoSQL zu konfigurieren und zu starten. Um es einfacher zu machen, werden wir Docker verwenden, aber es ist wichtig zu beachten, dass Oracle NoSQL auch den Cloud-Ausbau auf der Oracle-Infrastruktur unterstützt:
docker run -d --name oracle-instance -p 8080:8080 ghcr.io/oracle/nosql:latest-ce
Durch die Verwendung von Docker vereinfachen wir den Setup-Prozess und stellen sicher, dass unsere Oracle NoSQL-Instanz in einer kontrollierten Umgebung läuft. Diese Konfiguration bietet eine praktische Herangehensweise für Entwicklungs- und Testzwecke und betont die Flexibilität, mit der Oracle NoSQL in verschiedenen Umgebungen, einschließlich Cloud-Infrastrukturen,部署t werden kann.
Nachdem die Konfiguration und die Datenbank eingerichtet wurden, geht es im nächsten Schritt darum, die Entität
zu definieren und die Implementierung der Konverter
zu erstellen. In diesem Beispiel demonstriert uns die problemlose Integration von Jakarta NoSQL und Jakarta JSON-B, wie unterschiedliche Jakarta-Spezifikationen effektiv zusammenarbeiten können.
Der erste Schritt besteht darin, die Maschine
-Entität zu definieren, die einen polymorphen Motor
-Feld enthält.
@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
}
Danach definieren wir die Motor
-Klasse und spezifizieren die Typen und Implementierungen mit JsonbTypeInfo
, um Polymorphismus zu behandeln:
@JsonbTypeInfo(
key = "type",
value = {
@JsonbSubtype(alias = "gas", type = GasEngine.class),
@JsonbSubtype(alias = "electric", type = ElectricEngine.class)
}
)
@JsonbVisibility(FieldAccessStrategy.class)
public abstract class Engine {
// Gemeinsame Motor-Eigenschaften
// Getters and setters
}
Der Motor-Konverter kann von Anbieter zu Anbieter unterschiedlich sein und als String
, Map<String, Object>
, BSON
usw. arbeiten.
Nach dem Einrichten der Konfiguration und der Datenbank ist der nächste Schritt das Erstellen der Anwendungs- und Datenbankbrücke. Eclipse JNoSQL integriert zwei Spezifikationen, Jakarta NoSQL und Jakarta Data, mit einer einzigen Schnittstelle, um dies zu erreichen. Annotationen behandeln die notwendigen Schritte.
Zunächst definieren wir die MachineRepository
-Schnittstelle:
@Repository
public interface MachineRepository extends BasicRepository<Machine, String> {
@Query("from Machine where engine.type = :type")
List<Machine> findByType(@Param("type") String type);
}
Diese Repository-Schnittstelle ermöglicht es uns, Elemente direkt innerhalb der JSON-Daten ohne Probleme zu durchsuchen, und Sie können sie weiter ausbauen, ohne eine starre Struktur zu schaffen.
Als Nächstes definieren wir den Controller, um diese Ressource bereitzustellen:
@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);
}
}
Dieser Controller stellt Endpunkte für das Verwalten von Maschinen bereit, einschließlich des Abrufens von Maschinen nach Typ und Seitenzahl.
Führen Sie schließlich die Anwendung aus und fügen Sie Daten mit den folgenden curl
-Befehlen ein:
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
}'
Diese Einrichtung ermöglicht es Ihnen, nach Typ innerhalb von JSON zu suchen, und die Seitenzahl lässt sich leicht implementieren. Weitere Informationen zu Seitentechniken finden Sie in diesem Artikel.
Mit einigen eingefügten Daten können Sie erforschen und verstehen, wie die Suche funktioniert:
- Maschinen mit Paginierung abrufen
- Alle Maschinen abrufen
- Gasmaschinen abrufen
Abschließende Gedanken
Die Integration von Polymorphismus mit NoSQL-Datenbanken unter Verwendung von Jakarta NoSQL und Jakarta JSON-B bietet Flexibilität und Effizienz bei der Verwaltung verschiedener Datentypen. Durch die Nutzung der schemafreien Natur von NoSQL wird die Entwicklung vereinfacht und die Anpassungsfähigkeit der Anwendung verbessert. Für das vollständige Beispiel und den Quellcode besuchen Sie bitte soujava/helidon-oracle-json-types.
Source:
https://dzone.com/articles/intro-to-polymorphism-with-db-engines-in-nosql