CodeGym /Java Blog /Random-IT /La tua prima applicazione Hibernate
John Squirrels
Livello 41
San Francisco

La tua prima applicazione Hibernate

Pubblicato nel gruppo Random-IT
In questo articolo, acquisirai familiarità con uno dei framework aziendali più popolari per Java e creerai la tua prima applicazione Hibernate. Mai sentito parlare di Hibernate? O forse ne hai sentito parlare, ma non l'hai usato? O forse hai provato a usarlo, ma non ci sei riuscito? In tutti e tre i casi, benvenuti in below the cut :) La tua prima applicazione Hibernate - 1 Ciao a tutti! In questo articolo parlerò delle caratteristiche principali del framework Hibernate e ti aiuterò a scrivere la tua prima mini-applicazione. Per questo, abbiamo bisogno di:
  1. IntelliJ IDEA Ultimate Edition
    Scaricalo dal sito ufficiale e attiva la versione di prova di 30 giorni.
  2. PostgreSQL - uno dei più popolari sistemi di gestione di database moderni (DBMS)
  3. Maven (già collegato a IDEA)
  4. Un po 'di pazienza.
Per ogni evenienza, ho pubblicato il codice dell'applicazione su GitHub (ramo codegym). L'articolo è rivolto principalmente a coloro che non hanno mai lavorato con questa tecnologia prima, quindi ho ridotto al minimo la quantità di codice. Iniziamo!

Cos'è l'ibernazione?

È una delle implementazioni ORM (object-relational mapping) più popolari. Una mappatura oggetto-relazionale definisce la relazione tra oggetti software e record di database. Naturalmente, Hibernate ha funzionalità molto ampie, ma ci concentreremo sulle funzioni più semplici. Il nostro obiettivo è creare un'applicazione CRUD (Create, Read, Update, Delete) che sarà in grado di:
  1. Crea utenti (Utente), cercali nel database per ID, aggiorna i loro dati nel database ed eliminali dal database.
  2. Assegna oggetti auto (Auto) agli utenti. Crea, aggiorna, trova ed elimina auto dal database.
  3. Inoltre, l'applicazione dovrebbe rimuovere automaticamente le auto "senza proprietario" dal database. In altre parole, quando un utente viene cancellato, anche tutte le auto appartenenti a quell'utente devono essere cancellate dal database.
Il nostro progetto sarà strutturato così: La tua prima applicazione Hibernate - 2Come puoi vedere, niente di complicato. 6 classi + 1 file con configurazioni. Innanzitutto, crea un nuovo progetto Maven in IntelliJ IDEA. File -> Nuovo progetto. Seleziona Maven tra i tipi di progetto proposti e vai al passaggio successivo. La tua prima applicazione Hibernate - 3Apache Maven è un framework per la creazione automatica di progetti in base a una descrizione della loro struttura nei file POM. L'intera struttura del tuo progetto sarà descritta in pom.xml, un file che IDEA stessa creerà nella root del tuo progetto. Nelle impostazioni del progetto, è necessario specificare le seguenti impostazioni Maven: groupId e artifactId. Nei progetti, groupId è in genere una descrizione dell'azienda o dell'unità aziendale. Il nome di dominio dell'azienda o del sito web può andare qui. A sua volta, artifactId è il nome del progetto. Per groupdId, puoi inserire com.yourNickname.codegym. Questo non avrà alcun effetto sull'applicazione. Per artifactId, scegli il nome del progetto che preferisci. La versione può essere lasciata invariata. La tua prima applicazione Hibernate - 4Nell'ultima schermata è sufficiente confermare i dati precedentemente inseriti.La tua prima applicazione Hibernate - 5Quindi, abbiamo creato il progetto. Ora tutto ciò che resta da fare è scrivere del codice e farlo funzionare :) Per prima cosa: se vogliamo creare un'applicazione che funzioni con un database, non possiamo assolutamente fare a meno di un database! Scarica PostgreSQL da qui (sto usando la versione 9). PostgreSQL ha un utente predefinito 'postgres': dovrai pensare a una password per esso durante l'installazione. Non dimenticare la password. Ne avremo bisogno dopo! (In generale, utilizzare il database predefinito nelle applicazioni è una cattiva pratica, ma lo faremo per ridurre il numero di cause di ulcere creando il tuo database). Se non sei amico della riga di comando e delle query SQL, ci sono buone notizie. IntelliJ IDEA fornisce un'interfaccia utente completamente adatta per lavorare con il database. La tua prima applicazione Hibernate - 6(situato nel riquadro destro di IDEA, la scheda Database). Per creare una connessione, fai clic su "+" e seleziona la nostra origine dati (PostgeSQL). Compila i campi per l'utente e il database ("postgres" per entrambi) e inserisci la password che è stata impostata durante l'installazione di PostgreSQL. Se necessario, scarica il driver Postgres. Puoi farlo sulla stessa pagina. Fare clic su "Test connessione" per verificare che la connessione al database sia stata stabilita. Se vedi "Riuscito", vai avanti. Ora creeremo le tabelle di cui abbiamo bisogno. Ci saranno un totale di due: utenti e auto. Parametri per la tabella utenti: La tua prima applicazione Hibernate - 7Si noti che id è la chiave primaria. Se non sai qual è la chiave primaria in SQL, cercala su Google. Questo è importante. Impostazioni per la tabella automatica: La tua prima applicazione Hibernate - 8Per la tabella autos, devi configurare una chiave esterna. Servirà per collegare le nostre tabelle. Ti consiglio di leggere di più a riguardo. In parole povere, fa riferimento a una tabella esterna, nel nostro caso utenti. Se un'auto appartiene all'utente con id = 1, allora il campo user_id delle auto sarà uguale a 1. Questo è il modo in cui associamo gli utenti alle loro auto nella nostra applicazione. Nella nostra tabella autos, il campo user_id fungerà da chiave esterna. Farà riferimento al campo id della tabella utenti. La tua prima applicazione Hibernate - 9Quindi, abbiamo creato un database con due tabelle. Resta da capire come gestirlo dal codice Java. Inizieremo con il file pom.xml, in cui dobbiamo includere le librerie necessarie (in Maven si chiamano dipendenze). Tutte le librerie sono archiviate nel repository centrale di Maven. Le librerie specificate in pom.xml sono disponibili per l'uso nel progetto. Il tuo pom.xml dovrebbe assomigliare a questo: La tua prima applicazione Hibernate - 10Niente di complicato, come puoi vedere. Abbiamo aggiunto solo 2 dipendenze - per l'utilizzo di PostgreSQL e Hibernate. Ora passiamo al codice Java. Crea tutti i pacchetti e le classi necessari nel progetto. Per iniziare, abbiamo bisogno di un modello di dati: le classi Usere 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;
     }
 }
 
 
Come puoi vedere, le classi hanno un mucchio di annotazioni oscure. Cominciamo a scavare in loro. Per noi, l'annotazione principale è @Entity. Leggilo su Wikipedia e impara tutto a memoria. Questo è il fondamento della fondazione. Questa annotazione consente di mappare gli oggetti della tua classe Java su un database. Affinché una classe sia un'entità, deve soddisfare i seguenti requisiti:
  • Deve avere un costruttore vuoto ( publico protected)
  • Non può essere nidificato, un'interfaccia o un fileenum
  • Non può essere finale non può avere finalcampi/proprietà
  • Deve avere almeno un campo @Id.
Controlla le tue classi di entità: sono luoghi molto popolari per spararti ai piedi. È molto facile dimenticare qualcosa. Inoltre, un'entità può fare quanto segue:
  • Può avere costruttori non vuoti
  • Può ereditare ed essere ereditato
  • Può avere altri metodi e implementare interfacce.
Come puoi vedere, la Userclasse è molto simile alla tabella degli utenti. Ha id, nameeagecampi. Le annotazioni che si trovano sopra di esse non necessitano di alcuna spiegazione particolare: è chiaro che @Id indica che il campo è un identificatore di oggetti di questa classe. L'annotazione @Table sopra la classe indica il nome della tabella in cui sono scritti gli oggetti. Nota il commento sopra il campo dell'età: se il nome del campo nella classe è uguale al nome della tabella, puoi omettere l'annotazione @Column e funzionerà. Per quanto riguarda la parte indicata tra parentesi graffe ("strategy = GenerationType.IDENTITY"): esistono diverse strategie per la generazione degli ID. Puoi cercarli su Google, ma per la nostra applicazione non c'è bisogno di preoccuparsi. La cosa principale è che per i nostri oggetti il ​​valore di id verrà generato automaticamente. Di conseguenza, non esiste un setter per id e non lo impostiamo nemmeno nel costruttore. Tuttavia,Userla classe si distingue. Ha una lista di auto! La tua prima applicazione Hibernate - 11L'annotazione @OneToMany è sospesa sopra l'elenco. Significa che più auto possono corrispondere allo stesso oggetto della classe User. L'elemento "mappedBy" fa riferimento al campo utente della Autoclasse. Pertanto, auto e utenti sono correlati. L'elemento orphanRemoval indica se applicare l'operazione di rimozione alle entità che non hanno più una relazione. Se eliminiamo un utente dal database, verranno eliminate anche tutte le auto ad esso associate. A sua volta, nelAutoclass, vedrai il campo utente con l'annotazione @ManyToOne (un utente può corrispondere a molti Auto) e l'annotazione @JoinColumn. Indica quale colonna nella tabella autos è usata per fare riferimento alla tabella users (cioè la chiave esterna di cui abbiamo parlato prima). Dopo aver creato il modello di dati, è il momento di insegnare al nostro programma a eseguire operazioni con i dati nel database. Iniziamo con la classe di utilità HibernateSessionFactoryUtil. Ha un solo compito: creare una session factory affinché la nostra applicazione funzioni con il database (saluta il modello di progettazione Factory!). Non sa fare altro.

 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;
     }
 }
 
In questa classe, creiamo un nuovo oggetto Configuration e gli passiamo le classi che dovrebbe trattare come entità: Usere Auto. Attenzione al configuration.getProperties()metodo. Quali altre proprietà ci sono? Da dove vengono? Le proprietà sono le impostazioni di ibernazione indicate nell'apposito file hibernate.cfg.xml. La tua prima applicazione Hibernate - 12Hibernate.cfg.xml si legge qui: new Configuration().configure(); Come vedete, non ha nulla di particolare: contiene i parametri per la connessione al database, oltre al parametro show_sql. Ciò è necessario affinché tutte le query sql eseguite da Hibernate vengano visualizzate sulla console. In questo modo vedrai esattamente cosa sta facendo Hibernate in un dato momento, eliminando ogni senso di "magia". Successivamente abbiamo bisogno del fileUserDAOclasse. La migliore pratica è programmare attraverso le interfacce: creare un'interfaccia UserDAOe UserDAOImplun'implementazione separate, ma salterò questo per ridurre la quantità di codice. Non farlo in progetti reali! Il modello di progettazione DAO (oggetto di accesso ai dati) è uno dei più comuni. L'idea è semplice: creare un livello dell'applicazione responsabile solo dell'accesso ai dati, niente di più. Recupera i dati dal database, aggiorna i dati, elimina i dati: tutto qui. Studia di più su DAO. Utilizzerai oggetti di accesso ai dati costantemente nel tuo lavoro. Cosa può UserDaofare la nostra classe? Bene, come tutti i DAO, può funzionare solo con i dati. Trova un utente per ID, aggiorna i suoi dati, eliminalo, ottieni un elenco di tutti gli utenti dal database o salva un nuovo utente nel database: questa è l'intera funzionalità.

 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;
     }
 }
 
UserDaoI metodi di sono simili tra loro. Nella maggior parte di essi, otteniamo un oggetto Session (sessione di connessione al database) utilizzando la nostra Session Factory, creiamo una singola transazione all'interno di questa sessione, eseguiamo le necessarie manipolazioni dei dati, salviamo il risultato della transazione nel database e quindi chiudiamo la sessione. I metodi stessi, come puoi vedere, sono abbastanza semplici. DAO è il "cuore" della nostra applicazione. Tuttavia, non creeremo direttamente un DAO e chiameremo i suoi metodi nel nostro main()metodo. Tutta la logica verrà spostata nella 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 servizio è un livello di dati dell'applicazione responsabile dell'esecuzione della logica aziendale. Se il tuo programma deve eseguire una sorta di logica aziendale, lo fa attraverso i servizi. Un servizio contiene un UserDaoe chiama i metodi DAO nei suoi metodi. Potrebbe sembrare che stiamo duplicando le funzioni qui (perché non chiamare semplicemente i metodi da un oggetto DAO?), ma con molti oggetti e logica complessa, la stratificazione dell'applicazione offre enormi vantaggi (farlo è una buona pratica - ricordalo in futuro e leggi di "livelli di applicazione"). Il nostro servizio ha una logica semplice, ma i metodi di servizio nei progetti del mondo reale contengono molto più di una riga di codice :) Ora abbiamo tutto il necessario per eseguire l'applicazione! Nel main()metodo, creiamo un utente e la sua auto, associamo l'uno all'altro e salviamoli nel database.

 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);
     }
 }
 
 
Come puoi vedere, la tabella utenti ha il proprio record e la tabella autos ha il proprio record. La tua prima applicazione Hibernate - 13La tua prima applicazione Hibernate - 14Proviamo a rinominare il nostro utente. Cancella la tabella degli utenti ed esegui il codice

 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);
     }
 }
 
 
Funziona! La tua prima applicazione Hibernate - 15E se elimini l'utente? Cancella la tabella degli utenti (le auto si cancelleranno da sole) ed esegui il codice

 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);
     }
 }
 
 
E le nostre tabelle sono completamente vuote (presta attenzione alla console: lì verranno visualizzate tutte le richieste eseguite da Hibernate). Puoi giocare con l'applicazione e provare tutte le sue funzioni. Ad esempio, crea un utente con auto, salvalo nel database, guarda l'id assegnato all'utente e prova a utilizzare questo id nelmain()metodo per recuperare l'utente dal database e visualizzare un elenco delle sue auto sulla console. Ovviamente, abbiamo visto solo una piccola parte delle funzionalità di Hibernate. Le sue capacità sono molto ampie ed è stato a lungo uno strumento industriale standard per lo sviluppo Java. Se vuoi studiarlo in dettaglio, posso consigliare il libro "Java Persistence API and Hibernate". Ho recensito in un precedente articolo. Spero che questo articolo sia stato utile ai lettori. Se hai domande, chiedile nei commenti. Sarò felice di rispondere :) Inoltre, non dimenticare di supportare l'autore nel concorso pubblicando un "Mi piace". O meglio ancora - "Lo adoro" :) Buona fortuna per i tuoi studi!
Commenti
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION