Сегодня я расскажу как заставить общаться наше JavaFX приложение с базой данных. Все это дело происходит через Mysql Connector и немного магии. Но на самом деле, все очень просто.

Для начала мы создадим проект в нашей IntelliJ типа JavaFX. Все таки на визуальном приложении будет более наглядно! Далее идем в Scene Builder, о котором я рассказывал в прошлом посте и создаем форму авторизации.

Форма авторизации реализованная в Scene Builder oт Gluon

Великолепно, теперь сохраним ее, перенесем в проект и накинем стили, ну как же без красоты, а?

Не забываем выставить контроллер у главного контейнера через выражение fx:controller=»sample.Controller»:

<AnchorPane fx:controller="sample.Controller" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1">
   <children>
      <Label layoutX="227.0" layoutY="70.0" text="Авторизация">
         <font>
            <Font name="Raleway" size="24.0" />
         </font>
      </Label>
      <Label layoutX="82.0" layoutY="156.0" text="Логин:" />
      <Label layoutX="78.0" layoutY="192.0" text="Пароль:" />
      <TextField layoutX="154.0" layoutY="151.0" prefHeight="27.0" prefWidth="352.0" />
      <PasswordField layoutX="154.0" layoutY="187.0" prefHeight="27.0" prefWidth="352.0" />
      <Button layoutX="447.0" layoutY="256.0" mnemonicParsing="false" styleClass="success" text="Вход" />
   </children>
</AnchorPane>

Теперь добавим в проект наш CSS и пропишем его нашей форме. И не забываем, что стили должны лежать в папке SRC!

Scene scene = new Scene(root, 600, 400);
        scene.getStylesheets().add("bootstrap3.css");
        primaryStage.setScene(scene);

Отлично, наша красивая форма готова, теперь мы наконец приступим к реализации связи с базой данных. Первым делом, что нужно сделать это, конечно же, создать базу данных и таблицу. Так как, мы будем реализовывать авторизацию, нужно создать таблицу users с полями id (куда без ключа?), username и password.

Я использую для работы с базой данных программу Navicat for MySQL. Очень удобно визуально создавать таблицы и заполнять их ручными данными.

Созданная таблица в Navicat

После того, как база данных готова следует перейти к программированию. Как я говорил выше, для работы с базой данных нам потребуется библиотека MySQL Connector, поэтому скачиваем ее и подключаем к проекту.

Добавление библиотеки в проект

Я написал небольшой, но удобный класс, который является универсальным для работы с базой данных. Я его использую во всех своих проектах. Поэтому, если хотите хоть чуть-чуть упросить себе жизнь скачиваем и используем на здоровье. В противном случае, можете просто его скачать и изучить как он работает.

Перед использованием моего класса, я немного расскажу о нем. Первое, что в нем вы увидите это основные поля, т.е. наши атрибуты подключения и конструктор, который их заполняет при обращению к классу впервые.

private String host;
    private String username;
    private String password;

    public MysqlConnection(String _host, String _username, String _password)
    {
        //Конструктор
        host = _host;
        username = _username;
        password = _password;
    }

После этого идут несколько методов на получение этих данных. Используются в методы по причине того, что наши поля являются скрытыми (основы инкапсуляции).

 //Последующие три метода отвечают за получение данных для подключения к базе данных
    public String getHost() {
        return host;
    }

    public String getUsername() {
        return username;
    }

    public String getPassword() {
        return password;
    }

Далее идут два метода, конкретно которые мы будем использовать в нашей программе. Один отвечает за получение данных, которой за отправку. К примеру, на запрос SELECT мы будем использовать метод getData(), а для INSERT и UPDATE – setData().

public ResultSet getData(String sqlStr) throws SQLException {
        //Получение данных из базы
        Connection connection = DriverManager.getConnection(host,username,password);
        Statement stmt = connection.createStatement();
        ResultSet resultSet = stmt.executeQuery(sqlStr);
        return  resultSet;
    }

    public void setData(String sqlStr) throws SQLException {
        //Обновение данных в базе
        Connection connection = DriverManager.getConnection(host, username, password);
        Statement stmt =  connection.createStatement();
        stmt.executeUpdate(sqlStr);
    }

Более правильной реализацией работы с базой данных будет являться отправка данных на какой-либо сайт с последующей обработкой PHP и возвращением данных в формате JSON. Это является и более безопасным методом и более правильным. Но в этом посте мы рассматриваем наипростейший способ связи с базой данных, а позже я расскажу про более правильный.

Для того, чтобы каждый раз не отправлять в класс данные для подключения мы можем сделать отдельный класс, который будет их хранить. А в мой класс от него унаследовать. Это и реализуем.

Создаем класс Configuration, что будет непосредственно хранить наши данные. Прописываем protected поля host, username, password и перемещаем в него методы получения этих данных, чтобы они были на своем месте.

package sample;

public class Configuration {

    protected String host = "";

    protected String username = "";

    protected String password = "";

    //Последующие три метода отвечают за получение данных для подключения к базе данных
    public String getHost() {
        return host;
    }

    public String getUsername() {
        return username;
    }

    public String getPassword() {
        return password;
    }
}

Не забываем, дописать свои данные для подключения к базе данных!

И немного корректируем класс MysqlConnection:

package sample;

import java.sql.*;

public class MysqlConnection extends Configuration {

    public ResultSet getData(String sqlStr) throws SQLException {
        //Получение данных из базы
        Connection connection = DriverManager.getConnection(host,username,password);
        Statement stmt = connection.createStatement();
        ResultSet resultSet = stmt.executeQuery(sqlStr);
        return  resultSet;
    }

    public void setData(String sqlStr) throws SQLException {
        //Обновение данных в базе
        Connection connection = DriverManager.getConnection(host, username, password);
        Statement stmt =  connection.createStatement();
        stmt.executeUpdate(sqlStr);
    }
}

Мы унаследовали его от класса Configuration и убрали все лишнее. А так как поля мы сделали protected они доступны классу Configuration и всем кто от него наследуется.

Великолепно, первая часть готова! Приступаем к логике. Создаем событие для нашей кнопки(onAction) и ссылки на наши поля для ввода:

 @FXML
    TextField loginTxt;
    @FXML
    PasswordField passwordField;

    public void SingIn(ActionEvent actionEvent) {

    }

Первым делом нам нужно записывать в переменные данные с полей. После чего создать экземпляр класса MySQLConnection:

 String username = LoginField.getText();
        String password = PasswordField.getText();
        MysqlConnection mc = new MysqlConnection();

Теперь требуется сформировать запрос к нашей базе данных. Правильнее будет не запрашивать всю таблицу и проверять локально, а отправить запрос с условием, и если он вернется пустой, значит такой записи нет.

По причине того, что мы запрашиваем данные из базы данных мы будем использовать метод getData(). Посмотрев класс, вы наверное заметили, что этот метод возвращает тип данных ResultSet. Поэтому наш запрос будет выглядеть так:

ResultSet rs = mc.getData("SELECT username, password FROM users WHERE username = '" + username + "' AND password = '" + password + "'");   

Остался последний шаг, проверить то, что пришло нам с базы данных. Для этого, мы запросим возможно ли получить первый элемент, если нет, то результат пустой, если да, то запись нашлась и наша авторизация удачна!

if (rs.next() == true) {
            Alert alert = new Alert(Alert.AlertType.INFORMATION);
            alert.setTitle("Успех");
            alert.setHeaderText(null);
            alert.setContentText("Авторизация прошла успешно!");
            alert.showAndWait();
        }
        else {
            Alert alert = new Alert(Alert.AlertType.INFORMATION);
            alert.setTitle("Неверные данные!");
            alert.setHeaderText(null);
            alert.setContentText("Увы, но вы ввели неверные данные!");
            alert.showAndWait();
        }

Полный код нашего контроллера будет такой:

package sample;

import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.control.Alert;
import javafx.scene.control.PasswordField;

import javafx.scene.control.TextField;
import java.sql.ResultSet;
import java.sql.SQLException;

public class Controller {

    @FXML
    TextField LoginField;
    @FXML
    PasswordField PasswordField;

    public void SingIn(ActionEvent actionEvent) throws SQLException {
        String username = LoginField.getText();
        String password = PasswordField.getText();
        MysqlConnection mc = new MysqlConnection();
        ResultSet rs = mc.getData("SELECT username, password FROM users WHERE username = '" + username + "' AND password = '" + password + "'");
        if (rs.next() == true) {
            Alert alert = new Alert(Alert.AlertType.INFORMATION);
            alert.setTitle("Успех");
            alert.setHeaderText(null);
            alert.setContentText("Авторизация прошла успешно!");
            alert.showAndWait();
        }
        else {
            Alert alert = new Alert(Alert.AlertType.INFORMATION);
            alert.setTitle("Неверные данные!");
            alert.setHeaderText(null);
            alert.setContentText("Увы, но вы ввели неверные данные!");
            alert.showAndWait();
        }

    }
}

И так мы познакомились с простейшим вариантом работы с базой данных. На днях расскажу, как получить некоторое кол-во информации и обработать его. К примеру, мы может иметь таблицу новостей, которую мы запросим в нашу программу и выведем. Да-да, как лента Вконтакте.