JavaRush /Java Blog /Random-IT /La tua prima applicazione di ibernazione

La tua prima applicazione di ibernazione

Pubblicato nel gruppo Random-IT
In questo articolo conoscerai uno dei framework aziendali più popolari per Java e creerai la tua prima applicazione utilizzando Hibernate. Non hai mai sentito parlare dell'ibernazione? Forse ne hai sentito parlare, ma non l'hai usato? Oppure hai provato ad avviare, ma non ci sei riuscito? In tutti e tre i casi, benvenuto nel taglio :) La tua prima applicazione di ibernazione - 1Ciao a tutti! In questo articolo parlerò delle principali funzionalità del framework Hibernate e ti aiuterò a scrivere la tua prima mini-applicazione. Per questo abbiamo bisogno di:
  1. Edizione Intellij Idea Ultimate;
    Scarica dal sito ufficiale e attiva la versione di prova di 30 giorni.
  2. PostgeSQL è uno dei moderni sistemi di gestione di database (DBMS) più popolari;
  3. Maven (già integrato in IDEA);
  4. Un po 'di pazienza.
L'articolo è rivolto principalmente a chi non ha mai lavorato con questa tecnologia, quindi la quantità di codice è stata ridotta il più possibile. Iniziamo!

Cos'è l'ibernazione?

Questa è una delle implementazioni più popolari del modello ORM. Il modello relazionale a oggetti descrive le relazioni tra gli oggetti software e i record nel database. Naturalmente, le funzionalità di Hibernate sono molto ampie, ma ci concentreremo sulle funzioni più semplici. Il nostro obiettivo: creare un'applicazione CRUD (Crea, Leggi, Aggiorna, Elimina) che sarà in grado di:
  1. Creare utenti (Utente), nonché cercarli nel database per ID, aggiornare i loro dati nel database e anche eliminarli dal database.
  2. Assegna oggetti veicolo (Auto) agli utenti. Crea, modifica, trova ed elimina auto dal database.
  3. Inoltre, l'applicazione dovrebbe rimuovere automaticamente le auto “orfane” dal database. Quelli. Quando un utente viene eliminato, anche tutte le vetture a lui appartenenti dovranno essere eliminate dal database.
La struttura del nostro progetto sarà la seguente: La tua prima applicazione di ibernazione - 2Come puoi vedere, niente di complicato. 6 classi + 1 file con configurazioni. Innanzitutto, creiamo un nuovo progetto Maven in Intellij Idea. File -> Nuovo progetto. Dai tipi di progetto proposti, seleziona Maven e vai avanti. La tua prima applicazione di ibernazione - 3Apache Maven è un framework per automatizzare l'assemblaggio di progetti basato sulla descrizione della loro struttura in file nel linguaggio POM. L'intera struttura del tuo progetto sarà descritta nel file pom.xml, che IDEA stessa creerà nella root del tuo progetto. Nelle impostazioni del progetto dovrai specificare i parametri Maven: groupId e artifactId. In genere nei progetti groupId è il nome dell'organizzazione o della divisione e lì è scritto il nome del dominio dell'organizzazione o del sito del progetto. A sua volta, artifactId è il nome del progetto. Per groupdId è possibile specificare com.вашНикнейм.javarush, ciò non influenzerà in alcun modo il funzionamento dell'applicazione. Per artifactId, seleziona il nome di progetto che preferisci. Puoi anche lasciare la versione invariata. La tua prima applicazione di ibernazione - 4Nell'ultima schermata sarà sufficiente confermare i dati precedentemente inseriti. La tua prima applicazione di ibernazione - 5Quindi, abbiamo creato il progetto, non resta che scrivere il codice e farlo funzionare :) Innanzitutto, se vogliamo creare un'applicazione che funzioni con un database, non possiamo assolutamente fare a meno di un database! Scarica PostgreSQL da qui (io uso la versione 9). PostgreSQL ha un utente predefinito "postgres", dovrai creare una password durante l'installazione. Non dimenticare la password, ci servirà più tardi! (In generale, utilizzare il database predefinito nelle applicazioni è una cattiva pratica, ma per ridurre il numero di emorroidi ci accontenteremo di creare il nostro database). Se non ti senti a tuo agio con la riga di comando e le query SQL, ci sono buone notizie. Intellij IDEA fornisce un'interfaccia utente abbastanza adatta per lavorare con il database. Si presenta così: La tua prima applicazione di ibernazione - 6(situato sulla barra laterale destra di IDEA, scheda Database) Per creare una connessione, fare clic su "+", selezionare il nostro provider (PostgeSQL). Compila i campi con l'utente, il nome del database (entrambi sono Postgres) e inserisci la password che hai impostato durante l'installazione di PostgreSQL. Se necessario, scarica il driver Postgres, puoi farlo su questa stessa pagina. Fare clic su "Test connessione" per verificare che la connessione al database sia stabilita. Se vedi la scritta "Successful", andiamo avanti. Ora creiamo le tabelle di cui abbiamo bisogno. Ce ne saranno due: utenti e automobili. Parametri per la tabella utenti: La tua prima applicazione su Hibernate - 7tieni presente che id è la chiave primaria. Se non sai cos'è una chiave primaria in SQL, cercala su Google, è importante. Impostazione per la tabella auto: La tua prima applicazione su Hibernate - 8Per le auto è necessario configurare Foreign Key - chiave esterna. Collegherà le nostre tabelle. Ti consiglio di leggere di più su di lui; Per dirla in modo molto semplice si riferisce ad una tabella esterna, nel nostro caso gli utenti. Se l'auto appartiene a un utente con id=1, nel campo user_id della tabella autos avrà 1. Questo è il modo in cui colleghiamo 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 di ibernazione - 9Pertanto, abbiamo creato un database con due tabelle. Resta da capire come gestirlo dal codice Java. Inizieremo con il file pom.xml, nel quale dovremo includere le librerie necessarie (nel linguaggio Maven si chiamano dipendenze). Tutte le librerie sono archiviate nel repository Maven centrale. Quelli specificati in pom.xml possono essere utilizzati nel progetto. Il tuo pom.xml dovrebbe assomigliare a questo: La tua prima applicazione di ibernazione - 10Niente di complicato come puoi vedere. Abbiamo aggiunto solo 2 dipendenze: per l'utilizzo di PostgreSQL e Hibernate. Passiamo ora al codice Java. Crea tutti i pacchetti e le classi necessari per il progetto. Per cominciare, avremo bisogno di modelli di dati: classi Usere file 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;
    }
}
Come puoi vedere, le classi sono dotate di una serie di annotazioni ancora poco chiare. Cominciamo ad occuparci di loro. L'annotazione principale per noi è @Entity. Leggilo su Wikipedia e ricorda tutto, questa è la base delle basi. Questa annotazione consente di associare gli oggetti Java della tua classe al database. Affinché una classe sia un'entità, deve soddisfare i seguenti requisiti:
  • Deve avere un costruttore vuoto ( publico protected);
  • Non può essere nidificato, interfacciato o enum;
  • Non può essere finale non può contenere final-campi/proprietà;
  • Deve contenere almeno un campo @Id.
Controlla le tue classi di entità, questi sono un posto molto popolare per darti la zappa sui piedi. È molto facile dimenticare qualcosa. In questo caso l’ente può:
  • Contenere costruttori non vuoti;
  • Essere ereditato ed essere ereditato;
  • Contengono altri metodi e implementano le interfacce.
Come puoi vedere, la classe Userè molto simile alla tabella users. Ci sono campi id, name, age. Le annotazioni situate sopra di esse non necessitano di molte spiegazioni: è già chiaro che @Id indica che il campo è un identificatore di oggetti di questa classe. L'annotazione @Table sopra la classe specifica il nome della tabella in cui vengono scritti gli oggetti. Presta attenzione al commento sopra il campo età: se il nome del campo nella classe e nella tabella è lo stesso, non devi aggiungere l'annotazione @Column, funzionerà così. Per quanto riguarda la “strategia = GenerationType.IDENTITY” indicata tra parentesi: esistono diverse strategie di generazione dell'ID. Puoi cercarlo su Google, ma nell'ambito della nostra applicazione non devi preoccuparti. La cosa principale è che gli ID per i nostri oggetti verranno generati automaticamente, quindi non esiste un setter per id e non lo specifichiamo nemmeno nel costruttore. UserTuttavia, la classe si distingue ancora in qualche modo . Ha una lista di auto! L'annotazione @OneToMany viene visualizzata sopra l'elenco. Ciò significa che un oggetto della classe utente può corrispondere a più macchine. L'impostazione "mappedBY" punta al campo utente della classe Auto. In questo modo macchine e utenti sono collegati tra loro. L'impostazione orphanRemoval si traduce abbastanza bene dall'inglese: "rimuovi orfani". Se eliminiamo un utente dal database, verranno eliminate anche tutte le auto a lui associate. A sua volta nella classe Autovedrai il campo utente con l'annotazione @ManyToOne (più Auto possono corrispondere ad un Utente) e l'annotazione @JoinColumn. Indica attraverso quale colonna della tabella autos avviene la connessione con la tabella users (la stessa chiave esterna di cui abbiamo parlato prima). Dopo aver creato un modello di dati, è il momento di insegnare al nostro programma a eseguire operazioni su questi dati nel database. Cominciamo con la classe di utilità HibernateSessionFactoryUtil. Ha un solo compito: creare una session factory affinché la nostra applicazione funzioni con il database (ciao, il pattern "Factory!"). Non può fare nient'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("Exception!" + e);
            }
        }
        return sessionFactory;
    }
}
In questa classe creiamo un nuovo oggetto di configurazione, Configuration, e gli passiamo le classi che dovrebbe percepire come entità - Usere Auto. Attenzione al metodo configuration.getProperties(). Quali altre proprietà? Dove? Le proprietà sono parametri per il funzionamento dell'ibernazione, specificati in un file speciale hibernate.cfg.xml. La tua prima applicazione di ibernazione - 11Hibernate.cfg.xml viene letto qui: new Configuration().configure(); Come puoi vedere, non contiene nulla di speciale: parametri per la connessione al database e un parametro speciale show_sql. È necessario affinché tutte le query SQL che verranno eseguite in ibernazione sul nostro database vengano inviate alla console. In questo modo vedrai esattamente cosa sta facendo Hibernate in ogni momento ed eliminerai l'effetto "magico". Successivamente abbiamo bisogno della classe UserDAO. (In senso buono, devi programmare attraverso le interfacce: crea un'interfaccia UserDAOe implementala separatamente UserDAOImpl, ma per ridurre la quantità di codice lo ometterò. Non farlo nei progetti reali!). DAO (oggetto di accesso ai dati) è uno dei modelli di progettazione più comuni, "Accesso ai dati". Il suo significato è semplice: creare un livello nell'applicazione responsabile solo dell'accesso ai dati e nient'altro. Ottieni dati dal database, aggiorna i dati, cancella i dati e il gioco è fatto. Leggi di più sui DAO; li utilizzerai costantemente nel tuo lavoro. Cosa può fare la nostra classe UserDao? In realtà, come tutti i DAO, può funzionare solo con i dati. Trova un utente tramite ID, aggiorna i suoi dati, cancellalo, estrai un elenco di tutti gli utenti dal database o salva un nuovo utente nel database: questa è tutta la sua 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;
    }
}
I metodi UserDaosono simili tra loro. Nella maggior parte di essi, riceviamo un oggetto Session (una sessione che si connette al nostro database) utilizzando la nostra Session Factory, creiamo una singola transazione all'interno di questa sessione, eseguiamo le trasformazioni dei dati necessarie, salviamo il risultato della transazione nel database e chiudiamo la sessione. I metodi stessi, come puoi vedere, sono abbastanza semplici. Il DAO è il “cuore” della nostra applicazione. Tuttavia, non creeremo direttamente il DAO e chiameremo i suoi metodi nel nostro file main(). Tutta la logica verrà spostata nel file 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);
    }


}
Il servizio è un livello dati nell'applicazione responsabile dell'esecuzione della logica aziendale. Se il tuo programma deve eseguire una logica aziendale, lo fa tramite i servizi. Il servizio contiene al suo interno UserDaoe chiama metodi DAO nei suoi metodi. Potrebbe sembrarti una duplicazione di funzioni (perché non chiamare semplicemente metodi da un oggetto dao), ma con un gran numero di oggetti e una logica complessa, suddividere l'applicazione in livelli ha enormi vantaggi (questa è una buona pratica, ricorda queste informazioni per il futuro e leggere informazioni sui “livelli di applicazione”"). Nel nostro servizio la logica è semplice, ma nei progetti reali i metodi di servizio conterranno molto più di una riga di codice :) Ora abbiamo tutto ciò di cui abbiamo bisogno affinché l'applicazione funzioni! Creiamo main()un utente e delle macchine per lui nel metodo, colleghiamoli tra loro 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("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);
    }
}
Come puoi vedere, la tabella users ha la propria voce e la tabella autos ha la propria. La tua prima applicazione di ibernazione - 13La tua prima applicazione di ibernazione - 14Proviamo a rinominare il nostro utente. Cancellamo la tabella degli utenti ed eseguiamo 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("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);
    }
}
Lavori! La tua prima applicazione di ibernazione - 15Cosa succede se elimini un utente? Cancellamo la tabella degli utenti (autos si cancellerà da sola) ed eseguiamo 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("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);
    }
}
E le nostre tabelle sono completamente vuote (presta attenzione alla console, tutte le query eseguite da Hibernate verranno visualizzate lì). Puoi giocare con l'applicazione e provare tutte le sue funzionalità. Ad esempio, crea un utente con macchine, salvalo nel database, vedi quale ID gli è assegnato e prova a utilizzare il metodo main()per "estrarre" l'utente dal database tramite questo ID e visualizzare un elenco delle sue macchine nella console . Naturalmente abbiamo visto solo una piccola parte delle funzionalità di Hibernate. Le sue capacità sono molto ampie ed è stato per lungo tempo uno degli standard di settore per lo sviluppo Java. Se vuoi studiarlo nel dettaglio, posso consigliarti il ​​libro “Java Persistence API and Hibernate”, che ho recensito in uno dei miei articoli precedenti. 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 mettendo "Mi piace" a lui. O meglio ancora: "Mi piace moltissimo" :) Buona fortuna per i tuoi studi!
Commenti
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION