Vì JavaFX đang trở thành nền tảng với tư cách là khung GUI trên thực tế của Java, nên sớm muộn gì nó cũng sẽ thay thế Swing. JavaFX UI và JDBC có thể là sự kết hợp hiệu quả khi tạo ứng dụng hướng cơ sở dữ liệu, đặc biệt là trong hệ thống nhúng hoặc ngoại tuyến. Bài viết này về cơ bản chỉ ra cách điều này có thể được thực hiện với một tình huống ví dụ.
Tổng quan về ứng dụng JDBC
Sự phát triển của khung Java GUI hiện nằm trên thư viện JavaFX. Nó cung cấp một giải pháp thay thế mạnh mẽ nhưng linh hoạt cho phát triển GUI, trái ngược với khung Swing và AWT hiện có của nó. JavaFX cung cấp một mảng lớn hoặc các điều khiển và thành phần giúp xây dựng giao diện GUI một cách nhanh chóng và hiệu quả. Rất dễ dàng để phát triển một ứng dụng máy tính để bàn tương tác với cơ sở dữ liệu back-end. A JDBC (Kết nối cơ sở dữ liệu Java) ứng dụng chủ yếu có hệ thống cơ sở dữ liệu back-end như MySQL, Derby, Oracle hoặc bất kỳ cơ sở dữ liệu nào khác. Mã Java được viết để tìm nạp các bản ghi từ một hoặc nhiều bảng trong cơ sở dữ liệu. SQL (Ngôn ngữ truy vấn có cấu trúc) các truy vấn được kích hoạt từ mã Java và được gửi đến công cụ cơ sở dữ liệu để xử lý. Trình điều khiển JDBC hoạt động như một trung gian giữa chương trình Java và cơ sở dữ liệu và diễn giải vô số thông tin đến và đi, để cả bên chưa đối sánh, chẳng hạn như cơ sở dữ liệu và chương trình Java có thể dung hòa thành một giải pháp khả thi. Cơ sở dữ liệu hoàn toàn không biết gì về mã Java, các cú pháp của nó hoặc bất cứ điều gì về nó. Nó chỉ hiểu SQL và chỉ có thể giao tiếp với nó. Mặt khác, Java là một OOP (Lập trình hướng đối tượng) ngôn ngữ và không biết gì về SQL hoặc các cú pháp của nó. Để có thể giao tiếp, nhà cung cấp cơ sở dữ liệu cung cấp các trình điều khiển gốc cùng với cơ sở dữ liệu. Đây được gọi là trình điều khiển JDBC. Lưu ý rằng có bốn loại trình điều khiển có sẵn. Chúng được gọi một cách thông tục là trình điều khiển Kiểu-1, Kiểu-2, Kiểu-3 và Kiểu-4. Trình điều khiển gốc là trình điều khiển Loại 4 và được sử dụng phổ biến nhất. Chúng cũng hiệu quả hơn các loại khác. Một chương trình Java có thể bao gồm các trình điều khiển JDBC này như một thư viện bên ngoài vào chương trình Java, vì chúng thường có trong các tệp lưu trữ JAR.
JavaFX vào cảnh
Mọi ứng dụng cơ sở dữ liệu đều yêu cầu một giao diện để người dùng có thể tương tác với thông tin cơ sở dữ liệu. Tốt hơn, nếu đó là giao diện GUI, nơi chúng ta không phải cúi xuống giao diện lệnh cấp thấp, đáng sợ mà có được những gì chúng ta muốn chỉ bằng một cú nhấp chuột. Về khía cạnh này, JavaFX với JDBC có thể là một sự kết hợp tuyệt vời vì nó có khá nhiều thành phần GUI trực quan thú vị có thể được sử dụng để biểu diễn các bản ghi cơ sở dữ liệu theo cách có ý nghĩa hơn. Ví dụ:các bản ghi có thể được hiển thị dưới dạng bảng với TableView điều khiển. Hoặc, chúng ta có thể tạo một biểu mẫu để thêm các bản ghi mới vào bảng cơ sở dữ liệu. Dữ liệu đầu vào của người dùng có thể được xác nhận thông qua mã Java trước khi gửi đến cơ sở dữ liệu. Công cụ cơ sở dữ liệu back-end nhận được thời gian nghỉ ngơi từ việc xác thực dữ liệu và quá trình xử lý bị đình trệ do lỗi đầu vào. Hơn nữa, người dùng cuối có thể là một người ít hoặc không có ý tưởng về các ràng buộc của dữ liệu đầu vào. Điều này được thực hiện một cách lý tưởng khi biểu mẫu đầu vào được tạo bằng TextField , Nhãn , ComboBox và ListView điều khiển trong JavaFX. Các sự kiện được tạo bởi Nút và các điều khiển khác được xử lý theo cách mà người dùng cảm thấy thoải mái khi tương tác với giao diện GUI.
Vào một tình huống mẫu
Trong ví dụ minh họa sau, chúng tôi sẽ triển khai ListView hoạt động tìm kiếm bằng văn bản đầu vào trong Trường văn bản . Mục đã chọn trong ListView được tìm nạp tương ứng từ cơ sở dữ liệu phía sau và được hiển thị trong TableView điều khiển. Vì vậy, nó chủ yếu là một loại ứng dụng tìm nạp và hiển thị. Các hoạt động cơ sở dữ liệu khác — chẳng hạn như chèn, xóa và cập nhật bản ghi — không được thực hiện do các hạn chế về kích thước. Sẽ là một bài tập hay nếu bạn tự thực hiện chúng.
Vì vậy, trước khi bắt đầu, chúng ta phải tạo một bảng cơ sở dữ liệu và một dự án Java. Chúng tôi sẽ sử dụng MySQL làm cơ sở dữ liệu back-end; bạn có thể chọn bất kỳ trình điều khiển nào khác nhưng hãy đảm bảo bao gồm các trình điều khiển thích hợp trong pom.xml của bạn tập tin. Đây là một số mã SQL để tạo bảng, chèn một số dữ liệu giả và một số thao tác khác.
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>
Bây giờ, hãy tạo một đối tượng miền mà chúng tôi sẽ sử dụng trong cả ListView và TableView bởi vì cả hai đều có liên quan, như đã nêu trong trường hợp của chúng tôi. TableView sẽ chứa danh sách những người có thể quan sát được ( Người liên hệ ) dựa trên tên của nhân vật đã chọn từ ListView điều khiển. Chúng tôi cũng có Trường văn bản để tìm kiếm nhanh các mục ( Người liên hệ tên) có trong ListView . Khi lựa chọn một mục cụ thể từ ListView , một truy vấn SQL được kích hoạt và các bản ghi có liên quan được tìm nạp để điền vào TableView kiểm soát phù hợp.
Đối tượng miền: Người liên hệ
Người liên hệ lớp không là gì ngoài đại diện POJO của địa chỉ liên hệ thuộc tính bảng. Nó chứa hàm tạo và getter-setter đơn giản các phương pháp.
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; } }
Đối tượng truy cập dữ liệu: ContactDAO
Liên hệDAO là một lớp đối tượng truy cập dữ liệu chủ yếu bao gồm thao tác truy cập cơ sở dữ liệu. Nó triển khai DAO giao diện. Giao diện này có thể không quan trọng trong ví dụ của chúng tôi nhưng có thể được sử dụng tốt nếu ứng dụng được mở rộng với nhiều lớp đối tượng truy cập dữ liệu hơn. Đây, DAO giao diện bao gồm chuỗi kết nối, trình điều khiển, tên người dùng và mật khẩu để truy cập cơ sở dữ liệu MySQL.
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; } }
Giao diện JavaFX GUI: ContactBrowser
Trong ứng dụng JavaFX có tên là ContactBrowser , chúng tôi thiết lập tất cả các điều khiển theo chương trình. Điều này cũng có thể được thiết lập bằng FXML hoặc các công cụ tiện ích trình tạo như Trình tạo cảnh. Tuy nhiên, theo ý kiến của người ghi chép, chúng có thể được sử dụng khi một người đã có đủ kinh nghiệm về những gì diễn ra phía sau hậu trường trong JavaFX. GUI chủ yếu là sự tác động lẫn nhau của ba điều khiển, chẳng hạn như Trường văn bản ( searchField ), một ListView ( listView ) và TableView ( contactTableView ). Mã này có thể tự giải thích, với các nhận xét được đưa ra ở những nơi thích hợp. Biểu thức Lambda được sử dụng ở bất cứ nơi nào có thể áp dụng để giữ cho mã ngắn gọn. Tham khảo tài liệu JavaFX API nếu cần.
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); } }
Đầu ra
Hình 1: Đầu ra mã
Kết luận
Một ứng dụng JDBC với JavaFX về cơ bản có nghĩa là khung JavaFX GUI được sử dụng làm công cụ phát triển front-end và JDBC được sử dụng cho tương tác cơ sở dữ liệu back-end. Chúng có thể thuộc nhiều loại với N số lượng chức năng được xác định trong chúng. Cơ bản là ứng dụng CRUD. Chúng tôi đã thực hiện một phần của hoạt động tìm kiếm và hiển thị. Đây là những gì bạn có thể làm để mở rộng nó:triển khai Tạo , Xóa và Cập nhật các hoạt động; ngoài ra, bạn có thể thêm tên bằng hình ảnh trong ListView . Chúc bạn viết mã vui vẻ 😉