[JAVA] Interaktion mit einer MySQL-Datenbank mithilfe der ORM-Funktion (Object-Relational Mapping) von Apache Cayenne

In diesem Artikel verwenden wir die ORM-Funktion (Object Relational Mapping) von ** Apache Cayenne **, um mit einer ** MySQL ** -Datenbank aus einem kleinen ** Java ** -Projekt zu arbeiten, das mit Maven erstellt wurde.

Projekt Einstellungen

Maven ist eines der beliebtesten Tools zum Erstellen von Java-Anwendungen. In diesem Abschnitt legen Sie die Projektabhängigkeiten fest (dies setzt voraus, dass Ihr System leer ist).

Fügen Sie als ersten Schritt die folgenden Abhängigkeiten hinzu, um Apache Cayenne und den MYSQL-Connector (insbesondere den JDBC-Treiber) hinzuzufügen.

<dependency>
   <groupId>org.apache.cayenne</groupId>
   <artifactId>cayenne-server</artifactId>
   <version>4.0.1</version>
</dependency>
<dependency>
   <groupId>mysql</groupId>
   <artifactId>mysql-connector-java</artifactId>
   <version>5.1.14</version>
   <scope>runtime</scope>
</dependency>

Das Modeler-Plug-In muss auch in pom.xml definiert sein. Dies ist der Befehl maven, mit dem das Apache Cayenne Modeler-Plug-In über die Befehlszeile gestartet wird, wenn Sie die Zuordnungsdatei für Ihr aktuelles Projekt öffnen.

<plugin>
   <groupId>org.apache.cayenne.plugins</groupId>
   <artifactId>cayenne-modeler-maven-plugin</artifactId>
   <version>4.0.1</version>

   <configuration>
      <modelFile>${project.basedir}/src/main/resources/cayenne-blog.xml</modelFile>
   </configuration>
</plugin>

Modellierer sind im Allgemeinen die empfohlene Methode zum Entwerfen und Konfigurieren der Zuordnung zwischen der Datenbank und der tatsächlichen Java-Modellklasse.

Sie können es von [dieser Seite] herunterladen (http://cayenne.apache.org/download.html?spm=a2c65.11461447.0.0.640c764cCNwoDP). Sie müssen eine Version herunterladen, die für Ihr bestimmtes Betriebssystem erstellt wurde, oder Sie können stattdessen die plattformübergreifende Version (JAR) verwenden, die als Maven-Plug-In enthalten ist. Die neueste stabile Version zum Zeitpunkt des Schreibens dieses Artikels ist Version 4.1 c764cCNwoDP & file = RELEASE-NOTES.txt). Diese Version erfordert Java 1.8 oder höher.

Als nächsten Schritt erstellen wir das Projekt mit dem Befehl "mvn clean install", starten die GUI des Modellierers mit dem Befehl "mvn cayenne-modeler: run" und geben diesen Bildschirm aus.

image.png

Wenn Sie etwas anderes als MySQL verwenden, müssen Sie auch den JDBC-Treiber ändern, damit die Konfiguration datenbankabhängig ist. Hier finden Sie eine vollständige Liste mit den entsprechenden Treibern.

Mapping und Datenbankdesign

Angenommen, Sie haben eine vorhandene Datenbank mit dem Namen cayenne_blog, die die Eins-zu-Viele-Beziehung zwischen zwei Tabellen anzeigt, in der die folgenden Parameter definiert sind.

--author: id (PK) und name --Artikel: ID (PK), Titel, Inhalt, author_id (FK) Betrachten Sie nun einen SQL-Befehl, der in diesem Beispiel auf die Datenbank verweist.

CREATE TABLE `author` (
  `id` int(11) NOT NULL,
  `name` varchar(250) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

--
-- Indexes for table `article`
--
ALTER TABLE `article`
  ADD PRIMARY KEY (`id`),
  ADD KEY `author_id` (`author_id`);

--
-- Indexes for table `author`
--
ALTER TABLE `author`
  ADD PRIMARY KEY (`id`);

--
-- AUTO_INCREMENT for table `article`
--
ALTER TABLE `article`
  MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;

--
-- AUTO_INCREMENT for table `author`
--
ALTER TABLE `author`
  MODIFY `id` int(11) NOT NULL AUTO_INCREMENT;

--
-- Constraints for table `article`
--
ALTER TABLE `article`
  ADD CONSTRAINT `article_ibfk_1` FOREIGN KEY (`author_id`) REFERENCES `author` (`id`);

db.sql](https://github.com/dassiorleando/apache-cayenne/blob/master/db.sql) Importieren Sie die Datei in phpMyAdmin oder führen Sie den folgenden Befehl vom MYSQL-Server des Terminals aus Masu: mysql <db.sql.

Fügen wir nun ein Plugin namens "cayenne-maven-plugin" hinzu, bei dem es sich um eine Modeler-Plugin-Einstellung handelt, zu "pom.xml".

<plugin>
   <groupId>org.apache.cayenne.plugins</groupId>
   <artifactId>cayenne-maven-plugin</artifactId>
   <version>4.0.1</version>

   <configuration>
      <map>${project.basedir}/src/main/resources/blog.map.xml</map>
      <dataSource>
         <driver>com.mysql.jdbc.Driver</driver>
         <url>jdbc:mysql://localhost:3306/cayenne_blog</url>
         <username>root</username>
         <password>root</password>
      </dataSource>
      <dbImport>
         <defaultPackage>com.dassiorleando.apachecayenne.models</defaultPackage>
      </dbImport>
   </configuration>

   <dependencies>
      <dependency>
         <groupId>mysql</groupId>
         <artifactId>mysql-connector-java</artifactId>
         <version>5.1.44</version>
         <scope>runtime</scope>
      </dependency>
   </dependencies>
</plugin>

Hier legen Sie fest, wo der ORM die Daten speichert (<Datenquelle>) und wo die Mapping-Datei gespeichert wird (<Map>). In dieser Einstellung lautet der Datenbankname "cayenne_blog", die Anmeldeinformationen der Benutzerdatenbank lauten "root: root" (Aktualisierung auf die des MYSQL-Servers) und das Standardpaket ist das der Projektstruktur (Erstellen einer Modellklasse). Sie können sehen, dass Sie das Paket verwenden.

Verwenden Sie abschließend den Befehl cbimport in der Projektbefehlszeile: mvn cayenne: cdbimport. cdbimport synchronisiert die XML-Map-Datei mit einer vorhandenen Datenbank, sodass Sie ein Protokoll erhalten sollten, das dem folgenden ähnelt:

INFO] +++ Connecting: SUCCESS.
[INFO] Detected and installed adapter: org.apache.cayenne.dba.mysql.MySQLAdapter
[INFO]   Table: cayenne_blog.AUTO_PK_SUPPORT
[INFO]   Table: cayenne_blog.article
[INFO]   Table: cayenne_blog.author
[INFO]     Db Relationship : toOne  (article.author_id, author.id)
[INFO]     Db Relationship : toMany (author.id, article.author_id)
[INFO] 
[INFO] Map file does not exist. Loaded db model will be saved into '/Users/dassiorleando/projects/opensource/apache-cayenne/src/main/resources/blog.map.xml'
[INFO] 
[INFO] Detected changes: 
[INFO]     Create Table         article
[INFO]     Create Table         author
[INFO]     Create Table         AUTO_PK_SUPPORT
[INFO] 
[WARNING] Can't find ObjEntity for author
[WARNING] Db Relationship (Db Relationship : toOne  (article.author_id, author.id)) will have GUESSED Obj Relationship reflection. 
[INFO] Migration Complete Successfully.
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 4.165 s
[INFO] Finished at: 2019-07-22T17:40:36+01:00
[INFO] Final Memory: 10M/164M
[INFO] ------------------------------------------------------------------------

Lassen Sie uns eine Java-Klasse generieren: mvn cayenne: cgen

[INFO] Scanning for projects...
[INFO] 
[INFO] ------------------------------------------------------------------------
[INFO] Building apache-cayenne 0.0.1-SNAPSHOT
[INFO] ------------------------------------------------------------------------
[INFO] 
[INFO] --- cayenne-maven-plugin:4.0.1:cgen (default-cli) @ apache-cayenne ---
[INFO] Generating superclass file: /Users/dassiorleando/projects/opensource/apache-cayenne/src/main/java/com/dassiorleando/apachecayenne/model/auto/_Article.java
[INFO] Generating class file: /Users/dassiorleando/projects/opensource/apache-cayenne/src/main/java/com/dassiorleando/apachecayenne/model/Article.java
[INFO] Generating superclass file: /Users/dassiorleando/projects/opensource/apache-cayenne/src/main/java/com/dassiorleando/apachecayenne/model/auto/_Author.java
[INFO] Generating class file: /Users/dassiorleando/projects/opensource/apache-cayenne/src/main/java/com/dassiorleando/apachecayenne/model/Author.java
[INFO] Generating superclass file: /Users/dassiorleando/projects/opensource/apache-cayenne/src/main/java/com/dassiorleando/apachecayenne/model/auto/_AutoPkSupport.java
[INFO] Generating class file: /Users/dassiorleando/projects/opensource/apache-cayenne/src/main/java/com/dassiorleando/apachecayenne/model/AutoPkSupport.java
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------

Sie sollten sofort feststellen, dass sich die Struktur Ihres Projekts geändert hat. Wir sprechen über "_Article.java" und "_Author.java" (beide sind Erweiterungen von "CayenneDataObject"). Sie können sehen, dass dieselben Einstellungen (im XML-Format) in der Datei "resources / blog.map.xml" enthalten sind.

Geben Sie dann den Befehl mvn cayenne-modeler: run ein, um den Modellierer zu starten. Klicken Sie auf Neues Projekt und geben Sie auf der nächsten Seite den Datendomänennamen (Blog) für die Zuordnungsdatei an. Speichern Sie es hier im selben Ordner wie die erstellte Kartendatei.

image.png

Klicken Sie dann auf Datei> Datenkarte importieren, um auf die Benutzeroberfläche zuzugreifen, über die Sie eine Verknüpfung zur Datenkarte herstellen können.

Sobald die Dateien "cayenne-blog.xml" und "blog.map.xml" verknüpft sind, kann der Modellierer das Modell aktualisieren, um es in der Klasse wiederzugeben. Es wird wie folgt sein.

image.png

Apache Cayenne unterstützt drei Hauptstrategien.

image.png

Hinweis: Erstellen Sie einen DataNode, der genau unserer Datenbankkonfiguration entspricht (siehe folgende Abbildung).

image.png

Erstellen Sie im Verzeichnis "Ressourcen" Ihres Maven-Projekts eine spezielle XML-Datei mit dem Namen "Cayennepfeffer-Blog" mit folgendem Inhalt:

<?xml version="1.0" encoding="utf-8"?>
<domain project-version="9">
   <map name="blog"/>

   <node name="datanode"
       factory="org.apache.cayenne.configuration.server.XMLPoolingDataSourceFactory"
       schema-update-strategy="org.apache.cayenne.access.dbsync.SkipSchemaUpdateStrategy">
      <map-ref name="blog"/>
      <data-source>
         <driver value="com.mysql.jdbc.Driver"/>
         <url value="jdbc:mysql://localhost:3306/cayenne_blog"/>
         <connectionPool min="1" max="1"/>
         <login userName="root" password="root"/>
      </data-source>
   </node>
</domain>

Die "XMLPoolingDataSourceFactory" ist für das Laden von JDBC-Verbindungsinformationen aus der XML-Ressource verantwortlich, die dem "DataNodeDescriptor" zugeordnet ist.

Zuordnungsstruktur

Apache Cayenne hat eine eigene Syntax zum Schreiben von Modellen.

--DataNode (<Knoten>) : Datenbankmodell. Es enthält alle Informationen, die für die Verbindung mit der Datenbank erforderlich sind, einschließlich des Datenbanknamens, des Treibers und der Anmeldeinformationen des Datenbankbenutzers. --DataMap (<Datenkarte>) : Ein Container mit persistenten Entitäten, zu denen Sie eine Beziehung haben. --DbAttribute (<db-attribute>) : Repräsentiert eine Spalte in einer Datenbanktabelle. --DbEntity (<db-entity>) : Eine einzelne Datenbanktabelle oder ein einzelnes Ansichtsmodell. Sie können eine Beziehung zu DbAttributes haben.

--ObjEntity (<obj-entity>) : Ein einzelnes beständiges Java-Klassenmodell, bestehend aus ObjAttributes, das den Eigenschaften der Entitätsklasse entspricht, und ObjRelationships, einer Eigenschaft mit dem Typ einer anderen Entität. .. --Embeddable (<embeddable>) : Ein Java-Klassenmodell, das als Eigenschaft von ObjEntity fungiert, jedoch mehrere Spalten in der Datenbank unterstützt. --procedure (<procedure>): Registriert die gespeicherte Prozedur in der Datenbank. Wird beim Mapping verwendet.

Weitere Informationen finden Sie im folgenden Handbuch.

Anwenden von CRUD auf das Modell

In diesem Abschnitt werden wir einige grundlegende Operationen auf die Modelle anwenden ("Artikel" und "Autor"). Die Klasse "ObjectSelect" verfügt über einige statische Methoden, die zum Abfragen der Datenbank nützlich sind. Für Einfügungen und Aktualisierungen wird jedoch der Serverkontext (ObjectContext) verwendet, der zum Festschreiben von Änderungen verwendet wird. wird gebraucht.

Hier erfahren Sie, wie Sie den Kontext des Servers ermitteln, der unserem Projekt zugeordnet ist.

ServerRuntime cayenneRuntime = ServerRuntime.builder()
        .addConfig("cayenne-blog.xml")
        .build();

ObjectContext context = cayenneRuntime.newContext();

Hinweis: Die Datei cayenne-blog.xml befindet sich im Ressourcenordner Ihres Projekts.

Ein Objekt erstellen

Sie können ein Objekt mit der folgenden Abfrage erstellen.

/**
 * Save an author
 * @param name
 */
public void save(String name) {
    // Save a single author
    Author author = this.context.newObject(Author.class);
    author.setName(name);

    context.commitChanges();
}

Ein Objekt lesen

Sie können das Objekt mit der folgenden Abfrage laden.

/**
 * Find an author by its ID
 * @param id    the author's ID
 * @return      the matched author or null if not existing
 */
public Author findById(int id) {
    Author author = Cayenne.objectForPK(context, Author.class, id);
    return author;
}

/**
 * Looking for an author by name
 * @param name  the name to look up with
 * @return      the first matched author or null if not existing
 */
public Author findByName(String name) {
    Author foundAuthor = ObjectSelect.query(Author.class)
            .where(Author.NAME.eq(name))
            .selectOne(this.context);

    return foundAuthor;
}

/**
 * Find authors by name starting with(like%)
 * @param partName expected name part
 * @return         list of authors
 */
public List<Author> findByNameLike(String partName) {
    // Let's apply a case-insensitive LIKE on the Author's name column
    // We get all the authors with their name starting with "partName"
    List<Author> authorsLike = ObjectSelect.query(Author.class)
            .where(Author.NAME.likeIgnoreCase(partName + "%"))
            .select(context);

    return authorsLike;
}

/**
 * Find authors by name ending with
 * @param partName expected name part
 * @return         list of authors
 */
public List<Author> findByNameEndWith(String partName) {
    // All authors with names ending with "partName"
    List<Author> authorsEnd = ObjectSelect.query(Author.class)
            .where(Author.NAME.endsWith(partName))
            .select(context);

    return authorsEnd;
}

Finde alle Datensätze in der Klasse

Sie können alle zuvor gespeicherten Autoren mit der folgenden Abfrage abfragen:

public List<Author> findAll() {
    // Looking for all authors
    List<Author> authors = ObjectSelect
            .query(Author.class)
            .select(this.context);
    return authors;
}

Objekt aktualisieren

Sie können das Objekt mit der folgenden Abfrage aktualisieren.

/**
 * Update an author
 * @param id        the author's ID
 * @param newName   the new name to set
 * @return          true for a successful operation and false unknown author
 */
public boolean update(int id, String newName) {
    if (StringUtils.isEmpty(newName)) return false;

    // Get the author to update
    Author author = this.findById(id);

    if (author == null) return false;

    // Set its name
    author.setName(newName);
    context.commitChanges();
    return true;
}

Beziehung zu Objekten

So verknüpfen Sie einen Artikel eines Autors mit dem Autor.

/**
 * Attach a fake article to the author
 * @param id    the author's ID
 * @return      true for a successful operation and false unknown author
 */
public boolean attachArticle(int id) {
    // Get the author to link with
    Author author = this.findById(id);

    if (author == null) return false;

    // Create a fake article and link it to the current author
    Article article = context.newObject(Article.class);
    article.setTitle("My post title");
    article.setContent("The content");
    article.setAuthor(author);

    context.commitChanges();

    // Get author's linked data (articles)
    List<Article> articles = author.getArticles();

    return true;
}

Objekt löschen

Sie können das Objekt mit der folgenden Abfrage löschen.

/**
 * Delete an author
 * @param id author's ID
 * @return   true for a successful operation and false unknown author
 */
public boolean delete(int id) {
    // Get the author to delete
    Author author = this.findById(id);

    if (author != null) {
        context.deleteObjects(author);
        context.commitChanges();
        return true;
    } else {
        return false;
    }
}

Löschen Sie alle Datensätze in der Klasse

Mit der Apache Cayenne-API können Sie alle Datensätze in einer Tabelle mit "SQLTemplate" löschen. Hier stellen wir jedoch nur eine grundlegende SQL-Löschabfrage zusammen mit der Zielklasse bereit.

// SQL delete queries for Author and Article classes
SQLTemplate deleteArticles = new SQLTemplate(Article.class, "delete from article");
SQLTemplate deleteAuthors = new SQLTemplate(Author.class, "delete from author");

// Applying the deletion queries
context.performGenericQuery(deleteArticles);
context.performGenericQuery(deleteAuthors);

Ausdruck und Ausdrucksfabrik

Es gibt viele Möglichkeiten, erweiterte Abfragen mit Apache Cayenne zu erstellen. In den meisten Fällen jedoch Expression und ExpressionFactory Ich verwende die Klasse, aber hier ist ein Beispiel Ich werde einige vorstellen.

--likeExp: Wird verwendet, um einen "LIKE" -Ausdruck zu erstellen. --likeIgnoreCaseExp: Wird zum Erstellen des Ausdrucks LIKE_IGNORE_CASE verwendet. --containsExp: Ein Ausdruck, der für LIKE-Abfragen verwendet wird und ein Muster aufweist, das mit einer beliebigen Stelle in der Zeichenfolge übereinstimmt. --containsIgnoreCaseExp: Ähnlich wie enthältExp, verwendet jedoch einen Ansatz, bei dem die Groß- und Kleinschreibung nicht berücksichtigt wird. --startsWithExp: Das Muster entspricht dem Anfang der Zeichenfolge. --startsWithIgnoreCaseExp: Ähnlich wie testsWithExp, jedoch mit einem Ansatz, bei dem die Groß- und Kleinschreibung nicht berücksichtigt wird. --endsWithExp: Ein Ausdruck, der dem Ende der Zeichenfolge entspricht. --endsWithIgnoreCaseExp: Ein Ausdruck, der mit dem Ende einer Zeichenfolge übereinstimmt, bei der die Groß- und Kleinschreibung nicht berücksichtigt wird. --expTrue: Wird für True-Ausdrücke verwendet. --expFalse: Wird in Ausdrücken für BooleanFalse verwendet. --andExp: Wird verwendet, um zwei Ausdrücke mit den Operatoren und zu verketten. -- orExp: Wird verwendet, um zwei Ausdrücke mit dem Operator oder zu verketten.

Fazit

In diesem Lernprogramm haben Sie gelernt, wie Sie die ORM-Funktionalität (Object Relational Mapping) von Apache Cayenne für eine MySQL-Datenbank und grundlegende CRUD-Operationen als Beispiel für eine Abfrage mit einer Eins-zu-Viele-Beziehung konfigurieren. Den vollständigen Quellcode für diesen Artikel finden Sie unter Github.

Recommended Posts

Interaktion mit einer MySQL-Datenbank mithilfe der ORM-Funktion (Object-Relational Mapping) von Apache Cayenne
Versuchen Sie, die Dokumentendatenbank mit X DevAPI mit MySQL Connector / J 8.0.15 zu betreiben
Erstellen Sie eine Memo-App mit Tomcat + JSP + Servlet + MySQL mit Eclipse