Da JavaFX als De-facto-GUI-Framework von Java an Boden gewinnt, wird es Swing früher oder später ersetzen. JavaFX UI und JDBC können eine effektive Kombination sein, wenn Sie eine datenbankgesteuerte Anwendung erstellen, insbesondere in einem Offline- oder eingebetteten System. Dieser Artikel zeigt im Wesentlichen anhand eines Beispielszenarios, wie dies geschehen kann.
Überblick über JDBC-Anwendungen
Die Entwicklung des Java-GUI-Frameworks beruht nun auf der JavaFX-Bibliothek. Es bietet eine leistungsstarke und dennoch flexible Alternative zur GUI-Entwicklung, im Gegensatz zu seinem bestehenden Swing- und AWT-Framework. JavaFX stellt ein großes Array von Steuerelementen und Komponenten bereit, die beim schnellen und effektiven Erstellen einer GUI-Schnittstelle helfen. Es ist sehr einfach, eine Desktop-Anwendung zu entwickeln, die mit der Back-End-Datenbank interagiert. Ein JDBC (Java Database Connectivity) Die Anwendung verfügt in erster Linie über ein Back-End-Datenbanksystem wie MySQL, Derby, Oracle oder eine andere Datenbank. Java-Code wird geschrieben, um Datensätze aus einer oder mehreren Tabellen in der Datenbank abzurufen. Die SQL (Structured Query Language) Abfragen werden vom Java-Code ausgelöst und zur Verarbeitung an die Datenbank-Engine gesendet. Der JDBC-Treiber fungiert als Vermittler zwischen dem Java-Programm und der Datenbank und interpretiert die Fülle von Informationen hin und her, so dass sowohl die unübertroffene Partei, wie beispielsweise die Datenbank, als auch das Java-Programm sich zu einer praktikablen Lösung versöhnen können. Die Datenbank hat absolut keine Ahnung von Java-Code, seiner Syntax oder irgendetwas darüber. Es versteht einfach SQL und kann nur damit kommunizieren. Java hingegen ist ein OOP (Object Oriented Programming) Sprache und hat auch keine Ahnung von SQL oder dessen Syntax. Um die Kommunikation zu ermöglichen, liefert der Datenbankanbieter native Treiber zusammen mit der Datenbank. Dies wird als JDBC-Treiber bezeichnet. Beachten Sie, dass vier Arten von Treibern verfügbar sind. Sie werden umgangssprachlich als Typ-1-, Typ-2-, Typ-3- und Typ-4-Treiber bezeichnet. Die nativen Treiber sind Typ-4-Treiber und werden am häufigsten verwendet. Sie sind auch effizienter als andere Typen. Ein Java-Programm kann diese JDBC-Treiber als externe Bibliothek in das Java-Programm aufnehmen, da sie üblicherweise in JAR-Archivdateien enthalten sind.
JavaFX in die Szene
Jede Datenbankanwendung benötigt eine Schnittstelle, damit der Benutzer mit den Datenbankinformationen interagieren kann. Besser, wenn es sich um eine GUI-Schnittstelle handelt, bei der wir uns nicht auf eine einschüchternde Befehlsschnittstelle auf niedriger Ebene herablassen müssen, sondern mit einem Klick auf eine Schaltfläche bekommen, was wir wollen. In dieser Hinsicht kann JavaFX mit JDBC eine Killer-Kombination sein, da es eine ganze Reihe von visuell ansprechenden GUI-Komponenten hat, die verwendet werden können, um Datenbankeinträge sinnvoller darzustellen. Datensätze können beispielsweise mit der TableView tabellarisch dargestellt werden Steuerung. Oder wir können ein Formular erstellen, um neue Datensätze in die Datenbanktabelle hinzuzufügen. Die vom Benutzer eingegebenen Daten können vor dem Senden an die Datenbank durch Java-Code überprüft werden. Die Back-End-Datenbank-Engine erhält eine Pause von der Validierung von Daten und der angehaltenen Verarbeitung aufgrund eines Eingabefehlers. Darüber hinaus kann der Endbenutzer ein Laie sein, der wenig oder keine Ahnung von den Beschränkungen der Eingabedaten hat. Dies geschieht idealerweise, wenn ein Eingabeformular mit TextField erstellt wird , Label , ComboBox und ListView Steuerelemente in JavaFX. Die von Button generierten Ereignisse und andere Steuerelemente werden so gehandhabt, dass der Benutzer sich bei der Interaktion mit der GUI-Schnittstelle wohlfühlt.
In ein Beispielszenario
Im folgenden veranschaulichten Beispiel implementieren wir eine ListView Suchoperation durch Eingabetext in einem TextField . Der ausgewählte Eintrag in der ListView wird entsprechend aus der Backend-Datenbank geholt und in der TableView angezeigt Steuerung. Es handelt sich also in erster Linie um eine Anwendung zum Abrufen und Anzeigen. Andere Datenbankoperationen – wie das Einfügen, Löschen und Aktualisieren von Datensätzen – sind aufgrund von Größenbeschränkungen nicht implementiert. Es wäre eine schöne Übung, sie selbst umzusetzen.
Bevor wir beginnen, müssen wir also eine Datenbanktabelle und ein Java-Projekt erstellen. Wir verwenden MySQL als Back-End-Datenbank; Sie können auch andere wählen, aber stellen Sie sicher, dass Sie geeignete Treiber in Ihre pom.xml aufnehmen Datei. Hier ist ein Teil des SQL-Codes zum Erstellen der Tabelle, zum Einfügen einiger Dummy-Daten und einiger anderer Operationen.
CREATE DATABASE addressbook; USE DATABASE addressbook; DROP TABLE IF EXISTS contact; CREATE TABLE contact( id INT UNSIGNED NOT NULL AUTO_INCREMENT, name VARCHAR(100) NOT NULL, nick_name VARCHAR(20), address VARCHAR(128), home_phone VARCHAR(10), work_phone VARCHAR(10), cell_phone VARCHAR(10), email VARCHAR(100), birthday date, web_site VARCHAR(100), profession VARCHAR(100), PRIMARY KEY (id) ); INSERT INTO contact (name, nick_name, address, home_phone, work_phone, cell_phone, email, birthday, web_site,profession) VALUES ('Bruce Wayne', 'batman', 'XYZ Batcave', '9876543210', '6278287326', '9182872363', '[email protected]', '1976/02/03', 'batblog.com', 'Super Hero'); ... INSERT INTO contact (...) VALUES (...); Maven Project: pom.xml <project xmlns_xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.mano.jdbc.examples</groupId> <artifactId>JavaFXJDBCApp</artifactId> <version>1.0-SNAPSHOT</version> <packaging>jar</packaging> <name>JavaFXJDBCApp</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding> UTF-8 </project.build.sourceEncoding> </properties> <build> <plugins> <plugin> <groupId> org.apache.maven.plugins </groupId> <artifactId> maven-compiler-plugin </artifactId> <version>2.5.1</version> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> </plugins> </build> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> <!-- https://mvnrepository.com/artifact/mysql/ mysql-connector-java --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.6</version> </dependency> </dependencies> </project>
Lassen Sie uns nun ein Domänenobjekt erstellen, das wir sowohl in ListView verwenden und TableView weil sie beide verwandt sind, wie in unserem Fall angegeben. Die TableView enthält eine beobachtbare Liste von Personen (ContactPerson ) basierend auf dem Namen der ausgewählten Person aus der ListView Steuerung. Wir haben auch ein TextField um schnell nach Artikeln zu suchen (Ansprechpartner name), die in der ListView enthalten ist . Bei Auswahl eines bestimmten Elements aus der ListView , wird eine SQL-Abfrage ausgelöst und relevante Datensätze werden abgerufen, um die TableView zu füllen entsprechend kontrollieren.
Domänenobjekt:Kontaktperson
Der Ansprechpartner Klasse ist nichts anderes als die POJO-Darstellung des Kontakts Tabellenattribute. Es enthält den Konstruktor und einen einfachen Getter-Setter Methoden.
package org.mano.jdbc.examples; import java.util.Date; public class ContactPerson { private int id; private String name; private String nickName; private String address; private String homePhone; private String workPhone; private String cellPhone; private String email; private Date birthDate; private String webSite; private String profession; public ContactPerson() { } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getNickName() { return nickName; } public void setNickName(String nickName) { this.nickName = nickName; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } public String getHomePhone() { return homePhone; }< public void setHomePhone(String homePhone) { this.homePhone = homePhone; } public String getWorkPhone() { return workPhone; } public void setWorkPhone(String workPhone) { this.workPhone = workPhone; } public String getCellPhone() { return cellPhone; } public void setCellPhone(String cellPhone) { this.cellPhone = cellPhone; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public Date getBirthDate() { return birthDate; } public void setBirthDate(Date birthDate) { this.birthDate = birthDate; } public String getWebSite() { return webSite; } public void setWebSite(String webSite) { this.webSite = webSite; } public String getProfession() { return profession; } public void setProfession(String profession) { this.profession = profession; } }
Datenzugriffsobjekt:ContactDAO
Das ContactDAO ist eine Datenzugriffsobjektklasse, die hauptsächlich Datenbankzugriffsoperationen umfasst. Es implementiert das DAO Schnittstelle. Diese Schnittstelle ist in unserem Beispiel möglicherweise nicht wichtig, kann aber sinnvoll eingesetzt werden, wenn die Anwendung um weitere Datenzugriffsobjektklassen erweitert wird. Hier, das DAO Die Schnittstelle enthält eine Verbindungszeichenfolge, einen Treiber sowie einen Benutzernamen und ein Kennwort für den Zugriff auf die MySQL-Datenbank.
DAO.java
package org.mano.jdbc.examples; public interface DAO { public static final String DB_URL = "jdbc:mysql://localhost:3306/"+ "addressbook?zeroDateTimeBehavior=convertToNull"; public static final String DRIVER = "com.mysql.jdbc.Driver"; public static final String USER = "root"; public static final String PASS = "secret"; }
ContactDAO.java
package org.mano.jdbc.examples; import java.sql.*; import java.util.ArrayList; import java.util.List; public class ContactDAO implements DAO { private ontactPerson createContactPerson(ResultSet rs) { ContactPerson p = new ContactPerson(); try { p.setId(rs.getInt("id")); p.setName(rs.getString("name")); p.setNickName(rs.getString("nick_name")); p.setAddress(rs.getString("address")); p.setHomePhone(rs.getString("home_phone")); p.setWorkPhone(rs.getString("work_phone")); p.setCellPhone(rs.getString("cell_phone")); p.setEmail(rs.getString("email")); p.setBirthDate(rs.getDate("birthday")); p.setWebSite(rs.getString("web_site")); p.setProfession(rs.getString("profession")); } catch (SQLException ex) { } return p; } public List<ContactPerson> getContacts() { String sql = "Select * from contact order by name"; List<ContactPerson> list = new ArrayList<>(); try { Class.forName(DRIVER); Connection con = DriverManager.getConnection (DB_URL, USER, PASS); Statement stmt = con.createStatement(); ResultSet rs = stmt.executeQuery(sql); while (rs.next()) { ContactPerson p = createContactPerson(rs); list.add(p); } rs.close(); con.close(); } catch (ClassNotFoundException | SQLException ex) { } return list; } public List<ContactPerson> getContactsForName(String name) { String sql = "Select * from contact where name like '%" + name + "%'"; List<ContactPerson> list = new ArrayList<>(); try { Class.forName(DRIVER); Connection con = DriverManager.getConnection (DB_URL, USER, PASS); Statement stmt = con.createStatement(); ResultSet rs = stmt.executeQuery(sql); while (rs.next()) { ContactPerson p = createContactPerson(rs); list.add(p); } rs.close(); con.close(); } catch (ClassNotFoundException | SQLException ex) { } return list; } }
JavaFX-GUI-Schnittstelle:ContactBrowser
In der JavaFX-Anwendung namens ContactBrowser , richten wir alle Steuerelemente programmgesteuert ein. Dies kann auch mit FXML oder Builder-Utility-Tools wie Scene Builder eingestellt werden. Aber nach Meinung des Schreibers können sie verwendet werden, wenn man genug Erfahrung damit gesammelt hat, was hinter den Kulissen von JavaFX passiert. Die GUI ist in erster Linie ein Zusammenspiel von drei Steuerelementen, wie z. B. einem TextField (Suchfeld ), eine ListView (Listenansicht ) und TableView (contactTableView ). Der Code ist selbsterklärend, mit Kommentaren an geeigneten Stellen. Der Lambda-Ausdruck wird wo immer möglich verwendet, um den Code knapp zu halten. Schlagen Sie bei Bedarf in der JavaFX-API-Dokumentation nach.
package org.mano.jdbc.examples; import javafx.application.Application; import javafx.beans.value.*; import javafx.collections.*; import javafx.collections.transformation.*; import javafx.geometry.Insets; import javafx.scene.Scene; import javafx.scene.control.*; import javafx.scene.control.cell.PropertyValueFactory; import javafx.scene.layout.*; import javafx.scene.paint.Color; import javafx.stage.Stage; public class ContactBrowser extends Application { // List of contact table properties private String[] propertyName = {"id", "name", "nickName", "address", "homePhone", "workPhone", "cellPhone", "email", "birthDate", "webSite", "profession"}; private String[] propertyLabel = {"ID", "Name", "Nick Name", "Address", "Home Phone", "Work Phone", "Cell Phone", "Email", "Birth Date", "Website", "Profession"}; private ContactDAO contact = new ContactDAO(); private final GridPane gridPane = new GridPane(); private final Label lblName = new Label("Search by Name"); private final TextField searchField = new TextField(); private ObservableList<ContactPerson> observableNames; private FilteredList<ContactPerson> filteredData; private SortedList<ContactPerson> sortedData; private final ListView<ContactPerson> listView; TableView<ContactPerson> contactTableView = new TableView<>(); public ContactBrowser2() { lblName.setTextFill(Color.web("#0076a3")); observableNames = FXCollections.observableArrayList (contact.getContacts()); filteredData = new FilteredList<> (observableNames, p -> true); sortedData = new SortedList<>(filteredData); listView = new ListView<>(sortedData); } @Override public void start(Stage primaryStage) { primaryStage.setTitle("Address Book"); primaryStage.setMaximized(true); BorderPane borderPane = new BorderPane(); Scene scene = new Scene(borderPane,650,400,true); gridPane.setPadding(new Insets(10)); gridPane.setHgap(5); gridPane.setVgap(5); gridPane.add(lblName, 0, 0); gridPane.add(searchField, 0, 1); // Search TextField event handling searchField.textProperty() .addListener((observable, oldValue, newValue) -> filteredData.setPredicate(str -> { if (newValue == null || newValue.isEmpty()) return true; if (str.getName().toLowerCase().contains (newValue.toLowerCase())) return true; return false; })); listView.getSelectionModel().setSelectionMode (SelectionMode.SINGLE); listView.setPrefHeight(Integer.MAX_VALUE); // Sets a new cell factory to use in the ListView. // This throws away all old list cells and new ListCells // created with the new cell factory. listView.setCellFactory(listView-> { Tooltip tooltip = new Tooltip(); ListCell<ContactPerson> cell = new ListCell<ContactPerson>() { @Override public voidupdateItem(ContactPerson contactPerson, Boolean empty) { super.updateItem(contactPerson, empty); if (contactPerson != null) { setText(contactPerson.getName()); tooltip.setText(contactPerson.getNickName()); setTooltip(tooltip); } else setText(null); } }; return cell; }); gridPane.add(listView, 0, 2); // Create and initializing TableView ObservableList<ContactPerson> contactPeopleList = FXCollections.observableArrayList(); contactTableView.setItems(contactPeopleList); contactTableView.setColumnResizePolicy( TableView.CONSTRAINED_RESIZE_POLICY); for (int i = 0; i < propertyLabel.length; i++) { TableColumn<ContactPerson, Object> col = new TableColumn<>(propertyLabel[i]); col.setCellValueFactory(new PropertyValueFactory<>(propertyName[i])); contactTableView.getColumns().add(col); } borderPane.setCenter(contactTableView) borderPane.setLeft(gridPane); // TableView will populate from the contactPeopleList // contactPeopleList will have value according to the // item selected in the ListView listView.getSelectionModel() .selectedItemProperty() .addListener(new ChangeListener<ContactPerson>() { @Override public void changed( ObservableValue<? extends ContactPerson> observable, ContactPerson oldValue, ContactPerson newValue) { if (observable != null && observable.getValue() != null) { contactPeopleList.clear(); contactPeopleList.addAll( contact.getContactsForName (newValue.getName())); } } }); primaryStage.setScene(scene); primaryStage.show(); } public static void main(String[] args) { launch (args); } }
Ausgabe
Abbildung 1: Codeausgabe
Schlussfolgerung
Eine JDBC-Anwendung mit JavaFX bedeutet im Wesentlichen, dass das JavaFX-GUI-Framework als Front-End-Entwicklungsengine und JDBC für die Back-End-Datenbankinteraktion verwendet wurde. Sie können von verschiedenen Typen mit N sein Anzahl der darin definierten Funktionen. Die Basis ist die CRUD-Anwendung. Wir haben einen Teil der Such- und Anzeigeoperation implementiert. Folgendes können Sie tun, um es zu erweitern:Implementieren Sie Create , Löschen und Aktualisieren Operationen; außerdem können Sie in der ListView Namen mit Bildern hinzufügen . Viel Spaß beim Programmieren 😉