JavaRush /Blog Java /Random-FR /Votre première application Hibernate

Votre première application Hibernate

Publié dans le groupe Random-FR
Dans cet article, vous vous familiariserez avec l'un des frameworks d'entreprise les plus populaires pour Java et créerez votre première application à l'aide d'Hibernate. Vous n’avez jamais entendu parler d’Hibernate ? Peut-être en avez-vous entendu parler, mais ne l'avez-vous pas utilisé ? Ou vous avez essayé de démarrer, mais vous n’avez pas réussi ? Dans les trois cas, bienvenue dans le cut :) Votre première application Hibernate - 1Bonjour à tous ! Dans cet article, je vais parler des principales fonctionnalités du framework Hibernate et vous aider à écrire votre première mini-application. Pour cela nous avons besoin de :
  1. Intellij Idea Édition Ultime ;
    Téléchargez depuis le site officiel et activez la version d'essai de 30 jours.
  2. PostgeSQL est l'un des systèmes de gestion de bases de données (SGBD) modernes les plus populaires ;
  3. Maven (déjà intégré à IDEA) ;
  4. Un peu de patience.
L'article s'adresse principalement à ceux qui n'ont jamais travaillé avec cette technologie, la quantité de code a donc été réduite au maximum. Commençons!

Qu’est-ce que la mise en veille prolongée ?

Il s'agit de l'une des implémentations les plus populaires du modèle ORM. Le modèle objet-relationnel décrit les relations entre les objets logiciels et les enregistrements de la base de données. Bien entendu, les fonctionnalités d'Hibernate sont très larges, mais nous nous concentrerons sur les fonctions les plus simples. Notre objectif : créer une application CRUD (Créer, Lire, Mettre à jour, Supprimer) qui sera capable de :
  1. Créez des utilisateurs (Utilisateur), recherchez-les dans la base de données par ID, mettez à jour leurs données dans la base de données et supprimez-les également de la base de données.
  2. Attribuez des objets de véhicule (Auto) aux utilisateurs. Créez, modifiez, recherchez et supprimez des voitures de la base de données.
  3. De plus, l'application devrait supprimer automatiquement les voitures « orphelines » de la base de données. Ceux. Lorsqu'un utilisateur est supprimé, toutes les voitures lui appartenant doivent également être supprimées de la base de données.
La structure de notre projet sera la suivante : Votre première application Hibernate - 2Comme vous pouvez le constater, rien de compliqué. 6 classes + 1 fichier avec configs. Tout d’abord, créons un nouveau projet maven dans Intellij Idea. Fichier -> Nouveau projet. Parmi les types de projets proposés, sélectionnez Maven et continuez. Votre première application Hibernate - 3Apache Maven est un framework permettant d'automatiser l'assemblage de projets basé sur une description de leur structure dans des fichiers en langage POM. La structure entière de votre projet sera décrite dans le fichier pom.xml, qu'IDEA créera elle-même à la racine de votre projet. Dans les paramètres du projet, vous devrez spécifier les paramètres Maven - groupId etartefactId. Généralement, dans les projets, groupId est le nom de l'organisation ou de la division, et le nom de domaine de l'organisation ou du site du projet y est écrit. À son tour, artificialId est le nom du projet. Pour groupdId, vous pouvez spécifier com.вашНикнейм.javarush, cela n'affectera en rien le fonctionnement de l'application. Pour artificialId, sélectionnez le nom du projet de votre choix. Vous pouvez également laisser la version inchangée. Votre première application Hibernate - 4Sur le dernier écran, confirmez simplement vos données précédemment saisies. Votre première application Hibernate - 5Nous avons donc créé le projet, il ne reste plus qu'à écrire le code et le faire fonctionner :) Tout d'abord, si l'on veut créer une application qui fonctionne avec une base de données, on ne peut définitivement pas se passer d'une base de données ! Téléchargez PostgreSQL à partir d'ici (j'utilise la version 9). PostgreSQL a un utilisateur par défaut « postgres », vous devrez créer un mot de passe pour celui-ci lors de l'installation. N'oubliez pas votre mot de passe, nous en aurons besoin plus tard ! (En général, utiliser la base de données par défaut dans les applications est une mauvaise pratique, mais afin de réduire le nombre d'hémorroïdes, nous nous contenterons de créer notre propre base de données). Si vous n'êtes pas à l'aise avec la ligne de commande et les requêtes SQL, voici une bonne nouvelle. Intellij IDEA fournit une interface utilisateur tout à fait adaptée pour travailler avec la base de données. Cela ressemble à ceci : Votre première application Hibernate - 6(situé dans la barre latérale droite d'IDEA, onglet Base de données) Pour créer une connexion, cliquez sur « + », sélectionnez notre fournisseur (PostgeSQL). Remplissez les champs avec l'utilisateur, le nom de la base de données (les deux sont postgres) et entrez le mot de passe que vous avez défini lors de l'installation de PostgreSQL. Si nécessaire, téléchargez le pilote Postgres, cela peut être fait sur cette même page. Cliquez sur "Test de connexion" pour vérifier que la connexion à la base de données est établie. Si vous voyez l'inscription « Réussi », passons à autre chose. Créons maintenant les tables dont nous avons besoin. Il y en aura deux : les utilisateurs et les automobiles. Paramètres de la table des utilisateurs : Votre première application sur Hibernate - 7Veuillez noter que id est la clé primaire. Si vous ne savez pas ce qu’est une clé primaire en SQL, recherchez-la sur Google, c’est important. Paramètre pour la table autos : Votre première application sur Hibernate - 8Pour les automobiles, vous devez configurer Foreign Key - clé étrangère. Cela reliera nos tables. Je vous conseille d'en savoir plus sur lui ; Pour faire simple, il fait référence à une table externe, dans notre cas, les utilisateurs. Si la voiture appartient à un utilisateur avec id=1, alors dans le champ user_id de la table autos, elle aura 1. C'est ainsi que nous connectons les utilisateurs à leurs voitures dans notre application. Dans notre table autos, le champ user_id servira de clé étrangère. Il fera référence au champ id de la table des utilisateurs. Votre première application Hibernate - 9Ainsi, nous avons créé une base de données avec deux tables. Reste à comprendre comment le gérer depuis le code Java. Nous commencerons par le fichier pom.xml, dans lequel nous devons inclure les bibliothèques nécessaires (en langage Maven, elles sont appelées dépendances). Toutes les bibliothèques sont stockées dans le référentiel central Maven. Ceux d'entre eux que vous spécifiez dans pom.xml, vous pouvez les utiliser dans le projet. Votre pom.xml devrait ressembler à ceci : Votre première application Hibernate - 10Rien de compliqué comme vous pouvez le voir. Nous n'avons ajouté que 2 dépendances - pour utiliser PostgreSQL et Hibernate. Passons maintenant au code Java. Créez tous les packages et classes nécessaires pour le projet. Pour commencer, nous aurons besoin de modèles de données - classes Useret Auto.
package models;

import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;

@Entity
@Table (name = "users")
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;
    @Column(name = "name")
    private String name;
    //you can not specify Column name if it matches the name of the column in the table
    private int age;

    @OneToMany(mappedBy = "user", cascade = CascadeType.ALL, orphanRemoval = true)
    private List<Auto> autos;

    public User() {
    }

    public User(String name, int age) {
        this.name = name;
        this.age = age;
        autos = new ArrayList<>();
    }

    public void addAuto(Auto auto) {
        auto.setUser(this);
        autos.add(auto);
    }

    public void removeAuto(Auto auto) {
        autos.remove(auto);
    }

    public int getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public List<Auto> getAutos() {
        return autos;
    }

    public void setAutos(List<Auto> autos) {
        this.autos = autos;
    }

    @Override
    public String toString() {
        return "models.User{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                '}';
    }
}
package models;

import javax.persistence.*;

@Entity
@Table(name = "autos")
public class Auto {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;

    @Column (name = "model")
    private String model;

    //you can not specify Column name if it matches the name of the column in the table
    private String color;


    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "user_id")
    private User user;

    public Auto() {
    }

    public Auto(String model, String color) {
        this.model = model;
        this.color = color;
    }

    public int getId() {
        return id;
    }

    public String getModel() {
        return model;
    }

    public void setModel(String model) {
        this.model = model;
    }

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    public User getUser() {
        return user;
    }

    public void setUser(User user) {
        this.user = user;
    }

    @Override
    public String toString() {
        return color + " " + model;
    }
}
Comme vous pouvez le constater, les classes sont dotées d'un tas d'annotations encore floues. Commençons par nous occuper d'eux. L'annotation principale pour nous est @Entity. Lisez à ce sujet sur Wikipédia et rappelez-vous tout, c'est la base des bases. Cette annotation permet aux objets Java de votre classe d'être associés à la base de données. Pour qu’une classe soit une entité, elle doit répondre aux exigences suivantes :
  • Doit avoir un constructeur vide ( publicou protected);
  • Ne peut pas être imbriqué, interface ouenum ;
  • Ne peut pas être finalet ne peut pas contenir finalde -champs/propriétés ;
  • Doit contenir au moins un champ @Id.
Vérifiez vos classes d’entités, c’est un endroit très populaire pour se tirer une balle dans le pied. C'est très facile d'oublier quelque chose. Dans ce cas, l'entité peut :
  • Contenir des constructeurs non vides ;
  • Être hérité et être hérité ;
  • Contenir d’autres méthodes et implémenter des interfaces.
Comme vous pouvez le constater, la classe Userest très similaire à la table des utilisateurs. Il y a des champs id, name, age. Les annotations situées au-dessus d'elles n'ont pas besoin de beaucoup d'explications : il est déjà clair que @Id est une indication que le champ est un identifiant d'objets de cette classe. L'annotation @Table au-dessus de la classe spécifie le nom de la table dans laquelle les objets sont écrits. Faites attention au commentaire au dessus du champ age : si le nom du champ dans la classe et dans la table est le même, vous n'avez pas besoin d'ajouter l'annotation @Column, cela fonctionnera comme ça. Concernant la « stratégie = GenerationType.IDENTITY » indiquée entre parenthèses : il existe plusieurs stratégies de génération d’ID. Vous pouvez le rechercher sur Google, mais dans le cadre de notre application, vous n'avez pas à vous en soucier. L'essentiel est que les identifiants de nos objets seront générés automatiquement, il n'y a donc pas de paramètre pour l'identifiant, et nous ne le spécifions pas non plus dans le constructeur. UserCependant, la classe se démarque encore à certains égards . Il a une liste de voitures ! L'annotation @OneToMany apparaît au-dessus de la liste. Cela signifie qu'un objet de la classe utilisateur peut correspondre à plusieurs machines. Le paramètre "mappedBY" pointe vers le champ utilisateur de la classe Auto. De cette manière, les machines et les utilisateurs sont connectés les uns aux autres. Le paramètre orphanRemoval se traduit assez bien de l'anglais - « supprimer les orphelins ». Si nous supprimons un utilisateur de la base de données, toutes les voitures qui lui sont associées seront également supprimées. À votre tour, dans la classe, Autovous verrez le champ utilisateur avec l'annotation @ManyToOne (plusieurs Autos peuvent correspondre à un utilisateur) et l'annotation @JoinColumn. Il indique par quelle colonne de la table autos la connexion avec la table users se produit (la même clé étrangère dont nous avons parlé plus tôt). Après avoir créé un modèle de données, il est temps d'apprendre à notre programme à effectuer des opérations sur ces données dans la base de données. Commençons par la classe utilitaire HibernateSessionFactoryUtil. Il n'a qu'une seule tâche : créer une fabrique de sessions pour que notre application fonctionne avec la base de données (bonjour, le modèle "Factory !"). Il ne peut rien faire d'autre.
package utils;

import models.Auto;
import models.User;
import org.hibernate.SessionFactory;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Configuration;

public class HibernateSessionFactoryUtil {
    private static SessionFactory sessionFactory;

    private HibernateSessionFactoryUtil() {}

    public static SessionFactory getSessionFactory() {
        if (sessionFactory == null) {
            try {
                Configuration configuration = new Configuration().configure();
                configuration.addAnnotatedClass(User.class);
                configuration.addAnnotatedClass(Auto.class);
                StandardServiceRegistryBuilder builder = new StandardServiceRegistryBuilder().applySettings(configuration.getProperties());
                sessionFactory = configuration.buildSessionFactory(builder.build());

            } catch (Exception e) {
                System.out.println("Exception!" + e);
            }
        }
        return sessionFactory;
    }
}
Dans cette classe, nous créons un nouvel objet de configuration, Configuration, et lui transmettons les classes qu'il doit percevoir comme des entités - Useret Auto. Faites attention à la méthode configuration.getProperties(). Quelles autres propriétés ? Où? Les propriétés sont des paramètres sur le fonctionnement de la mise en veille prolongée, spécifiés dans un fichier spécial hibernate.cfg.xml. Votre première application Hibernate - 11Hibernate.cfg.xml est lu ici : new Configuration().configure(); Comme vous pouvez le voir, il n'a rien de spécial - des paramètres de connexion à la base de données et un paramètre spécial show_sql. Il est nécessaire pour que toutes les requêtes SQL qui hibernent s'exécuteront sur notre base de données soient affichées sur la console. De cette façon, vous verrez exactement ce que fait Hibernate à chaque instant et vous débarrasserez de l’effet « magique ». Ensuite, nous avons besoin de la classe UserDAO. (Dans le bon sens, vous devez programmer via des interfaces - créer une interface UserDAOet l'implémenter séparément UserDAOImpl, mais pour réduire la quantité de code, j'omettrai cela. Ne faites pas cela dans de vrais projets !). DAO (data access object) est l’un des modèles de conception les plus courants, « Data Access ». Sa signification est simple : créer une couche dans l'application qui est responsable uniquement de l'accès aux données, et rien d'autre. Obtenez des données de la base de données, mettez à jour les données, supprimez les données - et c'est tout. En savoir plus sur les DAO ; vous les utiliserez constamment dans votre travail. Que peut faire notre classe UserDao? En fait, comme tous les DAO, il ne peut fonctionner qu’avec des données. Rechercher un utilisateur par identifiant, mettre à jour ses données, le supprimer, extraire une liste de tous les utilisateurs de la base de données ou enregistrer un nouvel utilisateur dans la base de données - c'est toute sa fonctionnalité.
package dao;

import models.Auto;
import models.User;
import org.hibernate.Session;
import org.hibernate.Transaction;
import utils.HibernateSessionFactoryUtil;
import java.util.List;

public class UserDao {

    public User findById(int id) {
        return HibernateSessionFactoryUtil.getSessionFactory().openSession().get(User.class, id);
    }

    public void save(User user) {
        Session session = HibernateSessionFactoryUtil.getSessionFactory().openSession();
        Transaction tx1 = session.beginTransaction();
        session.save(user);
        tx1.commit();
        session.close();
    }

    public void update(User user) {
        Session session = HibernateSessionFactoryUtil.getSessionFactory().openSession();
        Transaction tx1 = session.beginTransaction();
        session.update(user);
        tx1.commit();
        session.close();
    }

    public void delete(User user) {
        Session session = HibernateSessionFactoryUtil.getSessionFactory().openSession();
        Transaction tx1 = session.beginTransaction();
        session.delete(user);
        tx1.commit();
        session.close();
    }

    public Auto findAutoById(int id) {
        return HibernateSessionFactoryUtil.getSessionFactory().openSession().get(Auto.class, id);
    }

    public List<User> findAll() {
        List<User> users = (List<User>)  HibernateSessionFactoryUtil.getSessionFactory().openSession().createQuery("From User").list();
        return users;
    }
}
Les méthodes UserDaosont similaires les unes aux autres. Dans la plupart d'entre eux, nous recevons un objet Session (une session se connectant à notre base de données) à l'aide de notre Session Factory, créons une seule transaction au sein de cette session, effectuons les transformations de données nécessaires, enregistrons le résultat de la transaction dans la base de données et fermons la session. Comme vous pouvez le constater, les méthodes elles-mêmes sont assez simples. Le DAO est le « cœur » de notre application. Cependant, nous ne créerons pas directement le DAO et n'appellerons pas ses méthodes dans notre main(). Toute la logique sera déplacée vers le UserService.
package services;

import dao.UserDao;
import models.Auto;
import models.User;

import java.util.List;

public class UserService {

    private UserDao usersDao = new UserDao();

    public UserService() {
    }

    public User findUser(int id) {
        return usersDao.findById(id);
    }

    public void saveUser(User user) {
        usersDao.save(user);
    }

    public void deleteUser(User user) {
        usersDao.delete(user);
    }

    public void updateUser(User user) {
        usersDao.update(user);
    }

    public List<User> findAllUsers() {
        return usersDao.findAll();
    }

    public Auto findAutoById(int id) {
        return usersDao.findAutoById(id);
    }


}
Le service est une couche de données dans l'application responsable de l'exécution de la logique métier. Si votre programme doit exécuter une logique métier, il le fait via des services. Le service contient en lui-même UserDaoet appelle des méthodes DAO dans ses méthodes. Cela peut vous sembler une duplication de fonctions (pourquoi ne pas simplement appeler des méthodes à partir d'un objet dao), mais avec un grand nombre d'objets et une logique complexe, diviser l'application en couches présente d'énormes avantages (c'est une bonne pratique, rappelez-vous ces informations pour l'avenir et découvrez les « couches d'application » "). Dans notre service, la logique est simple, mais dans les projets réels, les méthodes de service contiendront bien plus d'une ligne de code :) Nous avons maintenant tout ce dont nous avons besoin pour que l'application fonctionne ! Créons main()un utilisateur et des machines pour lui dans la méthode, connectons-les entre eux et enregistrons-les dans la base de données.
import models.Auto;
import models.User;
import services.UserService;

import java.sql.SQLException;

public class Main {
    public static void main(String[] args) throws SQLException {

        UserService userService = new UserService();
        User user = new User("Masha",26);
        userService.saveUser(user);
        Auto ferrari = new Auto("Ferrari", "red");
        ferrari.setUser(user);
        user.addAuto(ferrari);
        Auto ford = new Auto("Ford", "black");
        ford.setUser(user);
        user.addAuto(ford);
        userService.updateUser(user);
    }
}
Comme vous pouvez le voir, la table users a sa propre entrée et la table autos a la sienne. Votre première application Hibernate - 13Votre première application Hibernate - 14Essayons de renommer notre utilisateur. Effacons la table des utilisateurs et exécutons le code
import models.Auto;
import models.User;
import services.UserService;

import java.sql.SQLException;

public class Main {
    public static void main(String[] args) throws SQLException {

        UserService userService = new UserService();
        User user = new User("Masha",26);
        userService.saveUser(user);
        Auto ferrari = new Auto("Ferrari", "red");
        user.addAuto(ferrari);
        Auto ford = new Auto("Ford", "black");
        ford.setUser(user);
        user.addAuto(ford);
        userService.updateUser(user);
        user.setName("Sasha");
        userService.updateUser(user);
    }
}
Travaux! Votre première application Hibernate - 15Et si vous supprimez un utilisateur ? Effacons la table des utilisateurs (autos s'effacera tout seul) et exécutons le code
import models.Auto;
import models.User;
import services.UserService;

import java.sql.SQLException;

public class Main {
    public static void main(String[] args) throws SQLException {

        UserService userService = new UserService();
        User user = new User("Masha",26);
        userService.saveUser(user);
        Auto ferrari = new Auto("Ferrari", "red");
        user.addAuto(ferrari);
        Auto ford = new Auto("Ford", "black");
        ford.setUser(user);
        user.addAuto(ford);
        userService.updateUser(user);
        user.setName("Sasha");
        userService.updateUser(user);
        userService.deleteUser(user);
    }
}
Et nos tables sont complètement vides (faites attention à la console, toutes les requêtes exécutées par Hibernate y seront affichées). Vous pouvez jouer avec l'application et essayer toutes ses fonctionnalités. Par exemple, créez un utilisateur avec des machines, enregistrez-le dans la base de données, voyez quel ID lui est attribué et essayez d'utiliser la méthode main()pour "extraire" l'utilisateur de la base de données par cet identifiant et afficher une liste de ses machines dans la console. . Bien entendu, nous n’avons vu qu’une petite partie des fonctionnalités d’Hibernate. Ses capacités sont très étendues et il constitue depuis longtemps l’un des standards de l’industrie pour le développement Java. Si vous souhaitez l'étudier en détail, je peux vous recommander le livre « Java Persistence API and Hibernate », que j'ai examiné dans l'un de mes articles précédents. J'espère que cet article a été utile aux lecteurs. Si vous avez des questions, posez-les dans les commentaires, je me ferai un plaisir d'y répondre :) N'oubliez pas non plus de soutenir l'auteur dans le concours en le "Likant". Ou mieux encore - "Je l'aime beaucoup" :) Bonne chance dans vos études !
Commentaires
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION