ABONAMENTE VIDEO REDACȚIA
RO
EN
NOU
Numărul 150
Numărul 149 Numărul 148 Numărul 147 Numărul 146 Numărul 145 Numărul 144 Numărul 143 Numărul 142 Numărul 141 Numărul 140 Numărul 139 Numărul 138 Numărul 137 Numărul 136 Numărul 135 Numărul 134 Numărul 133 Numărul 132 Numărul 131 Numărul 130 Numărul 129 Numărul 128 Numărul 127 Numărul 126 Numărul 125 Numărul 124 Numărul 123 Numărul 122 Numărul 121 Numărul 120 Numărul 119 Numărul 118 Numărul 117 Numărul 116 Numărul 115 Numărul 114 Numărul 113 Numărul 112 Numărul 111 Numărul 110 Numărul 109 Numărul 108 Numărul 107 Numărul 106 Numărul 105 Numărul 104 Numărul 103 Numărul 102 Numărul 101 Numărul 100 Numărul 99 Numărul 98 Numărul 97 Numărul 96 Numărul 95 Numărul 94 Numărul 93 Numărul 92 Numărul 91 Numărul 90 Numărul 89 Numărul 88 Numărul 87 Numărul 86 Numărul 85 Numărul 84 Numărul 83 Numărul 82 Numărul 81 Numărul 80 Numărul 79 Numărul 78 Numărul 77 Numărul 76 Numărul 75 Numărul 74 Numărul 73 Numărul 72 Numărul 71 Numărul 70 Numărul 69 Numărul 68 Numărul 67 Numărul 66 Numărul 65 Numărul 64 Numărul 63 Numărul 62 Numărul 61 Numărul 60 Numărul 59 Numărul 58 Numărul 57 Numărul 56 Numărul 55 Numărul 54 Numărul 53 Numărul 52 Numărul 51 Numărul 50 Numărul 49 Numărul 48 Numărul 47 Numărul 46 Numărul 45 Numărul 44 Numărul 43 Numărul 42 Numărul 41 Numărul 40 Numărul 39 Numărul 38 Numărul 37 Numărul 36 Numărul 35 Numărul 34 Numărul 33 Numărul 32 Numărul 31 Numărul 30 Numărul 29 Numărul 28 Numărul 27 Numărul 26 Numărul 25 Numărul 24 Numărul 23 Numărul 22 Numărul 21 Numărul 20 Numărul 19 Numărul 18 Numărul 17 Numărul 16 Numărul 15 Numărul 14 Numărul 13 Numărul 12 Numărul 11 Numărul 10 Numărul 9 Numărul 8 Numărul 7 Numărul 6 Numărul 5 Numărul 4 Numărul 3 Numărul 2 Numărul 1
×
▼ LISTĂ EDIȚII ▼
Numărul 75
Abonament PDF

Hibernate : o abordare simplă prin exemple

Cătălin Tudose
Java and Web Technologies Expert @ Luxoft Training



PROGRAMARE


Hibernate este un framework Java foarte popular, destinat facilitării accesului la baze de date şi conectării între lumea obiectuală şi lumea tabelelor relaţionale. Articolul nostru îşi propune să ofere o introducere în utilizarea acestui framework.

Urmând paradigma POO, Java gestionează obiectele din memorie, acestea conlucrând pentru rezolvarea problemei. O posibilă dificultate cu care se poate confrunta programatorul este aceea a faptului ca, la terminarea execuţiei programului, informaţia conţinută de acestea să fie pierdută. Astfel de obiecte se numesc tranzitorii.

Noţiunea de persistenţă se referă la posibilitatea de salvare a datelor şi după încetarea execuţiei aplicaţiei. Aproape toate aplicaţiile necesită ca obiectul creat să fie salvat pentru un acces ulterior şi pentru o eventuală modificare.

Prin instanţiere, obiectul devine tranzitoriu în interiorul aplicaţiei. Pentru ca un obiect să devină persistent, acesta trebuie salvat şi făcut disponibil chiar şi după ce aplicaţia încetează să se execute.

Soluţia cea mai răspândită pentru realizarea persistenţei este folosirea bazei de date şi a sistemului pentru gestionarea bazelor de date. Există diferite tipuri de baze de date, în funcţie de modul în care datele sunt organizate şi în funcţie de modul în care le accesăm. Bazele de date relaţionale conţin date stocate în tabele care sunt conectate prin relaţii. În momentul de faţă, cel mai răspândit tip de baze de date este cel relaţional.

În timpul dezvoltării intensive şi a creării sistemelor de stocare şi gestionare a datelor, programarea orientată pe obiecte nu era prea răspândită. Acesta este unul dintre motivele din cauza cărora dezvoltarea sistemului de gestionare a datelor a folosit modelul relaţional. Încă unul dintre motivele pentru care se acordă atenţie în ziua de astăzi bazelor de date relaţionale este şi limbajul prin care sunt gestionate datele în astfel de sisteme - SQL.

Bazele de date relaţionale reprezintă o tehnologie matură care a fost deja dovedită în practică. Aproape fiecare dintre sistemele relaţionale pentru gestionarea bazelor de date, care sunt populare în ziua de astăzi, au în spatele lor o dezvoltare îndelungată şi o utilizare activă. De asemenea, bazele de date relaţionale se bazează pe standarde larg acceptate. Migrarea între două sisteme relaţionale pentru gestionarea bazelor de date nu reprezintă o dificultate.

Pentru conectarea lumii obiectuale cu lumea relațională trebuie dezvoltată o logică care va insera caracteristicile şi stările obiectelor în mod adecvat în baza de date, în aşa fel încât să fie posibilă citirea şi reutilizarea obiectelor. Pentru aşa ceva trebuie respectate unele reguli anterior stabilite. Autorii acestor reguli trebuie să fim noi; de asemenea, oricine ar vrea să lucreze la obiectele noastre trebuie să ştie regulile pe baza cărora se va executa persistenţa în baza de date.

Procesul care reduce decalajul între modelul relaţional şi cel orientat pe obiecte se numeşte mapare obiectual-relaţională. Acest proces are şi prescurtarea de ORM (Object-Relational Mapping). Scopul nostru este să gestionăm datele prin obiectele Java, ceea ce este o situaţie normală din punctul de vedere al unei aplicaţii.

După ce obiectele sunt salvate permanent în baza de date, acestea se pot prelua mai târziu din ea şi reîmpacheta în obiecte pentru a le folosi din nou. Această mapare, de fapt, transformă datele dintr-o reprezentare în alta.

Aceste transformări ale datelor se efectuează la nivelul mediu al aplicaţiei, în partea destinată persistenţei, adică în aşa-numitul strat sau nivel persistent. Echipa de dezvoltare dispune de mai multe posibilităţi de implementare a acestui mecanism. ORM se poate implementa doar cu ajutorul SQL-ului şi JDBC-ului, însă echipa de dezvoltare poate folosi şi un instrument care automatizează acest proces. Instrumentele care automatizează acest proces se numesc instrumente ORM, iar Hibernate este un astfel de instrument.

Dintre avantajele instrumentelor de mapare, menţionăm:

Mentenanţa

Cu ajutorul acestor instrumente se obţine un sistem uşor de întreţinut şi, în primul rând, uşor de înţeles. Această reducere semnificativă a cantităţii de cod reduce şi posibilitatea de erori, dar asigură o mentenanţă uşoară.

Timpul de dezvoltare

Codul care se scrie manual pentru persistenţa obiectelor este ceea ce necesită cel mai mult timp, dar pe de altă parte nu reprezintă nicio provocare pentru programatori. Părţile din aplicaţie legate de persistenţă se scriu pe baza unui şablon, independent de tipul de sistem care se implementează. Utilizarea instrumentelor pentru maparea obiectual-relaţională scurtează timpul pentru acest lucru monoton şi asigură programatorilor axarea asupra părţilor din cod specifice pentru o problemă care se implementează în aşa-numitul business logic.

Portabilitatea

Proiectarea corectă a aplicaţiei software implică faptul că aceasta, în timpul dezvoltării, nu ar trebui să "ştie" cu ce sistem de gestionare a bazei de date (SGBD) va comunica. Aceasta ar trebui să fie independentă de producător şi de versiunea de SGBD. Tocmai aceasta este una dintre caracteristicile mai importante ale aplicaţiilor proiectate în mod corect. Dacă din anumite motive se ajunge la schimbarea SGBD-ului, nici în acest caz nu trebuie să influenţeze aplicaţia software.

Dintre dezavantajele instrumentelor de mapare, menţionăm:

Hibernate asigură o persistenţă foarte uşoară a celor mai simple obiecte Java (POJO - Plain Old Java Object). Hibernate trebuie să cunoască ce tabele şi obiecte sunt în relaţie - aceasta se obţine prin mapare. Maparea defineşte modul de copiere a obiectelor din memoria aplicaţiei în baza de date. Există două moduri de definire a mapării:

Pe baza mapării Hibernate este capabil să realizeze partea sa de operaţie care se referă la salvarea datelor în baza de date. Pentru a face aceasta, Hibernate foloseşte fişierul său de configurare.

Presupunem că avem o aplicaţie care doreşte să opereze cu o librărie, gestionând cărţile acesteia.

O asemenea clasă POJO ar putea arăta astfel:

package model;
public class Book {
  private int id;
  private String author;
  private String title;

  public Book(String author, String title) {
        this.author = author;
        this.title = title;
    }

    public int getId() { return id; }
    public void setId(int id) { this.id = id; }
    public String getAuthor() { return author; }
    public void setAuthor(String author) {
        this.author = author;
    }
    public String getTitle() { return title; }
    public void setTitle(String title) {
        this.title = title;
    }
}

Configurarea din fişierul Hibernate este prezentată mai jos:

<?xml version="1.0" encoding="UTF-8"?>
<hibernate-configuration>
  <session-factory>
    <property name="hibernate.dialect">
      org.hibernate.dialect.MySQLDialect</property>

    <property 
      name="hibernate.connection.driver_class">
        com.mysql.cj.jdbc.Driver
    </property>

    <property name="hibernate.connection.url">  
    jdbc:mysql://localhost:3306/bookstore
    </property>

    <property name="hibernate.connection.username"> 
    root
    </property>

    <property name="hibernate.connection.password"> 
    </property>

    <property name="hibernate.hbm2ddl.auto">
        create
    </property>

    <mapping class="model.Book"/>
    <mapping resource="config/book.hbm.xml" />

  </session-factory>
</hibernate-configuration>

Fişierul de configurare Hibernate cuprinde câteva informaţii esenţiale:

Maparea este o marcare a datelor pentru ca acestea să fie recunoscute şi utilizate în mod corect. Pentru ca o entitate să fie salvată în baza de date, Hibernate caută fişierul de mapare care defineşte maparea entităţii în baza de date. Acest fişier conţine datele de care Hibernate are nevoie pentru ca să ştie în ce fel va efectua comunicarea cu baza de date, ce tabel să acceseze şi ce coloană să folosească. Pentru clasa Book, maparea XML ar arăta astfel:

<?xml version="1.0" encoding="utf-8"?>
 <hibernate-mapping>
     <class name="model.Book" table="books">
         <id name="id" type="long" column="id">
             <generator class="increment" />
         </id>
         <property name="author" 
           column="author" type="string" />
         <property name="title" 
                   column="title" 
           type="string" />
     </class>
 </hibernate-mapping>

Pentru a fi posibilă pornirea şi punerea în funcţie a Hibernate-ului este necesară existenţa obiectului Session. Acest obiect se foloseşte pentru crearea unei
conexiuni fizice la baza de date.

Persistenţa şi furnizarea obiectelor se execută prin
acest obiect. Pentru obţinerea instanţei obiectelor Session este necesară existenţa obiectelor Configuration
şi SessionFactory. Configurarea Hibernate-ului oferă informaţii despre bazele de date şi mapare.

Obiectul Configuration se foloseşte pentru crearea obiectului SessionFactory care la rândul său permite instanţierea obiectului Session.

Pentru obţinerea obiectului Session se creează o clasă auxiliară care se utilizează oriunde este necesar în aplicaţie. Cel mai des, o astfel de clasă se numeşte HibernateUtil.

public class HibernateUtil {

 private static final SessionFactory sessionFactory;
 private static final ServiceRegistry serviceRegistry;

 static {
   try {
    Configuration configuration = new Configuration();
    configuration.configure("config/hibernate.cfg.xml");
    serviceRegistry = 
     new StandardServiceRegistryBuilder() 
       .applySettings(configuration.getProperties())
       .build();

    sessionFactory = configuration
          .buildSessionFactory(serviceRegistry);

  } catch (Throwable ex) {
    System.err.println(
     "Initial SessionFactory creation failed." + ex);
      throw new ExceptionInInitializerError(ex);
      }
    }

 public static SessionFactory getSessionFactory() {
   return sessionFactory;
 }
}

Utilizarea HibernateUtil şi interacţiunea cu baza de date se produce astfel:

package booksstore;

import model.Book;
import model.HibernateUtil;
import org.hibernate.Session;
import org.hibernate.SessionFactory;

public class BooksStore {
    public static void main(String[] args) {

      SessionFactory sessionFactory = HibernateUtil
         .getSessionFactory();

      Session session = sessionFactory.openSession();
        session.beginTransaction();
        Book book = new Book("Dave Minter", 
                             "Beginning Hibernate");
        session.save(book);
        session.getTransaction().commit();
        session.close();
        System.exit(0);
    }
}

Pentru configurarea şi utilizarea Hibernate prin intermediul anotărilor este necesar să realizăm următoarele modificări:

package model;

import javax.persistence.*;

@Entity
@Table(name="books")
public class Book {

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

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

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

    public Book(String author, String title) {
        this.author = author;
        this.title = title;
    }

    public int getId() {
        return id;
    }

Anotările se scriu în cadrul claselor Java şi conţin marcajul \@ la început. Ele sunt parte a limbajului de programare Java începând cu versiunea 5. Ele pot fi verificate în timpul compilării şi eventual se poate efectua refactoring prin intermediul IDE-ului. În timpul mapării XML nu se poate verifica corectitudinea semantică. Mai mult, sunt mai simple spre deosebire de mapările XML care sunt mai complexe şi au mai mult cod.

Anotările utilizate în exemplul nostru au următoarea semnificaţie:

@Entity - defineşte clasa ca fiind asociată cu o entitate într-o bază de date.

@Table - indică denumirea tabelei cu care se face asocierea.

@Id - defineşte câmpul de identificare (cheia primară din tabelă).

@GeneratedValue - indică faptul că valoarea este generată de baza de date şi cum anume se face această generare.

@Column - indică numele coloanei cu care se face asocierea.

Concluzii

Hibernate este un puternic instrument ORM, a cărui introducere am făcut-o în acest articol. Am pus faţă în faţă cele două metode de a defini meta-informaţia necesară mapării între clasele Java şi tabela din baza de date. Exemplele au condus la crearea asocierii dintre o clasă din program şi o tabelă, reprezentând în acest fel primii paşi de acumulat celor care vor utiliza acest framework.

NUMĂRUL 149 - Development with AI

Sponsori

  • Accenture
  • BT Code Crafters
  • Accesa
  • Bosch
  • Betfair
  • MHP
  • BoatyardX
  • .msg systems
  • P3 group
  • Ing Hubs
  • Cognizant Softvision
  • Colors in projects