Datenbank-Anbindung
Hier soll ein Minimal-Beispiel vorgeführt werden. D.h. wie kann eine Netbeans Platform Application Kontakt mit einer Datenbank aufnehmen und Daten in die Datenbank schreiben. Alle darüber hinausgehenden Dinge wie z.B. eine Oberfläche um Datenbank-Inhalte anzuzeigen oder zu ändern soll Stoff anderer Kapitel sein.
Folgende Schritte sind notwendig, um dieses Minimal-Beispiel zu erhalten:
- Erzeugung einer Datenbank. In unserem Beispiel eine JavaDB Datenbank oder eine MySQL-Datenbank
- Erzeugung von 2 Wrapped Libraries. D.h. Libraries, die in Netbeans-Module eingepackt sind.
- Ein Modul für den Datenbank-Treiber
- Ein Modul für den JPA-Treiber
- Erzeugung eines Moduls, das die Datenbank tatsächlich benutzt. Dieses Modul enthält in unserem Fall
- Eine Persistence-Unit, die die Konfiguration des JPA-Treibers enthält. Diese Konfiguration enthält unter anderem die Zugangsdaten für die Datenbank
- Eine Entity-Klasse pro Tabelle der Datenbank (in unserem Falle eine)
- Eine weitere Klasse, die die Datenbank-Verbindung benutzt, um Daten in die Datenbank zu schreiben.
Datenbank anlegen
- Im Netbeans den Reiter Services auswählen
- Databases -> Java DB -> rechte Maustaste -> Create Database ...
- Database Name: testdb; User Name: test; Password: test; Confirm Password: test;
- OK
Wrapped Libraries
Zuerst eine neues Programm JpaTest anlegen, wie auf der Seite NetBeans Platform Application im Absatz Projekt erstellen erklärt.Derby Client
Um den Treiber für eine JavaDB-Datenbank in eine Wrapped Library einzubinden geht man folgendermaßen vor.- in der Appllication den Knoten Modules auswählen
- rechte Maustaste -> Add New Library ...
- Library -> Browse Button
- im Installations-Verzeichnis des Glassfish-Servers im Verzeichnis javadb/lib die Library derbyclient.jar auswählen -> Next
- Project Name: DerbyClient -> Next
- Code Name Base: org.apache.derby -> Finish
MySQL Client
Um den Treiber für eine MySQL-Datenbank in eine Wrapped Library einzubinden geht man folgendermaßen vor.- falls noch nicht geschehen: Datenbank-Treiber für MySQL besorgen unter https://dev.mysql.com/downloads/connector/j/
- in der Application den Knoten Modules auswählen
- rechte Maustaste -> Add New Library...
- Library -> Browse Button
- im Installations-Verzeichnis des Treibers den Treiber auswählen -> Next
- Projekt Name: MySQLClient -> Next
- Code Name Base: com.mysql
EclipseLink
- in der Application den Knoten Modules auswählen
- rechte Maustaste -> Add New Library ...
- Library -> Browse Button
- im Installations-Verzeichnis der NetBeans-IDE im Verzeichnis java/modules/ext/eclipselink folgende Library auswählen, dann -> Next
- eclipselink-xx.jar
- javax.persistence_xx.jar
- org.eclipse.persistence.jpa.jpql_xx.jar
- org.eclipse.persistence.jpa.modelgen_xx.jar
- Project Name: EclipseLink -> Next
- Code Name Base: org.eclipselink -> Finish
Core Modul
Bisher wurde die Datenbank angelegt und die Möglichkeiten geschaffen auf diese Datenbank zuzugreifen. Im Core Modul sollen diese Möglichkeiten nun genutzt werden.- in der Application den Knoten Modules auswählen
- rechte Maustaste -> Add New ...
- Project Name: Core -> Next
- Code Name Base -> de.erichweigand.jpatest.core -> Finish
- Im Core Modul Libraries auswählen -> rechte Maustaste -> Add Module Dependency -> folgende Abhängigkeiten dazufügen
- DerbyClient (für JavaDB Datenbanken)
- MySQLClient (für MySQL Datenbanken)
- EclipseLink
- Module System API
Persistence Unit
Eine Persistence Unit ist eine Konfiguration in XML beschrieben. Das XML ist in einer Datei namens persistence.xml. Diese Datei ist in einem Unterverzeichnis namens META-INF im Modul-Verzeichnis.- Core Modul -> Source Packages -> auswählen
- rechte Maustaste -> New .. -> Folder
- Folder Name: META-INF
- META-INF auswählen
- rechte Maustaste -> New -> Other -> Categories: XML -> File Types: XML Document -> Next
- Filename: persistence.xml -> Next -> Finish
<?xml version="1.0" encoding="UTF-8"?> <persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"> <persistence-unit name="PersonPU" transaction-type="RESOURCE_LOCAL"> <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider> <class>de.erichweigand.jpatest.core.PersonEntity</class> <shared-cache-mode>ALL</shared-cache-mode> <properties> <property name="driverClass" value="org.apache.derby.jdbc.ClientDriver"/> <!-- <property name="eclipselink.logging.level" value="FINE"/>--> <property name="javax.persistence.jdbc.url" value="jdbc:derby://localhost:1527/testdb"/> <property name="javax.persistence.jdbc.user" value="test"/> <property name="javax.persistence.jdbc.driver" value="org.apache.derby.jdbc.ClientDriver"/> <property name="javax.persistence.jdbc.password" value="test"/> <property name="eclipselink.ddl-generation" value="drop-and-create-tables"/> </properties> </persistence-unit> </persistence>Für MySQL-Datenbanken sieht diese Datei folgendermaßen aus.
<?xml version="1.0" encoding="UTF-8"?> <persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd"> <persistence-unit name="PersonPU" transaction-type="RESOURCE_LOCAL"> <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider> <class>de.erichweigand.jpatest.core.PersonEntity</class> <properties> <property name="driverClass" value="com.mysql.jdbc.Driver"/> <property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/test?zeroDateTimeBehavior=convertToNull"/> <property name="javax.persistence.jdbc.user" value="test"/> <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/> <property name="javax.persistence.jdbc.password" value="test"/> <property name="javax.persistence.schema-generation.database.action" value="create"/> </properties> </persistence-unit> </persistence>
Entity Klassen
JPA ist eine Möglichkeit eine Datenbank zu abstrahieren. Die Datensätze einer Datenbank-Tabelle werden hier direkt in Java-Objekte umgewandelt. Diese Java-Objekte nennt man Entity-Klassen. Die Entity-Klasse, die wir für unser Beispiel benutzen ist.package de.erichweigand.jpatest.core; import java.io.Serializable; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Table; @Entity @Table(name = "person") public class PersonEntity implements Serializable { private static final long serialVersionUID = 1L; @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; private String firstname = ""; private String lastname = "Unknown"; public PersonEntity() { } public PersonEntity(String firstname, String lastname) { this.firstname = firstname; this.lastname = lastname; } public synchronized String getFirstname() { return firstname; } public synchronized void setFirstname(String firstname) { this.firstname = firstname; } public synchronized String getLastname() { return lastname; } public synchronized void setLastname(String lastname) { this.lastname = lastname; } public synchronized Long getId() { return id; } @Override public boolean equals(Object o) { if (o == null) { return false; } if (getClass() != o.getClass()) { return false; } return this.getId().equals(((PersonEntity) o).getId()); } @Override public int hashCode() { int hash = 7; hash = 97 * hash + (this.id != null ? this.id.hashCode() : 0); return hash; } @Override public String toString() { StringBuilder sb = new StringBuilder(); sb.append("[").append(getId()).append("] "); if (!this.getFirstname().isEmpty()) { sb.append(this.getFirstname()); } if (!this.getLastname().isEmpty()) { sb.append(" ").append(this.getLastname()); } return sb.toString(); } }
Datenbank benutzen
Mit Hilfe dieser Klasse wird die Datenbank-Verbindung realisiert und einige Test-Daten in die Datenbank geschrieben. Das Ergebnis kann in der Datenbank überprüft werden.package de.erichweigand.jpatest.core; import javax.persistence.EntityManager; import javax.persistence.EntityManagerFactory; import javax.persistence.Persistence; import org.openide.modules.OnStart; @OnStart public final class Installer implements Runnable { private static final EntityManagerFactory EMF = Persistence.createEntityManagerFactory("PersonPU"); @Override public void run() { // put some test data into the FamilyTreeManager map addPerson(new PersonEntity("Homer", "Simpson")); addPerson(new PersonEntity("Marge", "Simpson")); addPerson(new PersonEntity("Bart", "Simpson")); addPerson(new PersonEntity("Lisa", "Simpson")); addPerson(new PersonEntity("Maggie", "Simpson")); } public void addPerson(final PersonEntity person) { EntityManager em = EMF.createEntityManager(); try { em.getTransaction().begin(); em.persist(person); em.getTransaction().commit(); } catch (Exception ex) { } finally { em.close(); } } }