JavaFX JDBC MySQL Database Example

In this tutorial, we will learn how to create a JavaFX application with database connectivity. In this JavaFx application, we create a Registration Form and we will store user registration form data into MySQL database using JDBC API.
Download the source code of this tutorial on my GitHub Repository.

Add Maven Dependency

Let's add MySQL driver maven dependency to above-created maven project:
        <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>8.0.15</version>
        </dependency>

Database Setup

Make sure that you have installed the MySQL server on your machine.
Let's first create a database with the following SQL statement:
create database javafx_registration;
Now, let's create a registration table in the above-created database with the following SQL statement:
CREATE TABLE registration
( 
 id BIGINT PRIMARY KEY AUTO_INCREMENT,
 full_name varchar(250) NOT NULL,
 email_id varchar(250) NOT NULL,
 password varchar(250)
);

Create the Main Application Class

Let’s first write the MainApp application class. As usual, For creating a JavaFX application, we’ll need to extend our Main class from javafx.application.Application and override its start() method.
package com.javaguides.javafx.registration;

import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;


public class MainApp extends Application {

    @Override
    public void start(Stage stage) throws Exception {
        System.out.println(getClass());
        Parent root = FXMLLoader.load(getClass().getResource("/fxml/registration_form.fxml"));
        stage.setTitle("User Registration");
        stage.setScene(new Scene(root, 800, 500));
        stage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}
We first load the FXML document using FXMLLoader. We wil create registration_form.fxml file in next step.

Create the Layout for Our Application using FXML

We’ll use the JavaFX GridPane layout for designing the registration form. It enables us to create a flexible grid of rows and columns in which to layout UI-controls.
<?import javafx.scene.layout.GridPane?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.text.Font?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.control.PasswordField?>
<?import javafx.scene.control.Button?>
<GridPane fx:controller="com.javaguides.javafx.registration.RegisterController"
    xmlns:fx="http://javafx.com/fxml" alignment="center"
          hgap="10" vgap="10">
    <padding>
        <Insets top="40" right="40" bottom="40" left="40"/>
    </padding>
    <columnConstraints>
        <ColumnConstraints minWidth="100" prefWidth="100"
                           maxWidth="Infinity" halignment="RIGHT"></ColumnConstraints>
        <ColumnConstraints minWidth="200" prefWidth="200"
                           maxWidth="Infinity" hgrow="ALWAYS"></ColumnConstraints>
    </columnConstraints>
    <!-- Add Header Label -->
    <Label text="Registration Form (FXML)" GridPane.columnIndex="0" 
           GridPane.rowIndex="0" GridPane.columnSpan="2" 
           GridPane.rowSpan="1" GridPane.halignment="CENTER" >
        <font>
            <Font name="Arial" size="24" ></Font>
        </font>
        <GridPane.margin>
            <Insets top="20" right="0" bottom="20" left="0"></Insets>
        </GridPane.margin>
    </Label>
    <!-- Add Name Label -->
    <Label text="Full Name : " GridPane.columnIndex="0" 
           GridPane.rowIndex="1" ></Label>
    <!-- Add Name Text Field -->
    <TextField fx:id="fullNameField" prefHeight="40" 
               GridPane.columnIndex="1" GridPane.rowIndex="1"/>
    <!-- Add Email Label -->
    <Label text="Email ID : " GridPane.columnIndex="0" 
           GridPane.rowIndex="2" ></Label>
    <!-- Add Email Text Field -->
    <TextField fx:id="emailIdField" prefHeight="40" 
               GridPane.columnIndex="1" GridPane.rowIndex="2"/>
    <!-- Add Password Label -->
    <Label text="Password : " GridPane.columnIndex="0" 
           GridPane.rowIndex="3" ></Label>
    <!-- Add Password Field -->
    <PasswordField fx:id="passwordField" prefHeight="40" 
                   GridPane.columnIndex="1" GridPane.rowIndex="3"/>
    <!-- Add Submit Button -->
    <Button fx:id="submitButton" text="Submit"
            prefWidth="100" prefHeight="40" defaultButton="true"
            GridPane.columnIndex="0" GridPane.rowIndex="4"
            GridPane.columnSpan="2" GridPane.rowSpan="1"
            GridPane.halignment="CENTER"
            onAction="#register">
        <GridPane.margin>
            <Insets top="20" right="0" bottom="20" left="0"></Insets>
        </GridPane.margin>
    </Button>
</GridPane>
The above FXML document is self-explanatory.
In the above FXML document, We create a GridPane layout which is center aligned and has a horizontal and vertical gap of 10.
We also specify the padding of 40px on each side. The layout also defines the controller that will be used to handle any mouse or keyboard events using fx:controller property.
GridPane.columnIndex and GridPane.rowIndex properties allow us to place ui controls in a particular cell.
The Submit button has an onAction property which calls a method named submitButton. This method has to be defined in the FXML controller and that’s we will create in the next step.

Create a register controller to handle form data

Let's create a RegisterController.java class and add the following content to it:
package com.javaguides.javafx.registration;

import java.sql.SQLException;

import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.Node;
import javafx.scene.control.Alert;
import javafx.scene.control.Button;
import javafx.scene.control.PasswordField;
import javafx.scene.control.TextField;
import javafx.stage.Window;

public class RegisterController {

    @FXML
    private TextField fullNameField;

    @FXML
    private TextField emailIdField;

    @FXML
    private PasswordField passwordField;

    @FXML
    private Button submitButton;

    @FXML
    public void register(ActionEvent event) throws SQLException {

        Window owner = submitButton.getScene().getWindow();

        System.out.println(fullNameField.getText());
        System.out.println(emailIdField.getText());
        System.out.println(passwordField.getText());
        if (fullNameField.getText().isEmpty()) {
            showAlert(Alert.AlertType.ERROR, owner, "Form Error!",
                "Please enter your name");
            return;
        }

        if (emailIdField.getText().isEmpty()) {
            showAlert(Alert.AlertType.ERROR, owner, "Form Error!",
                "Please enter your email id");
            return;
        }
        if (passwordField.getText().isEmpty()) {
            showAlert(Alert.AlertType.ERROR, owner, "Form Error!",
                "Please enter a password");
            return;
        }

        String fullName = fullNameField.getText();
        String emailId = emailIdField.getText();
        String password = passwordField.getText();

        JdbcDao jdbcDao = new JdbcDao();
        jdbcDao.insertRecord(fullName, emailId, password);

        showAlert(Alert.AlertType.CONFIRMATION, owner, "Registration Successful!",
            "Welcome " + fullNameField.getText());
    }

    private static void showAlert(Alert.AlertType alertType, Window owner, String title, String message) {
        Alert alert = new Alert(alertType);
        alert.setTitle(title);
        alert.setHeaderText(null);
        alert.setContentText(message);
        alert.initOwner(owner);
        alert.show();
    }
}
Note that the FXMLLoader will automatically inject values defined in the FXML document into corresponding references in the controller class.
So, the fullNameFieldemailIdFieldpasswordField and submitButton references specified in the above controller will automatically be injected by the objects created from the FXML document.
The @FXML annotation is mandatory for private member fields of the controller class, otherwise, field injection won’t work. However, it can be omitted for public fields.
We validate form fields and store to a database using JdbcDao class.

Create JDBCDao for Database operations

Here are steps to connect to the MySQL database:
  1. Establishing a connection
  2. Create a statement
  3. Execute the query
  4. Using try-with-resources Statements to Automatically Close JDBC Resources
From JDBC 4.0, we don't need to include 'Class.forName()' in our code, to load JDBC driver. When the method 'getConnection' is called, the 'DriverManager' will automatically load the suitable driver among the JDBC drivers that were loaded at initialization and those loaded explicitly using the same class loader as the current application.
Connection conn = DriverManager.getConnection(Urldatabase,Username,Password);
Any JDBC 4.0 drivers that are found in your classpath are automatically loaded. (However, you must manually load any drivers prior to JDBC 4.0 with the method Class.forName.)
Here is complete code to store user registration form-data:
 package com.javaguides.javafx.registration;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;

public class JdbcDao {

    // Replace below database url, username and password with your actual database credentials
    private static final String DATABASE_URL = "jdbc:mysql://localhost:3306/javafx_registration?useSSL=false";
    private static final String DATABASE_USERNAME = "root";
    private static final String DATABASE_PASSWORD = "root";
    private static final String INSERT_QUERY = "INSERT INTO registration (full_name, email_id, password) VALUES (?, ?, ?)";


    public void insertRecord(String fullName, String emailId, String password) throws SQLException {

        // Step 1: Establishing a Connection and 
        // try-with-resource statement will auto close the connection.
        try (Connection connection = DriverManager
            .getConnection(DATABASE_URL, DATABASE_USERNAME, DATABASE_PASSWORD);

            // Step 2:Create a statement using connection object
            PreparedStatement preparedStatement = connection.prepareStatement(INSERT_QUERY)) {
            preparedStatement.setString(1, fullName);
            preparedStatement.setString(2, emailId);
            preparedStatement.setString(3, password);

            System.out.println(preparedStatement);
            // Step 3: Execute the query or update query
            preparedStatement.executeUpdate();
        } catch (SQLException e) {
            // print SQL exception information
            printSQLException(e);
        }
    }

    public static void printSQLException(SQLException ex) {
        for (Throwable e: ex) {
            if (e instanceof SQLException) {
                e.printStackTrace(System.err);
                System.err.println("SQLState: " + ((SQLException) e).getSQLState());
                System.err.println("Error Code: " + ((SQLException) e).getErrorCode());
                System.err.println("Message: " + e.getMessage());
                Throwable t = ex.getCause();
                while (t != null) {
                    System.out.println("Cause: " + t);
                    t = t.getCause();
                }
            }
        }
    }
}

Run application

In order to run this JavaFX application, open MainApp.java file which contains main() method so right click-> Run As -> Java Application.

Output

The following are some screenshots of the application we just built.

Registration form validation:

Registration form enter valid data: 

Registration form submit success: 

Reference

Comments