CodeGym /Blog Java /Random-FR /Votre première application Hibernate
John Squirrels
Niveau 41
San Francisco

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 Hibernate. Vous n'avez jamais entendu parler d'Hibernate ? Ou peut-être en avez-vous entendu parler, mais ne l'avez-vous pas utilisé ? Ou peut-être avez-vous essayé de l'utiliser, mais sans succès ? Dans les trois cas - bienvenue en dessous de la coupe :) Votre première application Hibernate - 1 Bonjour à 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 Ultimate Edition
    Téléchargez-le sur le site officiel et activez la version d'essai de 30 jours.
  2. PostgreSQL - l'un des systèmes de gestion de base de données modernes les plus populaires (SGBD)
  3. Maven (déjà connecté à IDEA)
  4. Un peu de patience.
Au cas où, j'ai posté le code de l'application sur GitHub (branche codegym). L'article s'adresse principalement à ceux qui n'ont jamais travaillé avec cette technologie auparavant, j'ai donc minimisé la quantité de code. Commençons!

Qu'est-ce que l'hibernation ?

C'est l'une des implémentations de mappage objet-relationnel (ORM) les plus populaires. Un mappage objet-relationnel définit la relation entre les objets logiciels et les enregistrements de base de données. Bien sûr, Hibernate a des fonctionnalités très larges, mais nous nous concentrerons sur les fonctions les plus simples. Notre objectif est de créer une application CRUD (Create, Read, Update, Delete) qui pourra :
  1. Créez des utilisateurs (User), recherchez-les dans la base de données par ID, mettez à jour leurs données dans la base de données et supprimez-les de la base de données.
  2. Attribuez des objets de voiture (Auto) aux utilisateurs. Créez, mettez à jour, recherchez et supprimez des voitures de la base de données.
  3. De plus, l'application devrait automatiquement supprimer les voitures "sans propriétaire" de la base de données. En d'autres termes, lorsqu'un utilisateur est supprimé, toutes les voitures appartenant à cet utilisateur doivent également être supprimées de la base de données.
Notre projet sera structuré comme ceci : Votre première application Hibernate - 2Comme vous pouvez le voir, rien de compliqué. 6 classes + 1 fichier avec configs. Tout d'abord, créez un nouveau projet Maven dans IntelliJ IDEA. Fichier -> Nouveau projet. Sélectionnez Maven parmi les types de projets proposés et passez à l'étape suivante. Votre première application Hibernate - 3Apache Maven est un framework pour construire automatiquement des projets basés sur une description de leur structure dans des fichiers POM. Toute la structure de votre projet sera décrite dans pom.xml, un fichier qu'IDEA créera lui-même à la racine de votre projet. Dans les paramètres du projet, vous devez spécifier les paramètres Maven suivants : groupId et artefactId. Dans les projets, groupId est généralement une description de l'entreprise ou de l'unité commerciale. Le nom de domaine de l'entreprise ou du site Web peut aller ici. À son tour, artefactId est le nom du projet. Pour groupdId, vous pouvez saisir com.yourNickname.codegym. Cela n'aura aucun effet sur l'application. Pour artefactId, choisissez le nom de projet de votre choix. La version peut rester inchangée. Votre première application Hibernate - 4Sur le dernier écran, confirmez simplement les données saisies précédemment.Votre première application Hibernate - 5Donc, nous avons créé le projet. Maintenant, tout ce qu'il reste à faire est d'écrire du code et de le faire fonctionner :) Tout d'abord : si nous voulons créer une application qui fonctionne avec une base de données, nous ne pouvons définitivement pas nous 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 lui trouver un mot de passe lors de l'installation. N'oubliez pas le 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 nous le ferons afin de réduire le nombre de causes d'ulcères en créant votre propre base de données). Si vous n'êtes pas ami avec la ligne de commande et les requêtes SQL, il y a de bonnes nouvelles. IntelliJ IDEA fournit une interface utilisateur entièrement adaptée pour travailler avec la base de données. Votre première application Hibernate - 6(situé dans le volet droit d'IDEA, l'onglet Base de données). Pour créer une connexion, cliquez sur "+" et sélectionnez notre source de données (PostgeSQL). Remplissez les champs pour l'utilisateur et la base de données ("postgres" pour les deux) et entrez le mot de passe qui a été défini lors de l'installation de PostgreSQL. Si nécessaire, téléchargez le pilote Postgres. Vous pouvez le faire sur la même page. Cliquez sur "Tester la connexion" pour vérifier que la connexion à la base de données est établie. Si vous voyez "Succès", passez à autre chose. Nous allons maintenant créer les tables dont nous avons besoin. Il y en aura deux au total : les utilisateurs et les autos. Paramètres pour la table des utilisateurs : Votre première application Hibernate - 7Notez que id est la clé primaire. Si vous ne savez pas quelle est la clé primaire en SQL, recherchez-la sur Google. C'est important. Paramètres du tableau des autos : Votre première application Hibernate - 8Pour la table autos, vous devez configurer une clé étrangère. Il servira à relier nos tables. Je vous recommande de lire plus à ce sujet. En termes simples, il fait référence à une table externe, dans notre cas, les utilisateurs. Si une voiture appartient à l'utilisateur avec id = 1, alors le champ user_id des autos sera égal à 1. C'est ainsi que nous associons les utilisateurs à leurs voitures dans notre application. Dans notre table autos, le champ user_id agira comme clé étrangère. Il fera référence au champ id de la table des utilisateurs. Votre première application Hibernate - 9Nous avons donc créé une base de données avec deux tables. Reste à comprendre comment le gérer depuis du code Java. Nous allons commencer par le fichier pom.xml, dans lequel nous devons inclure les bibliothèques nécessaires (dans Maven, elles sont appelées dépendances). Toutes les bibliothèques sont stockées dans le référentiel Maven central. Les bibliothèques que vous spécifiez dans pom.xml sont disponibles pour que vous les utilisiez dans le projet. Votre pom.xml devrait ressembler à ceci : Votre première application Hibernate - 10Rien de compliqué, comme vous pouvez le voir. Nous avons ajouté seulement 2 dépendances — pour utiliser PostgreSQL et Hibernate. Passons maintenant au code Java. Créez tous les packages et classes nécessaires dans le projet. Pour commencer, nous avons besoin d'un modèle de données : les 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 omit the Column attribute if the name property matches the column name 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 omit the Column attribute if the name property matches the column name 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 voir, les classes ont un tas d'annotations obscures. Commençons à les creuser. Pour nous, l'annotation principale est @Entity. Lisez à ce sujet sur Wikipedia et apprenez tout par cœur. C'est le fondement de la fondation. Cette annotation permet aux objets de votre classe Java d'être mappés à une base de données. Pour qu'une classe soit une entité, elle doit satisfaire aux exigences suivantes :
  • Il doit avoir un constructeur vide ( publicou protected)
  • Il ne peut pas être imbriqué, une interface ou unenum
  • Il ne peut pas être finalet ne peut pas avoir finalde champs/propriétés
  • Il doit avoir au moins un champ @Id.
Vérifiez vos classes d'entités : ce sont des endroits très populaires pour vous tirer une balle dans le pied. C'est très facile d'oublier quelque chose. De plus, une entité peut faire ce qui suit :
  • Il peut avoir des constructeurs non vides
  • Il peut hériter et être hérité
  • Il peut avoir d'autres méthodes et implémenter des interfaces.
Comme vous pouvez le voir, la Userclasse est très similaire à la table des utilisateurs. Il a id, nameetagedes champs. Les annotations situées au-dessus n'ont pas besoin d'explication particulière : il est clair que @Id indique que le champ est un identifiant d'objets de cette classe. L'annotation @Table au-dessus de la classe indique le nom de la table où les objets sont écrits. Notez le commentaire au-dessus du champ age : si le nom du champ dans la classe est le même que le nom de la table, vous pouvez omettre l'annotation @Column et cela fonctionnera. Comme pour la partie indiquée entre les accolades ("strategy=GenerationType.IDENTITY") : il existe plusieurs stratégies pour générer les identifiants. Vous pouvez les rechercher sur Google, mais pour notre application, pas besoin de s'embêter. L'essentiel est que pour nos objets la valeur de id soit générée automatiquement. Par conséquent, il n'y a pas de setter pour id, et nous ne le définissons pas non plus dans le constructeur. Cependant,Userclasse se démarque. Il a une liste de voitures! Votre première application Hibernate - 11L'annotation @OneToMany est suspendue au-dessus de la liste. Cela signifie que plusieurs voitures peuvent correspondre à un même objet de la classe User. L'élément "mappedBy" fait référence au champ utilisateur de la Autoclasse. Ainsi, les voitures et les utilisateurs sont liés. L'élément orphanRemoval indique s'il faut appliquer l'opération de suppression aux entités qui n'ont plus de relation. Si nous supprimons un utilisateur de la base de données, toutes les voitures qui lui sont associées seront également supprimées. À son tour, dans leAutoclass, vous verrez le champ user avec l'annotation @ManyToOne (un User peut correspondre à plusieurs Autos) et l'annotation @JoinColumn. Il indique quelle colonne de la table autos est utilisée pour référencer la table users (c'est-à-dire la clé étrangère dont nous avons parlé plus tôt). Après avoir créé le modèle de données, il est temps d'apprendre à notre programme à effectuer des opérations avec les données de la base de données. Commençons par la classe utilitaire HibernateSessionFactoryUtil. Il n'a qu'un seul travail : créer une usine de session pour que notre application fonctionne avec la base de données (dites bonjour au modèle de conception d'usine !). Il ne sait 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("Исключение!" + e);
             }
         }
         return sessionFactory;
     }
 }
 
Dans cette classe, nous créons un nouvel objet Configuration et lui transmettons les classes qu'il doit traiter comme des entités : Useret Auto. Attention à la configuration.getProperties()méthode. Quelles autres propriétés y a-t-il? D'où viennent-ils? Les propriétés sont les paramètres d'hibernation indiqués dans le fichier spécial hibernate.cfg.xml. Votre première application Hibernate - 12Hibernate.cfg.xml se lit ici : new Configuration().configure(); Comme vous le voyez, il n'a rien de particulier : il contient les paramètres de connexion à la base de données, ainsi que le paramètre show_sql. Ceci est nécessaire pour que toutes les requêtes sql exécutées par Hibernate soient affichées sur la console. De cette façon, vous verrez exactement ce que fait Hibernate à tout moment, éliminant tout sentiment de "magie". Ensuite, nous avons besoin deUserDAOclasse. La meilleure pratique consiste à programmer via les interfaces - créez une UserDAOinterface et UserDAOImplune implémentation séparées, mais je vais ignorer cela afin de réduire la quantité de code. Ne faites pas cela dans de vrais projets ! Le modèle de conception DAO (objet d'accès aux données) est l'un des plus courants. L'idée est simple : créer une couche d'application responsable uniquement de l'accès aux données, rien de plus. Récupérer des données de la base de données, mettre à jour des données, supprimer des données - c'est tout. En savoir plus sur DAO. Vous utiliserez constamment des objets d'accès aux données dans votre travail. Que peut UserDaofaire notre classe ? Eh bien, comme tous les DAO, il ne peut fonctionner qu'avec des données. Trouver un utilisateur par identifiant, mettre à jour ses données, le supprimer, obtenir 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 l'intégralité de ses fonctionnalités.

 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;
     }
 }
 
UserDaoLes méthodes de sont similaires les unes aux autres. Dans la plupart d'entre eux, nous obtenons un objet Session (session de connexion à la base de données) à l'aide de notre Session Factory, créons une seule transaction dans cette session, effectuons les manipulations de données nécessaires, enregistrons le résultat de la transaction dans la base de données, puis fermons la session. Les méthodes elles-mêmes, comme vous pouvez le voir, sont assez simples. DAO est le "cœur" de notre application. Cependant, nous ne créerons pas directement un DAO et n'appellerons pas ses méthodes dans notre main()méthode. Toute la logique sera déplacée vers la UserServiceclasse.

 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);
     }
 
 
 }
 
 
Un service est une couche de données d'application responsable de l'exécution de la logique métier. Si votre programme doit exécuter une sorte de logique métier, il le fait via des services. Un service contient un UserDaoet appelle les méthodes DAO dans ses méthodes. Il peut sembler que nous dupliquons des fonctions ici (pourquoi ne pas simplement appeler les méthodes à partir d'un objet DAO ?), Mais avec beaucoup d'objets et une logique complexe, la superposition de l'application offre d'énormes avantages (c'est une bonne pratique - rappelez-vous ceci à l'avenir et lire sur les "couches d'application"). Notre service a une logique simple, mais les méthodes de service dans les projets réels contiennent bien plus d'une ligne de code :) Nous avons maintenant tout ce dont vous avez besoin pour exécuter l'application ! Dans la main()méthode, créons un utilisateur et sa voiture, associons-les l'un à l'autre, 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 ("Jenny", 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 des utilisateurs a son propre enregistrement et la table des autos a son propre enregistrement. Votre première application Hibernate - 13Votre première application Hibernate - 14Essayons de renommer notre utilisateur. Effacer la table des utilisateurs et exécuter 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 ("Jenny", 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 ("Benny");
         userService.updateUser(user);
     }
 }
 
 
Ça marche! Votre première application Hibernate - 15Et si vous supprimez l'utilisateur ? Effacez la table des utilisateurs (les autos s'effaceront) et exécutez 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 ("Jenny", 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 ("Benny");
         userService.updateUser(user);
         userService.deleteUser(user);
     }
 }
 
 
Et nos tables sont complètement vides (faites attention à la console — toutes les requêtes effectuées par Hibernate y seront affichées). Vous pouvez jouer avec l'application et essayer toutes ses fonctions. Par exemple, créez un utilisateur avec des voitures, enregistrez-le dans la base de données, examinez l'identifiant attribué à l'utilisateur et essayez d'utiliser cet identifiant dans lemain()méthode pour récupérer l'utilisateur de la base de données et afficher une liste de ses voitures sur la console. Bien sûr, nous n'avons vu qu'une petite partie des fonctionnalités d'Hibernate. Ses capacités sont très étendues et il s'agit depuis longtemps d'un outil standard 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". J'ai commenté dans un précédent article. 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 de vous répondre :) Aussi, n'oubliez pas de soutenir l'auteur du concours en postant un "J'aime". Ou mieux encore - "J'adore" :) Bonne chance dans vos études !
Commentaires
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION