lundi 2 mars 2020

JavaFX + Spring Boot + Database

Préambule


Dans un précédent article j'ai détaillé comment intégrer Spring Boot dans une application JavaFX en utilisant Maven (Vous pouvez le consulter ici).
Cet article sera assez court car nous allons simplement reprendre l'application du précédant article et voir comme y intégrer une base de données SQL.


Technos

 

Nous reprenons les technologies précédemment utilisées en y ajoutant ce qui est nécessaire à l'intégration de la base de données.
  • JavaFX 8 (version de la JRE 8 en l’occurrence)
  • Maven 3.x (on pourrait aussi bien utiliser Gradle)
  • Spring Boot 2.0.5
  • H2Database 1.4.197 (version compatible avec la version de Spring Boot)

Tutoriel

 

Pour commencer reprenons les sources du précédent projet à partir du repos Github, vous pouvez les télécharger à cette adresse : jfxspringboot

Dépendances 

 

Nous avons besoin d'ajouter quelques dépendances dans le pom.xml de notre application pour nous connecter à la base de données et pour faire des requêtes.


...
<dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
</dependency>

<dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
...

On ajoute la dépendance pour la base de données H2 qui est une base de données assez légère pouvant être utilisée soit en mémoire, soit en fichiers.
Ensuite on ajoute le starter spring-boot-starter-data-jpa qui va nous ajouter les librairies, dont un ORM par défaut Hibernate, afin de créer, mapper les entités et requêter la base de données.

Configuration Spring Boot

 

Nous allons à présent définir les différents paramètres qui vont nous permettre de gérer notre base de données pour l'application.
Grace à Spring Boot et à son système de configuration automatique le paramétrage est très simple à effectuer, il nous suffit d'ajouter les lignes suivantes dans le fichier application.properties de notre application.
spring.datasource.url=jdbc:h2:file:./database/h2/appdb
spring.datasource.username=mydb
spring.datasource.password=
spring.jpa.generate-ddl=true
spring.jpa.hibernate.ddl-auto=update
spring.jpa.show-sql=false

Les propriétés spring.datasource vont permettre à Spring de configurer la base de données H2 en fournissant les paramètres de connexion.
Les propriétés spring.jpa vont quant à elles définir les paramètres de l'ORM (ici Hibernate).

La première ligne nous indique que nous utilisons une base de données JDBC de type H2 au format fichiers qui seront stockés dans le répertoire "database/h2/appdb" de notre application.
spring.datasource.url=jdbc:h2:file:./database/h2/appdb

Les deux lignes suivantes définissent le login/mot de passe de la base de données, ici pour l'exemple on ne met pas de mot de passe ce qui n'est pas vraiment recommandé :)
spring.datasource.username=mydb
spring.datasource.password=

La ligne suivante indique que nous générons le schéma de la base de données à partir du mapping des entités.
spring.jpa.generate-ddl=true

Ensuite nous configurons le mode "update" du genarate-ddl car par défaut il est configuré en "create/drop", ce qui détruit la base de données à l'arrêt de l'application.
spring.jpa.hibernate.ddl-auto=update

Et enfin nous indiquons que nous ne voulons pas tracer les requêtes SQL effectuées par l'ORM.
spring.jpa.show-sql=false

Entités, repositories, services

 

Afin d'utiliser notre base de données il nous faut définir ce qu'elle va contenir. Pour cela nous allons commencer par créer une entité qui correspondra à la table utilisateur de notre application.

package fr.jbe.jfxspringboot.db.domain;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.SequenceGenerator;

@Entity
public class User {

 @Id
 @SequenceGenerator(name = "userSequence", sequenceName = "SEQ_USER", allocationSize = 1)
 @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "userSequence")
 private Long id;
 
 private String firstname;
 
 private String lastname;
 
 public User() {
 }

 public User(String firstname, String lastname) {
  this.firstname = firstname;
  this.lastname = lastname;
 }

 // Getter and Setter
 
}

Puis nous créons le repository qui va nous permettre de communiquer avec la base de données afin de créer et récupérer les données de la table User.

package fr.jbe.jfxspringboot.db.repository;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import fr.jbe.jfxspringboot.db.domain.User;

@Repository
public interface IUserRepository extends JpaRepository<User, Long> {

 public User findByFirstname(String firstname);

}

Enfin nous ajoutons un service qui sera notre point d'entrée pour manipuler les données utilisateurs de la table User.

package fr.jbe.jfxspringboot.db.service;

import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import fr.jbe.jfxspringboot.db.domain.User;
import fr.jbe.jfxspringboot.db.repository.IUserRepository;

@Service
@Transactional
public class UserService {

 @Autowired
 private IUserRepository userRepository;
 
 public User findByFirstname(String firstname) {
  return userRepository.findByFirstname(firstname);
 }
 
 public List<User> findAll() {
  return userRepository.findAll();
 }
 
 public User save(User user) {
  return userRepository.save(user);
 }
}

Intégration à la vue JavaFX

 

Pour finir nous allons faire appel à notre service utilisateur dans le controller de la vue FXML de notre application afin de lister les utilisateurs présents dans la base de données.

Nous ajoutons dans le fichier FXML un bouton et un textarea qui vont servir à afficher notre liste d'utilisateurs.

<Label text="Liste des utilisateurs" GridPane.halignment="RIGHT" GridPane.rowIndex="3">
   <font>
      <Font name="System Bold" size="12.0" />
   </font>
</Label>
<Button mnemonicParsing="false" onAction="#handleDisplay" text="Afficher" GridPane.columnIndex="1" GridPane.rowIndex="3" />
<TextArea fx:id="userList" prefHeight="200.0" prefWidth="200.0" GridPane.columnSpan="2" GridPane.rowIndex="4">
   <GridPane.margin>
       <Insets top="5.0" />
   </GridPane.margin>
</TextArea>

Puis dans la méthode initialize() du contrôler de la vue nous créons des nouveaux utilisateurs dans la table User s'ils n'existe pas déjà. Lors de l'appuis sur le bouton "Afficher" la méthode handleDisplay() va requêter la liste des utilisateur dans la base de données et les afficher dans le textarea.

 
 @FXML
 private void initialize() {
  name.clear();
  displayName.setText("");
  
  User user = userService.findByFirstname("Julien");
  if (user == null) {
   user = new User("Julien", "B");
   userService.save(user);
  }
  User user2 = userService.findByFirstname("David");
  if (user2 == null) {
   user2 = new User("David", "M");
   userService.save(user2);
  }
 }
 
 @FXML
 public void handleDisplay() {
  List users = userService.findAll();
  for (User user : users) {
   userList.appendText(user.getFirstname().concat(" ").concat(user.getLastname().concat("\n")));
  }
 }


Résultat

 

Voici ce que cela donne dans l'application :


Conclusion 

 

Nous avons pu voir qu'il était assez simple de configurer une base de données intégrée à notre application en se base sur l'auto-configuration qu'apport Spring Boot. Il ne reste plus ensuite qu'à injecter le service utilisateur dans le contrôler de notre choix pour pouvoir communiquer avec la base de données.

J'espère que cet article vous aura intéressé et n’hésitez pas à laisser un commentaire si vous avez des questions ou des remarques constructives.
Merci d'avoir pris le temps de lire cet article et à bientôt.

Retrouvez les sources sur github.com