Ibernazione - Guida rapida

Cos'è JDBC?

JDBC sta per Java Database Connectivity. Fornisce una serie di API Java per accedere ai database relazionali dal programma Java. Queste API Java consentono ai programmi Java di eseguire istruzioni SQL e interagire con qualsiasi database conforme a SQL.

JDBC fornisce un'architettura flessibile per scrivere un'applicazione indipendente dal database che può essere eseguita su piattaforme diverse e interagire con diversi DBMS senza alcuna modifica.

Pro e contro di JDBC

Pro di JDBC Contro di JDBC

Elaborazione SQL pulita e semplice

Buone prestazioni con dati di grandi dimensioni

Ottimo per piccole applicazioni

Sintassi semplice così facile da imparare

Complesso se utilizzato in grandi progetti

Grande sovraccarico di programmazione

Nessun incapsulamento

Difficile da implementare il concetto MVC

La query è specifica per DBMS

Perché Object Relational Mapping (ORM)?

Quando lavoriamo con un sistema orientato agli oggetti, c'è una mancata corrispondenza tra il modello a oggetti e il database relazionale. Gli RDBMS rappresentano i dati in un formato tabulare, mentre i linguaggi orientati agli oggetti, come Java o C #, lo rappresentano come un grafico di oggetti interconnessi.

Considera la seguente classe Java con i costruttori appropriati e la funzione pubblica associata:

public class Employee {
   private int id;
   private String first_name; 
   private String last_name;   
   private int salary;  

   public Employee() {}
   public Employee(String fname, String lname, int salary) {
      this.first_name = fname;
      this.last_name = lname;
      this.salary = salary;
   }
   
   public int getId() {
      return id;
   }
   
   public String getFirstName() {
      return first_name;
   }
   
   public String getLastName() {
      return last_name;
   }
   
   public int getSalary() {
      return salary;
   }
}

Considera che gli oggetti di cui sopra devono essere memorizzati e recuperati nella seguente tabella RDBMS:

create table EMPLOYEE (
   id INT NOT NULL auto_increment,
   first_name VARCHAR(20) default NULL,
   last_name  VARCHAR(20) default NULL,
   salary     INT  default NULL,
   PRIMARY KEY (id)
);

Primo problema, cosa succede se dobbiamo modificare il design del nostro database dopo aver sviluppato alcune pagine o la nostra applicazione? In secondo luogo, il caricamento e l'archiviazione di oggetti in un database relazionale ci espone ai seguenti cinque problemi di mancata corrispondenza:

Sr.No. Mancata corrispondenza e descrizione
1

Granularity

A volte avrai un modello a oggetti, che ha più classi del numero di tabelle corrispondenti nel database.

2

Inheritance

Gli RDBMS non definiscono nulla di simile a Inheritance, che è un paradigma naturale nei linguaggi di programmazione orientati agli oggetti.

3

Identity

Un RDBMS definisce esattamente una nozione di "uguaglianza": la chiave primaria. Java, tuttavia, definisce sia l'identità dell'oggetto (a == b) che l'uguaglianza dell'oggetto (a.equals (b)).

4

Associations

I linguaggi orientati agli oggetti rappresentano associazioni utilizzando riferimenti a oggetti mentre un RDBMS rappresenta un'associazione come colonna di chiave esterna.

5

Navigation

Le modalità di accesso agli oggetti in Java e in RDBMS sono fondamentalmente diverse.

Il Ooggetto-Relazionale Mapping (ORM) è la soluzione per gestire tutti i disallineamenti di impedenza di cui sopra.

Cos'è ORM?

ORM sta per Ooggetto-Relazionale Mapping (ORM) è una tecnica di programmazione per convertire i dati tra database relazionali e linguaggi di programmazione orientati agli oggetti come Java, C #, ecc.

Un sistema ORM presenta i seguenti vantaggi rispetto al semplice JDBC:

Sr.No. Vantaggi
1 Passiamo agli oggetti di accesso al codice aziendale anziché alle tabelle DB.
2 Nasconde i dettagli delle query SQL dalla logica OO.
3 Basato su JDBC "sotto il cofano".
4 Non è necessario occuparsi dell'implementazione del database.
5 Entità basate su concetti di business piuttosto che sulla struttura del database.
6 Gestione delle transazioni e generazione automatica delle chiavi.
7 Sviluppo rapido dell'applicazione.

Una soluzione ORM è composta dalle seguenti quattro entità:

Sr.No. Soluzioni
1 Un'API per eseguire operazioni CRUD di base su oggetti di classi persistenti.
2 Un linguaggio o un'API per specificare query che fanno riferimento a classi e proprietà delle classi.
3 Una funzione configurabile per specificare i metadati di mappatura.
4 Una tecnica per interagire con oggetti transazionali per eseguire controlli sporchi, fetch di associazioni pigre e altre funzioni di ottimizzazione.

Framework Java ORM

Esistono diversi framework persistenti e opzioni ORM in Java. Un framework persistente è un servizio ORM che archivia e recupera oggetti in un database relazionale.

  • Enterprise JavaBeans Entity Beans
  • Oggetti dati Java
  • Castor
  • TopLink
  • Primavera DAO
  • Hibernate
  • E molti altri

Hibernate è un file Ooggetto-Relazionale Mapping (ORM) per JAVA. È un framework persistente open source creato da Gavin King nel 2001. È un servizio di query e persistenza relazionale a oggetti potente e ad alte prestazioni per qualsiasi applicazione Java.

Hibernate associa le classi Java alle tabelle del database e dai tipi di dati Java ai tipi di dati SQL e solleva lo sviluppatore dal 95% delle comuni attività di programmazione relative alla persistenza dei dati.

Hibernate si trova tra gli oggetti Java tradizionali e il server di database per gestire tutte le operazioni di persistenza di quegli oggetti in base ai meccanismi e ai modelli O / R appropriati.

Vantaggi di ibernazione

  • Hibernate si occupa di mappare le classi Java alle tabelle del database utilizzando file XML e senza scrivere alcuna riga di codice.

  • Fornisce API semplici per archiviare e recuperare oggetti Java direttamente da e verso il database.

  • Se sono presenti modifiche nel database o in una tabella, è necessario modificare solo le proprietà del file XML.

  • Estrae i tipi SQL non familiari e fornisce un modo per aggirare gli oggetti Java familiari.

  • Hibernate non richiede un server delle applicazioni per funzionare.

  • Manipola associazioni complesse di oggetti del database.

  • Riduce al minimo l'accesso al database con strategie di recupero intelligenti.

  • Fornisce una semplice query di dati.

Database supportati

Hibernate supporta quasi tutti i principali RDBMS. Di seguito è riportato un elenco di alcuni dei motori di database supportati da Hibernate:

  • Motore di database HSQL
  • DB2/NT
  • MySQL
  • PostgreSQL
  • FrontBase
  • Oracle
  • Database di Microsoft SQL Server
  • Sybase SQL Server
  • Informix Dynamic Server

Tecnologie supportate

Hibernate supporta una varietà di altre tecnologie, tra cui:

  • XDoclet Spring
  • J2EE
  • Plug-in di Eclipse
  • Maven

Hibernate ha un'architettura a più livelli che aiuta l'utente a operare senza dover conoscere le API sottostanti. Hibernate fa uso del database e dei dati di configurazione per fornire servizi di persistenza (e oggetti persistenti) all'applicazione.

Di seguito è riportata una vista di alto livello dell'architettura dell'applicazione Hibernate.

Di seguito è riportata una vista dettagliata dell'architettura dell'applicazione Hibernate con le sue importanti classi principali.

Hibernate utilizza varie API Java esistenti, come JDBC, Java Transaction API (JTA) e Java Naming and Directory Interface (JNDI). JDBC fornisce un livello rudimentale di astrazione delle funzionalità comuni ai database relazionali, consentendo a quasi tutti i database con un driver JDBC di essere supportati da Hibernate. JNDI e JTA consentono l'integrazione di Hibernate con i server delle applicazioni J2EE.

La sezione seguente fornisce una breve descrizione di ciascuno degli oggetti classe coinvolti in Hibernate Application Architecture.

Oggetto di configurazione

L'oggetto Configuration è il primo oggetto Hibernate creato in qualsiasi applicazione Hibernate. Di solito viene creato solo una volta durante l'inizializzazione dell'applicazione. Rappresenta un file di configurazione o delle proprietà richiesto da Hibernate.

L'oggetto Configurazione fornisce due componenti chiave:

  • Database Connection- Questo viene gestito tramite uno o più file di configurazione supportati da Hibernate. Questi file sonohibernate.properties e hibernate.cfg.xml.

  • Class Mapping Setup - Questo componente crea la connessione tra le classi Java e le tabelle del database.

Oggetto SessionFactory

L'oggetto di configurazione viene utilizzato per creare un oggetto SessionFactory che a sua volta configura Hibernate per l'applicazione utilizzando il file di configurazione fornito e consente di istanziare un oggetto Session. SessionFactory è un oggetto thread-safe e utilizzato da tutti i thread di un'applicazione.

La SessionFactory è un oggetto pesante; di solito viene creato durante l'avvio dell'applicazione e conservato per un uso successivo. Avresti bisogno di un oggetto SessionFactory per database utilizzando un file di configurazione separato. Quindi, se stai usando più database, dovresti creare più oggetti SessionFactory.

Oggetto sessione

Una sessione viene utilizzata per ottenere una connessione fisica con un database. L'oggetto Session è leggero e progettato per essere istanziato ogni volta che è necessaria un'interazione con il database. Gli oggetti persistenti vengono salvati e recuperati tramite un oggetto Session.

Gli oggetti della sessione non dovrebbero essere tenuti aperti per molto tempo perché di solito non sono thread-safe e dovrebbero essere creati e distrutti secondo necessità.

Oggetto transazione

Una transazione rappresenta un'unità di lavoro con il database e la maggior parte dell'RDBMS supporta la funzionalità di transazione. Le transazioni in Hibernate vengono gestite da un gestore delle transazioni e da una transazione sottostanti (da JDBC o JTA).

Questo è un oggetto opzionale e le applicazioni Hibernate potrebbero scegliere di non utilizzare questa interfaccia, invece di gestire le transazioni nel proprio codice dell'applicazione.

Oggetto query

Gli oggetti query utilizzano una stringa SQL o Hibernate Query Language (HQL) per recuperare i dati dal database e creare oggetti. Un'istanza di Query viene utilizzata per associare i parametri della query, limitare il numero di risultati restituiti dalla query e infine per eseguire la query.

Oggetto Criteri

Gli oggetti Criteria vengono utilizzati per creare ed eseguire query di criteri orientate agli oggetti per recuperare gli oggetti.

Questo capitolo spiega come installare Hibernate e altri pacchetti associati per preparare un ambiente per le applicazioni Hibernate. Lavoreremo con il database MySQL per sperimentare esempi di Hibernate, quindi assicurati di avere già una configurazione per il database MySQL. Per maggiori dettagli su MySQL, puoi controllare il nostro Tutorial su MySQL .

Download di Hibernate

Si presume che tu abbia già l'ultima versione di Java installata sul tuo sistema. Di seguito sono riportati i semplici passaggi per scaricare e installare Hibernate sul tuo sistema:

  • Scegli se installare Hibernate su Windows o Unix, quindi procedi al passaggio successivo per scaricare il file .zip per Windows e il file .tz per Unix.

  • Scarica l'ultima versione di Hibernate da http://www.hibernate.org/downloads.

  • Al momento della stesura di questo tutorial, ho scaricato hibernate-distribution3.6.4.Final e quando decomprimi il file scaricato, ti darà la struttura della directory come mostrato nell'immagine seguente

Installazione di Hibernate

Dopo aver scaricato e decompresso l'ultima versione del file di installazione di Hibernate, è necessario eseguire i seguenti due semplici passaggi. Assicurati di impostare correttamente la tua variabile CLASSPATH altrimenti dovrai affrontare problemi durante la compilazione dell'applicazione.

  • Ora copia tutti i file della libreria da /lib nel tuo CLASSPATH e cambia la tua variabile classpath per includere tutti i JAR -

  • Infine, copia hibernate3.jarfile nel tuo CLASSPATH. Questo file si trova nella directory principale dell'installazione ed è il JAR principale di cui Hibernate ha bisogno per fare il suo lavoro.

Prerequisiti di ibernazione

Di seguito è riportato l'elenco dei pacchetti / librerie richiesti da Hibernate e dovresti installarli prima di iniziare con Hibernate. Per installare questi pacchetti, dovrai copiare i file di libreria da/lib nel tuo CLASSPATH e modifica la tua variabile CLASSPATH di conseguenza.

Sr.No. Pacchetti / librerie
1

dom4j

Analisi XML www.dom4j.org/

2

Xalan

Processore XSLT https://xml.apache.org/xalan-j/

3

Xerces

Il parser Java di Xerces https://xml.apache.org/xerces-j/

4

cglib

Modifiche appropriate alle classi Java in fase di esecuzione http://cglib.sourceforge.net/

5

log4j

Registrazione di Faremwork https://logging.apache.org/log4j

6

Commons

Registrazione, e-mail, ecc. https://jakarta.apache.org/commons

7

SLF4J

Facciata di registrazione per Java https://www.slf4j.org

Hibernate richiede di sapere in anticipo dove trovare le informazioni di mappatura che definiscono il modo in cui le classi Java si relazionano alle tabelle del database. Hibernate richiede anche una serie di impostazioni di configurazione relative al database e altri parametri correlati. Tutte queste informazioni vengono solitamente fornite come file delle proprietà Java standard chiamatohibernate.propertieso come file XML denominato hibernate.cfg.xml.

Prenderò in considerazione il file formattato XML hibernate.cfg.xmlper specificare le proprietà Hibernate richieste nei miei esempi. La maggior parte delle proprietà assume i propri valori predefiniti e non è necessario specificarli nel file delle proprietà a meno che non sia realmente richiesto. Questo file è conservato nella directory principale del classpath dell'applicazione.

Proprietà di ibernazione

Di seguito è riportato l'elenco delle proprietà importanti, ti verrà richiesto di configurare un database in una situazione autonoma -

Sr.No. Proprietà e descrizione
1

hibernate.dialect

Questa proprietà fa in modo che Hibernate generi l'SQL appropriato per il database scelto.

2

hibernate.connection.driver_class

La classe del driver JDBC.

3

hibernate.connection.url

L'URL JDBC all'istanza del database.

4

hibernate.connection.username

Il nome utente del database.

5

hibernate.connection.password

La password del database.

6

hibernate.connection.pool_size

Limita il numero di connessioni in attesa nel pool di connessioni del database Hibernate.

7

hibernate.connection.autocommit

Consente l'utilizzo della modalità autocommit per la connessione JDBC.

Se si utilizza un database insieme a un server delle applicazioni e JNDI, è necessario configurare le seguenti proprietà:

Sr.No. Proprietà e descrizione
1

hibernate.connection.datasource

Il nome JNDI definito nel contesto del server delle applicazioni, che si sta utilizzando per l'applicazione.

2

hibernate.jndi.class

La classe InitialContext per JNDI.

3

hibernate.jndi.<JNDIpropertyname>

Passa qualsiasi proprietà JNDI desiderata a JNDI InitialContext .

4

hibernate.jndi.url

Fornisce l'URL per JNDI.

5

hibernate.connection.username

Il nome utente del database.

6

hibernate.connection.password

La password del database.

Iberna con il database MySQL

MySQL è uno dei sistemi di database open source più popolari oggi disponibili. Cerchiamo di crearehibernate.cfg.xmlfile di configurazione e posizionarlo nella radice del classpath dell'applicazione. Dovrai assicurarti di averlo fattotestdb database disponibile nel tuo database MySQL e hai un utente test disponibile per accedere al database.

Il file di configurazione XML deve essere conforme alla DTD di configurazione di Hibernate 3, disponibile all'indirizzo http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd.

<?xml version = "1.0" encoding = "utf-8"?>
<!DOCTYPE hibernate-configuration SYSTEM 
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
   <session-factory>
   
      <property name = "hibernate.dialect">
         org.hibernate.dialect.MySQLDialect
      </property>
      
      <property name = "hibernate.connection.driver_class">
         com.mysql.jdbc.Driver
      </property>
      
      <!-- Assume test is the database name -->
      
      <property name = "hibernate.connection.url">
         jdbc:mysql://localhost/test
      </property>
      
      <property name = "hibernate.connection.username">
         root
      </property>
      
      <property name = "hibernate.connection.password">
         root123
      </property>
      
      <!-- List of XML mapping files -->
      <mapping resource = "Employee.hbm.xml"/>
      
   </session-factory>
</hibernate-configuration>

Il file di configurazione sopra include <mapping> tag, che sono correlati al file di mappatura di ibernazione e vedremo nel prossimo capitolo cos'è esattamente un file di mappatura di ibernazione e come e perché lo usiamo?

Di seguito è riportato l'elenco di vari tipi di proprietà dialettali di database importanti:

Sr.No. Proprietà database e dialetto
1

DB2

org.hibernate.dialect.DB2Dialect

2

HSQLDB

org.hibernate.dialect.HSQLDialect

3

HypersonicSQL

org.hibernate.dialect.HSQLDialect

4

Informix

org.hibernate.dialect.InformixDialect

5

Ingres

org.hibernate.dialect.IngresDialect

6

Interbase

org.hibernate.dialect.InterbaseDialect

7

Microsoft SQL Server 2000

org.hibernate.dialect.SQLServerDialect

8

Microsoft SQL Server 2005

org.hibernate.dialect.SQLServer2005Dialect

9

Microsoft SQL Server 2008

org.hibernate.dialect.SQLServer2008Dialect

10

MySQL

org.hibernate.dialect.MySQLDialect

11

Oracle (any version)

org.hibernate.dialect.OracleDialect

12

Oracle 11g

org.hibernate.dialect.Oracle10gDialect

13

Oracle 10g

org.hibernate.dialect.Oracle10gDialect

14

Oracle 9i

org.hibernate.dialect.Oracle9iDialect

15

PostgreSQL

org.hibernate.dialect.PostgreSQLDialect

16

Progress

org.hibernate.dialect.ProgressDialect

17

SAP DB

org.hibernate.dialect.SAPDBDialect

18

Sybase

org.hibernate.dialect.SybaseDialect

19

Sybase Anywhere

org.hibernate.dialect.SybaseAnywhereDialect

Una sessione viene utilizzata per ottenere una connessione fisica con un database. L'oggetto Session è leggero e progettato per essere istanziato ogni volta che è necessaria un'interazione con il database. Gli oggetti persistenti vengono salvati e recuperati tramite un oggetto Session.

Gli oggetti della sessione non dovrebbero essere tenuti aperti per molto tempo perché di solito non sono thread-safe e dovrebbero essere creati e distrutti secondo necessità. La funzione principale della sessione è offrire, creare, leggere ed eliminare operazioni per istanze di classi di entità mappate.

Le istanze possono esistere in uno dei tre stati seguenti in un dato momento:

  • transient - Una nuova istanza di una classe persistente, che non è associata a una sessione e non ha alcuna rappresentazione nel database e nessun valore identificativo è considerata transitoria da Hibernate.

  • persistent- È possibile rendere persistente un'istanza transitoria associandola a una sessione. Un'istanza persistente ha una rappresentazione nel database, un valore identificativo ed è associata a una sessione.

  • detached - Una volta chiusa la sessione di ibernazione, l'istanza persistente diventerà un'istanza scollegata.

Un'istanza di Session è serializzabile se le sue classi persistenti sono serializzabili. Una transazione tipica dovrebbe utilizzare il seguente idioma:

Session session = factory.openSession();
Transaction tx = null;

try {
   tx = session.beginTransaction();
   // do some work
   ...
   tx.commit();
}

catch (Exception e) {
   if (tx!=null) tx.rollback();
   e.printStackTrace(); 
} finally {
   session.close();
}

Se la sessione genera un'eccezione, è necessario eseguire il rollback della transazione e annullare la sessione.

Metodi di interfaccia di sessione

Esistono numerosi metodi forniti da Session, ma elencherò solo alcuni metodi importanti, che utilizzeremo in questo tutorial. Puoi controllare la documentazione di Hibernate per un elenco completo dei metodi associati aSession e SessionFactory.

Sr.No. Metodi e descrizione della sessione
1

Transaction beginTransaction()

Inizia un'unità di lavoro e restituisci l'oggetto Transaction associato.

2

void cancelQuery()

Annulla l'esecuzione della query corrente.

3

void clear()

Cancella completamente la sessione.

4

Connection close()

Termina la sessione rilasciando la connessione JDBC e ripulendo.

5

Criteria createCriteria(Class persistentClass)

Crea una nuova istanza di Criteria, per la classe di entità data o una superclasse di una classe di entità.

6

Criteria createCriteria(String entityName)

Crea una nuova istanza di Criteria, per il nome dell'entità specificato.

7

Serializable getIdentifier(Object object)

Restituisce il valore dell'identificatore dell'entità data come associata a questa sessione.

8

Query createFilter(Object collection, String queryString)

Crea una nuova istanza di Query per la raccolta e la stringa di filtro specificate.

9

Query createQuery(String queryString)

Crea una nuova istanza di Query per la stringa di query HQL specificata.

10

SQLQuery createSQLQuery(String queryString)

Crea una nuova istanza di SQLQuery per la stringa di query SQL specificata.

11

void delete(Object object)

Rimuovi un'istanza persistente dal datastore.

12

void delete(String entityName, Object object)

Rimuovi un'istanza persistente dal datastore.

13

Session get(String entityName, Serializable id)

Restituisce l'istanza persistente dell'entità denominata fornita con l'identificatore specificato o null se non esiste un'istanza persistente di questo tipo.

14

SessionFactory getSessionFactory()

Ottieni la session factory che ha creato questa sessione.

15

void refresh(Object object)

Rileggere lo stato dell'istanza data dal database sottostante.

16

Transaction getTransaction()

Ottieni l'istanza Transaction associata a questa sessione.

17

boolean isConnected()

Controlla se la sessione è attualmente connessa.

18

boolean isDirty()

Questa sessione contiene modifiche che devono essere sincronizzate con il database?

19

boolean isOpen()

Controlla se la sessione è ancora aperta.

20

Serializable save(Object object)

Mantieni l'istanza temporanea data, assegnando prima un identificatore generato.

21

void saveOrUpdate(Object object)

Salva (Object) o aggiorna (Object) l'istanza data.

22

void update(Object object)

Aggiorna l'istanza persistente con l'identificatore dell'istanza scollegata specificata.

23

void update(String entityName, Object object)

Aggiorna l'istanza persistente con l'identificatore dell'istanza scollegata specificata.

L'intero concetto di Hibernate consiste nel prendere i valori dagli attributi della classe Java e mantenerli in una tabella di database. Un documento di mappatura aiuta Hibernate a determinare come estrarre i valori dalle classi e mapparli con la tabella ei campi associati.

Le classi Java i cui oggetti o istanze verranno memorizzate nelle tabelle del database sono chiamate classi persistenti in Hibernate. Hibernate funziona meglio se queste classi seguono alcune semplici regole, note anche comePlain Old Java Object (POJO) modello di programmazione.

Ci sono le seguenti regole principali delle classi persistenti, tuttavia, nessuna di queste regole è un requisito fondamentale:

  • Tutte le classi Java che verranno mantenute necessitano di un costruttore predefinito.

  • Tutte le classi dovrebbero contenere un ID per consentire una facile identificazione dei tuoi oggetti all'interno di Hibernate e nel database. Questa proprietà è mappata alla colonna della chiave primaria di una tabella di database.

  • Tutti gli attributi che verranno mantenuti dovrebbero essere dichiarati privati ​​e avere getXXX e setXXX metodi definiti nello stile JavaBean.

  • Una caratteristica centrale di Hibernate, i proxy, dipende dal fatto che la classe persistente non sia finale o dall'implementazione di un'interfaccia che dichiari tutti i metodi pubblici.

  • Tutte le classi che non estendono o implementano alcune classi e interfacce specializzate richieste dal framework EJB.

Il nome POJO viene utilizzato per sottolineare che un dato oggetto è un normale oggetto Java, non un oggetto speciale e in particolare non un Enterprise JavaBean.

Semplice esempio di POJO

Sulla base delle poche regole sopra menzionate, possiamo definire una classe POJO come segue:

public class Employee {
   private int id;
   private String firstName; 
   private String lastName;   
   private int salary;  

   public Employee() {}
   public Employee(String fname, String lname, int salary) {
      this.firstName = fname;
      this.lastName = lname;
      this.salary = salary;
   }
   
   public int getId() {
      return id;
   }
   
   public void setId( int id ) {
      this.id = id;
   }
   
   public String getFirstName() {
      return firstName;
   }
   
   public void setFirstName( String first_name ) {
      this.firstName = first_name;
   }
   
   public String getLastName() {
      return lastName;
   }
   
   public void setLastName( String last_name ) {
      this.lastName = last_name;
   }
   
   public int getSalary() {
      return salary;
   }
   
   public void setSalary( int salary ) {
      this.salary = salary;
   }
}

Una mappatura oggetto / relazionale viene solitamente definita in un documento XML. Questo file di mappatura istruisce Hibernate: come mappare la classe o le classi definite alle tabelle del database?

Sebbene molti utenti di Hibernate scelgano di scrivere manualmente l'XML, esistono numerosi strumenti per generare il documento di mappatura. Questi includonoXDoclet, Middlegen e AndroMDA per gli utenti avanzati di Hibernate.

Consideriamo la nostra classe POJO definita in precedenza i cui oggetti persisteranno nella tabella definita nella sezione successiva.

public class Employee {
   private int id;
   private String firstName; 
   private String lastName;   
   private int salary;  

   public Employee() {}
   
   public Employee(String fname, String lname, int salary) {
      this.firstName = fname;
      this.lastName = lname;
      this.salary = salary;
   }
   
   public int getId() {
      return id;
   }
   
   public void setId( int id ) {
      this.id = id;
   }
   
   public String getFirstName() {
      return firstName;
   }
   
   public void setFirstName( String first_name ) {
      this.firstName = first_name;
   }
   
   public String getLastName() {
      return lastName;
   }
   
   public void setLastName( String last_name ) {
      this.lastName = last_name;
   }
   
   public int getSalary() {
      return salary;
   }
   
   public void setSalary( int salary ) {
      this.salary = salary;
   }
}

Ci sarebbe una tabella corrispondente a ogni oggetto che sei disposto a fornire la persistenza. Considera che gli oggetti precedenti devono essere archiviati e recuperati nella seguente tabella RDBMS:

create table EMPLOYEE (
   id INT NOT NULL auto_increment,
   first_name VARCHAR(20) default NULL,
   last_name  VARCHAR(20) default NULL,
   salary     INT  default NULL,
   PRIMARY KEY (id)
);

Sulla base delle due entità di cui sopra, possiamo definire il seguente file di mappatura, che istruisce Hibernate su come mappare la classe o le classi definite alle tabelle del database.

<?xml version = "1.0" encoding = "utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC 
"-//Hibernate/Hibernate Mapping DTD//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> 

<hibernate-mapping>
   <class name = "Employee" table = "EMPLOYEE">
      
      <meta attribute = "class-description">
         This class contains the employee detail. 
      </meta>
      
      <id name = "id" type = "int" column = "id">
         <generator class="native"/>
      </id>
      
      <property name = "firstName" column = "first_name" type = "string"/>
      <property name = "lastName" column = "last_name" type = "string"/>
      <property name = "salary" column = "salary" type = "int"/>
      
   </class>
</hibernate-mapping>

È necessario salvare il documento di mappatura in un file con il formato <classname> .hbm.xml. Abbiamo salvato il nostro documento di mappatura nel file Employee.hbm.xml.

Vediamo di capire un piccolo dettaglio sugli elementi di mappatura utilizzati nel file di mappatura -

  • Il documento di mappatura è un documento XML con estensione <hibernate-mapping> come elemento radice, che contiene tutti i file <class> elementi.

  • Il <class>gli elementi vengono utilizzati per definire associazioni specifiche da classi Java alle tabelle del database. Il nome della classe Java viene specificato utilizzando ilname attributo dell'elemento class e del database table nome viene specificato utilizzando l'attributo table.

  • Il <meta> elemento è un elemento opzionale e può essere utilizzato per creare la descrizione della classe.

  • Il <id>L'elemento mappa l'attributo ID univoco nella classe alla chiave primaria della tabella del database. Ilname l'attributo dell'elemento id si riferisce alla proprietà nella classe e nel file columnl'attributo si riferisce alla colonna nella tabella del database. Iltype l'attributo contiene il tipo di mappatura ibernazione, questo tipo di mappatura convertirà da Java a tipo di dati SQL.

  • Il <generator>l'elemento all'interno dell'elemento id viene utilizzato per generare automaticamente i valori della chiave primaria. Ilclass l'attributo dell'elemento generatore è impostato su native per lasciare che ibernazione raccolga entrambi identity, sequence, o hilo algoritmo per creare la chiave primaria a seconda delle capacità del database sottostante.

  • Il <property>elemento viene utilizzato per mappare una proprietà di classe Java a una colonna nella tabella del database. Ilname l'attributo dell'elemento si riferisce alla proprietà nella classe e nel columnl'attributo si riferisce alla colonna nella tabella del database. Iltype l'attributo contiene il tipo di mappatura ibernazione, questo tipo di mappatura convertirà da Java a tipo di dati SQL.

Sono disponibili altri attributi ed elementi, che verranno utilizzati in un documento di mappatura e proverei a coprirne il maggior numero possibile mentre discuto di altri argomenti correlati a Hibernate.

Quando si prepara un documento di mappatura Hibernate, si scopre di mappare i tipi di dati Java nei tipi di dati RDBMS. Iltypesdichiarati e utilizzati nei file di mappatura non sono tipi di dati Java; non sono neanche tipi di database SQL. Questi tipi sono chiamatiHibernate mapping types, che può tradurre da tipi di dati Java a SQL e viceversa.

Questo capitolo elenca tutti i tipi di mappatura di base, data e ora, oggetti grandi e vari altri tipi di mappatura incorporati.

Tipi primitivi

Tipo di mappatura Tipo Java Tipo SQL ANSI
numero intero int o java.lang.Integer NUMERO INTERO
lungo long o java.lang.Long BIGINT
corto short o java.lang.Short PICCOLO
galleggiante float o java.lang.Float GALLEGGIANTE
Doppio double o java.lang.Double DOPPIO
big_decimal java.math.BigDecimal NUMERICO
personaggio java.lang.String CAR (1)
corda java.lang.String VARCHAR
byte byte o java.lang.Byte TINYINT
booleano boolean o java.lang.Boolean PO
si No boolean o java.lang.Boolean CHAR (1) ('Y' o 'N')
true/false boolean or java.lang.Boolean CHAR(1) ('T' or 'F')

Date and Time Types

Mapping type Java type ANSI SQL Type
date java.util.Date or java.sql.Date DATE
time java.util.Date or java.sql.Time TIME
timestamp java.util.Date or java.sql.Timestamp TIMESTAMP
calendar java.util.Calendar TIMESTAMP
calendar_date java.util.Calendar DATE

Binary and Large Object Types

Mapping type Java type ANSI SQL Type
binary byte[] VARBINARY (or BLOB)
text java.lang.String CLOB
serializable any Java class that implements java.io.Serializable VARBINARY (or BLOB)
clob java.sql.Clob CLOB
blob java.sql.Blob BLOB

JDK-related Types

Mapping type Java type ANSI SQL Type
class java.lang.Class VARCHAR
locale java.util.Locale VARCHAR
timezone java.util.TimeZone VARCHAR
currency java.util.Currency VARCHAR

Let us now take an example to understand how we can use Hibernate to provide Java persistence in a standalone application. We will go through the different steps involved in creating a Java Application using Hibernate technology.

Create POJO Classes

The first step in creating an application is to build the Java POJO class or classes, depending on the application that will be persisted to the database. Let us consider our Employee class with getXXX and setXXX methods to make it JavaBeans compliant class.

A POJO (Plain Old Java Object) is a Java object that doesn't extend or implement some specialized classes and interfaces respectively required by the EJB framework. All normal Java objects are POJO.

When you design a class to be persisted by Hibernate, it is important to provide JavaBeans compliant code as well as one attribute, which would work as index like id attribute in the Employee class.

public class Employee {
   private int id;
   private String firstName; 
   private String lastName;   
   private int salary;  

   public Employee() {}
   public Employee(String fname, String lname, int salary) {
      this.firstName = fname;
      this.lastName = lname;
      this.salary = salary;
   }
   
   public int getId() {
      return id;
   }
   
   public void setId( int id ) {
      this.id = id;
   }
   
   public String getFirstName() {
      return firstName;
   }
   
   public void setFirstName( String first_name ) {
      this.firstName = first_name;
   }
   
   public String getLastName() {
      return lastName;
   }
   
   public void setLastName( String last_name ) {
      this.lastName = last_name;
   }
   
   public int getSalary() {
      return salary;
   }
   
   public void setSalary( int salary ) {
      this.salary = salary;
   }
}

Create Database Tables

Second step would be creating tables in your database. There would be one table corresponding to each object, you are willing to provide persistence. Consider above objects need to be stored and retrieved into the following RDBMS table −

create table EMPLOYEE (
   id INT NOT NULL auto_increment,
   first_name VARCHAR(20) default NULL,
   last_name  VARCHAR(20) default NULL,
   salary     INT  default NULL,
   PRIMARY KEY (id)
);

Create Mapping Configuration File

This step is to create a mapping file that instructs Hibernate how to map the defined class or classes to the database tables.

<?xml version = "1.0" encoding = "utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC 
"-//Hibernate/Hibernate Mapping DTD//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> 

<hibernate-mapping>
   <class name = "Employee" table = "EMPLOYEE">
      
      <meta attribute = "class-description">
         This class contains the employee detail. 
      </meta>
      
      <id name = "id" type = "int" column = "id">
         <generator class="native"/>
      </id>
      
      <property name = "firstName" column = "first_name" type = "string"/>
      <property name = "lastName" column = "last_name" type = "string"/>
      <property name = "salary" column = "salary" type = "int"/>
      
   </class>
</hibernate-mapping>

You should save the mapping document in a file with the format <classname>.hbm.xml. We saved our mapping document in the file Employee.hbm.xml. Let us see little detail about the mapping document −

  • The mapping document is an XML document having <hibernate-mapping> as the root element which contains all the <class> elements.

  • The <class> elements are used to define specific mappings from a Java classes to the database tables. The Java class name is specified using the name attribute of the class element and the database table name is specified using the table attribute.

  • The <meta> element is optional element and can be used to create the class description.

  • The <id> element maps the unique ID attribute in class to the primary key of the database table. The name attribute of the id element refers to the property in the class and the column attribute refers to the column in the database table. The type attribute holds the hibernate mapping type, this mapping types will convert from Java to SQL data type.

  • The <generator> element within the id element is used to generate the primary key values automatically. The class attribute of the generator element is set to native to let hibernate pick up either identity, sequence or hilo algorithm to create primary key depending upon the capabilities of the underlying database.

  • The <property> element is used to map a Java class property to a column in the database table. The name attribute of the element refers to the property in the class and the column attribute refers to the column in the database table. The type attribute holds the hibernate mapping type, this mapping types will convert from Java to SQL data type.

There are other attributes and elements available, which will be used in a mapping document and I would try to cover as many as possible while discussing other Hibernate related topics.

Create Application Class

Finally, we will create our application class with the main() method to run the application. We will use this application to save few Employee's records and then we will apply CRUD operations on those records.

import java.util.List; 
import java.util.Date;
import java.util.Iterator; 
 
import org.hibernate.HibernateException; 
import org.hibernate.Session; 
import org.hibernate.Transaction;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class ManageEmployee {
   private static SessionFactory factory; 
   public static void main(String[] args) {
      
      try {
         factory = new Configuration().configure().buildSessionFactory();
      } catch (Throwable ex) { 
         System.err.println("Failed to create sessionFactory object." + ex);
         throw new ExceptionInInitializerError(ex); 
      }
      
      ManageEmployee ME = new ManageEmployee();

      /* Add few employee records in database */
      Integer empID1 = ME.addEmployee("Zara", "Ali", 1000);
      Integer empID2 = ME.addEmployee("Daisy", "Das", 5000);
      Integer empID3 = ME.addEmployee("John", "Paul", 10000);

      /* List down all the employees */
      ME.listEmployees();

      /* Update employee's records */
      ME.updateEmployee(empID1, 5000);

      /* Delete an employee from the database */
      ME.deleteEmployee(empID2);

      /* List down new list of the employees */
      ME.listEmployees();
   }
   
   /* Method to CREATE an employee in the database */
   public Integer addEmployee(String fname, String lname, int salary){
      Session session = factory.openSession();
      Transaction tx = null;
      Integer employeeID = null;
      
      try {
         tx = session.beginTransaction();
         Employee employee = new Employee(fname, lname, salary);
         employeeID = (Integer) session.save(employee); 
         tx.commit();
      } catch (HibernateException e) {
         if (tx!=null) tx.rollback();
         e.printStackTrace(); 
      } finally {
         session.close(); 
      }
      return employeeID;
   }
   
   /* Method to  READ all the employees */
   public void listEmployees( ){
      Session session = factory.openSession();
      Transaction tx = null;
      
      try {
         tx = session.beginTransaction();
         List employees = session.createQuery("FROM Employee").list(); 
         for (Iterator iterator = employees.iterator(); iterator.hasNext();){
            Employee employee = (Employee) iterator.next(); 
            System.out.print("First Name: " + employee.getFirstName()); 
            System.out.print("  Last Name: " + employee.getLastName()); 
            System.out.println("  Salary: " + employee.getSalary()); 
         }
         tx.commit();
      } catch (HibernateException e) {
         if (tx!=null) tx.rollback();
         e.printStackTrace(); 
      } finally {
         session.close(); 
      }
   }
   
   /* Method to UPDATE salary for an employee */
   public void updateEmployee(Integer EmployeeID, int salary ){
      Session session = factory.openSession();
      Transaction tx = null;
      
      try {
         tx = session.beginTransaction();
         Employee employee = (Employee)session.get(Employee.class, EmployeeID); 
         employee.setSalary( salary );
		 session.update(employee); 
         tx.commit();
      } catch (HibernateException e) {
         if (tx!=null) tx.rollback();
         e.printStackTrace(); 
      } finally {
         session.close(); 
      }
   }
   
   /* Method to DELETE an employee from the records */
   public void deleteEmployee(Integer EmployeeID){
      Session session = factory.openSession();
      Transaction tx = null;
      
      try {
         tx = session.beginTransaction();
         Employee employee = (Employee)session.get(Employee.class, EmployeeID); 
         session.delete(employee); 
         tx.commit();
      } catch (HibernateException e) {
         if (tx!=null) tx.rollback();
         e.printStackTrace(); 
      } finally {
         session.close(); 
      }
   }
}

Compilation and Execution

Here are the steps to compile and run the above mentioned application. Make sure, you have set PATH and CLASSPATH appropriately before proceeding for the compilation and execution.

  • Create hibernate.cfg.xml configuration file as explained in configuration chapter.

  • Create Employee.hbm.xml mapping file as shown above.

  • Create Employee.java source file as shown above and compile it.

  • Create ManageEmployee.java source file as shown above and compile it.

  • Execute ManageEmployee binary to run the program.

You would get the following result, and records would be created in the EMPLOYEE table.

$java ManageEmployee
.......VARIOUS LOG MESSAGES WILL DISPLAY HERE........

First Name: Zara  Last Name: Ali  Salary: 1000
First Name: Daisy  Last Name: Das  Salary: 5000
First Name: John  Last Name: Paul  Salary: 10000
First Name: Zara  Last Name: Ali  Salary: 5000
First Name: John  Last Name: Paul  Salary: 10000

Se controlli la tua tabella EMPLOYEE, dovrebbe avere i seguenti record:

mysql> select * from EMPLOYEE;
+----+------------+-----------+--------+
| id | first_name | last_name | salary |
+----+------------+-----------+--------+
| 29 | Zara       | Ali       |   5000 |
| 31 | John       | Paul      |  10000 |
+----+------------+-----------+--------+
2 rows in set (0.00 sec

mysql>

Finora, abbiamo visto una mappatura O / R di base utilizzando l'ibernazione, ma ci sono tre argomenti di mappatura più importanti, che dobbiamo apprendere in dettaglio.

Questi sono -

  • Mappatura delle collezioni,
  • Mappatura delle associazioni tra classi di entità e
  • Mappature dei componenti.

Mappature delle collezioni

Se un'entità o una classe ha una raccolta di valori per una particolare variabile, allora possiamo mappare quei valori utilizzando una qualsiasi delle interfacce di raccolta disponibili in java. Hibernate può persistere istanze dijava.util.Map, java.util.Set, java.util.SortedMap, java.util.SortedSet, java.util.Liste qualsiasi array di entità o valori persistenti.

Sr.No. Tipo di raccolta e descrizione della mappatura
1 java.util.Set

Questo viene mappato con un elemento <set> e inizializzato con java.util.HashSet

2 java.util.SortedSet

Questo è mappato con un elemento <set> e inizializzato con java.util.TreeSet. Ilsort l'attributo può essere impostato su un confronto o su un ordinamento naturale.

3 java.util.List

Questo è mappato con un elemento <list> e inizializzato con java.util.ArrayList

4 java.util.Collection

Questo è mappato con un elemento <bag> o <ibag> e inizializzato con java.util.ArrayList

5 java.util.Map

Questo è mappato con un elemento <map> e inizializzato con java.util.HashMap

6 java.util.SortedMap

Questo è mappato con un elemento <map> e inizializzato con java.util.TreeMap. Ilsort l'attributo può essere impostato su un confronto o su un ordinamento naturale.

Gli array sono supportati da Hibernate con <primitive-array> per i tipi di valore primitivo Java e <array> per tutto il resto. Tuttavia, sono usati raramente, quindi non li discuterò in questo tutorial.

Se si desidera mappare un'interfaccia di raccolta definita dall'utente, che non è supportata direttamente da Hibernate, è necessario informare Hibernate della semantica delle raccolte personalizzate, che non è molto semplice e non è consigliabile utilizzarla.

Mappature delle associazioni

La mappatura delle associazioni tra le classi di entità e le relazioni tra le tabelle è l'anima di ORM. Di seguito sono riportati i quattro modi in cui è possibile esprimere la cardinalità della relazione tra gli oggetti. Una mappatura di associazione può essere sia unidirezionale che bidirezionale.

Sr.No. Tipo di mappatura e descrizione
1 Molti a uno

Mappatura della relazione molti a uno utilizzando Hibernate

2 Uno a uno

Mappatura della relazione uno a uno utilizzando Hibernate

3 Uno a molti

Mappatura della relazione uno-a-molti utilizzando Hibernate

4 Molti a molti

Mappatura della relazione molti-a-molti utilizzando Hibernate

Mappature dei componenti

È molto probabile che una classe Entity possa avere un riferimento a un'altra classe come variabile membro. Se la classe riferita non ha un proprio ciclo di vita e dipende completamente dal ciclo di vita della classe di entità proprietaria, allora la classe riferita è quindi chiamata comeComponent class.

La mappatura della raccolta di componenti è possibile anche in modo simile, proprio come la mappatura delle raccolte regolari con piccole differenze di configurazione. Vedremo in dettaglio queste due mappature con esempi.

Sr.No. Tipo di mappatura e descrizione
1 Mappature dei componenti

Mappatura per una classe che ha un riferimento a un'altra classe come variabile membro.

Finora hai visto come Hibernate utilizza il file di mapping XML per la trasformazione dei dati da POJO a tabelle di database e viceversa. Le annotazioni di ibernazione sono il modo più recente per definire le mappature senza l'uso di file XML. È possibile utilizzare annotazioni in aggiunta o in sostituzione dei metadati di mapping XML.

Annotazioni di ibernazione è il modo efficace per fornire i metadati per il mapping di oggetti e tabelle relazionali. Tutti i metadati vengono inseriti nel file java POJO insieme al codice, questo aiuta l'utente a comprendere la struttura della tabella e POJO simultaneamente durante lo sviluppo.

Se si intende rendere portabile la propria applicazione su altre applicazioni ORM conformi a EJB 3, è necessario utilizzare le annotazioni per rappresentare le informazioni di mappatura, ma se si desidera una maggiore flessibilità, è necessario utilizzare le mappature basate su XML.

Configurazione dell'ambiente per l'annotazione di ibernazione

Prima di tutto dovresti assicurarti di utilizzare JDK 5.0 altrimenti devi aggiornare il tuo JDK a JDK 5.0 per sfruttare il supporto nativo per le annotazioni.

In secondo luogo, dovrai installare il pacchetto di distribuzione delle annotazioni Hibernate 3.x, disponibile da sourceforge: ( Scarica Hibernate Annotation ) e copiahibernate-annotations.jar, lib/hibernate-comons-annotations.jar e lib/ejb3-persistence.jar dalla distribuzione Annotazioni di Hibernate al tuo CLASSPATH.

Esempio di classe annotata

Come accennato in precedenza mentre si lavora con Hibernate Annotation, tutti i metadati vengono raggruppati nel file java POJO insieme al codice, questo aiuta l'utente a comprendere la struttura della tabella e POJO simultaneamente durante lo sviluppo.

Considera che utilizzeremo la seguente tabella EMPLOYEE per memorizzare i nostri oggetti:

create table EMPLOYEE (
   id INT NOT NULL auto_increment,
   first_name VARCHAR(20) default NULL,
   last_name  VARCHAR(20) default NULL,
   salary     INT  default NULL,
   PRIMARY KEY (id)
);

Di seguito è riportata la mappatura della classe Employee con annotazioni per mappare oggetti con la tabella EMPLOYEE definita -

import javax.persistence.*;

@Entity
@Table(name = "EMPLOYEE")
public class Employee {
   @Id @GeneratedValue
   @Column(name = "id")
   private int id;

   @Column(name = "first_name")
   private String firstName;

   @Column(name = "last_name")
   private String lastName;

   @Column(name = "salary")
   private int salary;  

   public Employee() {}
   
   public int getId() {
      return id;
   }
   
   public void setId( int id ) {
      this.id = id;
   }
   
   public String getFirstName() {
      return firstName;
   }
   
   public void setFirstName( String first_name ) {
      this.firstName = first_name;
   }
   
   public String getLastName() {
      return lastName;
   }
   
   public void setLastName( String last_name ) {
      this.lastName = last_name;
   }
   
   public int getSalary() {
      return salary;
   }
   
   public void setSalary( int salary ) {
      this.salary = salary;
   }
}

Hibernate rileva che l'annotazione @Id si trova su un campo e presume che debba accedere alle proprietà di un oggetto direttamente tramite i campi in fase di esecuzione. Se hai posizionato l'annotazione @Id sul metodo getId (), abiliterai l'accesso alle proprietà tramite i metodi getter e setter per impostazione predefinita. Quindi, anche tutte le altre annotazioni vengono posizionate sui campi o sui metodi getter, seguendo la strategia selezionata.

La sezione seguente spiegherà le annotazioni utilizzate nella classe precedente.

@Entity Annotation

Le annotazioni standard EJB 3 sono contenute nel file javax.persistencepacchetto, quindi importiamo questo pacchetto come primo passaggio. In secondo luogo, abbiamo utilizzato il file@Entity annotazione alla classe Employee, che contrassegna questa classe come un bean di entità, quindi deve avere un costruttore senza argomenti visibile almeno con ambito protetto.

@ Annotazione tabella

L'annotazione @Table consente di specificare i dettagli della tabella che verrà utilizzata per rendere persistente l'entità nel database.

L'annotazione @Table fornisce quattro attributi, consentendo di sovrascrivere il nome della tabella, il suo catalogo e il suo schema e imporre vincoli univoci alle colonne nella tabella. Per ora, stiamo usando solo il nome della tabella, che è EMPLOYEE.

Annotazioni @Id e @GeneratedValue

Ogni bean di entità avrà una chiave primaria, che annoti sulla classe con il @Idannotazione. La chiave primaria può essere un singolo campo o una combinazione di più campi a seconda della struttura della tabella.

Per impostazione predefinita, l'annotazione @Id determinerà automaticamente la strategia di generazione della chiave primaria più appropriata da utilizzare ma è possibile sovrascriverla applicando il @GeneratedValue annotazione, che accetta due parametri strategy e generatordi cui non parlerò qui, quindi utilizziamo solo la strategia di generazione delle chiavi predefinita. Lasciando che Hibernate determini quale tipo di generatore utilizzare rende il tuo codice portabile tra database diversi.

@ Annotazione colonna

L'annotazione @Column viene utilizzata per specificare i dettagli della colonna a cui verrà mappato un campo o una proprietà. Puoi utilizzare l'annotazione di colonna con i seguenti attributi più comunemente usati:

  • name l'attributo consente di specificare esplicitamente il nome della colonna.

  • length l'attributo consente la dimensione della colonna utilizzata per mappare un valore in particolare per un valore String.

  • nullable l'attributo consente alla colonna di essere contrassegnata come NOT NULL quando viene generato lo schema.

  • unique l'attributo consente di contrassegnare la colonna come contenente solo valori univoci.

Crea classe di applicazione

Infine, creeremo la nostra classe dell'applicazione con il metodo main () per eseguire l'applicazione. Useremo questa applicazione per salvare pochi record dei dipendenti e quindi applicheremo le operazioni CRUD su quei record.

import java.util.List; 
import java.util.Date;
import java.util.Iterator; 
 
import org.hibernate.HibernateException; 
import org.hibernate.Session; 
import org.hibernate.Transaction;
import org.hibernate.cfg.AnnotationConfiguration;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class ManageEmployee {
   private static SessionFactory factory; 
   public static void main(String[] args) {
      
      try {
         factory = new AnnotationConfiguration().
                   configure().
                   //addPackage("com.xyz") //add package if used.
                   addAnnotatedClass(Employee.class).
                   buildSessionFactory();
      } catch (Throwable ex) { 
         System.err.println("Failed to create sessionFactory object." + ex);
         throw new ExceptionInInitializerError(ex); 
      }
      
      ManageEmployee ME = new ManageEmployee();

      /* Add few employee records in database */
      Integer empID1 = ME.addEmployee("Zara", "Ali", 1000);
      Integer empID2 = ME.addEmployee("Daisy", "Das", 5000);
      Integer empID3 = ME.addEmployee("John", "Paul", 10000);

      /* List down all the employees */
      ME.listEmployees();

      /* Update employee's records */
      ME.updateEmployee(empID1, 5000);

      /* Delete an employee from the database */
      ME.deleteEmployee(empID2);

      /* List down new list of the employees */
      ME.listEmployees();
   }
   
   /* Method to CREATE an employee in the database */
   public Integer addEmployee(String fname, String lname, int salary){
      Session session = factory.openSession();
      Transaction tx = null;
      Integer employeeID = null;
      
      try {
         tx = session.beginTransaction();
         Employee employee = new Employee();
         employee.setFirstName(fname);
         employee.setLastName(lname);
         employee.setSalary(salary);
         employeeID = (Integer) session.save(employee); 
         tx.commit();
      } catch (HibernateException e) {
         if (tx!=null) tx.rollback();
         e.printStackTrace(); 
      } finally {
         session.close(); 
      }
      return employeeID;
   }
   
   /* Method to  READ all the employees */
   public void listEmployees( ){
      Session session = factory.openSession();
      Transaction tx = null;
      
      try {
         tx = session.beginTransaction();
         List employees = session.createQuery("FROM Employee").list(); 
         for (Iterator iterator = employees.iterator(); iterator.hasNext();){
            Employee employee = (Employee) iterator.next(); 
            System.out.print("First Name: " + employee.getFirstName()); 
            System.out.print("  Last Name: " + employee.getLastName()); 
            System.out.println("  Salary: " + employee.getSalary()); 
         }
         tx.commit();
      } catch (HibernateException e) {
         if (tx!=null) tx.rollback();
         e.printStackTrace(); 
      } finally {
         session.close(); 
      }
   }
   
   /* Method to UPDATE salary for an employee */
   public void updateEmployee(Integer EmployeeID, int salary ){
      Session session = factory.openSession();
      Transaction tx = null;
      
      try {
         tx = session.beginTransaction();
         Employee employee = (Employee)session.get(Employee.class, EmployeeID); 
         employee.setSalary( salary );
		 session.update(employee); 
         tx.commit();
      } catch (HibernateException e) {
         if (tx!=null) tx.rollback();
         e.printStackTrace(); 
      } finally {
         session.close(); 
      }
   }
   
   /* Method to DELETE an employee from the records */
   public void deleteEmployee(Integer EmployeeID){
      Session session = factory.openSession();
      Transaction tx = null;
      
      try {
         tx = session.beginTransaction();
         Employee employee = (Employee)session.get(Employee.class, EmployeeID); 
         session.delete(employee); 
         tx.commit();
      } catch (HibernateException e) {
         if (tx!=null) tx.rollback();
         e.printStackTrace(); 
      } finally {
         session.close(); 
      }
   }
}

Configurazione del database

Ora creiamo hibernate.cfg.xml file di configurazione per definire i parametri relativi al database.

<?xml version = "1.0" encoding = "utf-8"?>
<!DOCTYPE hibernate-configuration SYSTEM 
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">

<hibernate-configuration>
   <session-factory>
   
      <property name = "hibernate.dialect">
         org.hibernate.dialect.MySQLDialect
      </property>
   
      <property name = "hibernate.connection.driver_class">
         com.mysql.jdbc.Driver
      </property>

      <!-- Assume students is the database name -->
   
      <property name = "hibernate.connection.url">
         jdbc:mysql://localhost/test
      </property>
   
      <property name = "hibernate.connection.username">
         root
      </property>
   
      <property name = "hibernate.connection.password">
         cohondob
      </property>

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

Compilazione ed esecuzione

Ecco i passaggi per compilare ed eseguire l'applicazione sopra menzionata. Assicurati di aver impostato PATH e CLASSPATH in modo appropriato prima di procedere per la compilazione e l'esecuzione.

  • Elimina il file di mapping Employee.hbm.xml dal percorso.

  • Crea il file sorgente Employee.java come mostrato sopra e compilarlo.

  • Crea il file sorgente ManageEmployee.java come mostrato sopra e compilarlo.

  • Esegui il binario ManageEmployee per eseguire il programma.

Si otterrebbe il seguente risultato e i record verranno creati nella tabella EMPLOYEE.

$java ManageEmployee
.......VARIOUS LOG MESSAGES WILL DISPLAY HERE........

First Name: Zara  Last Name: Ali  Salary: 1000
First Name: Daisy  Last Name: Das  Salary: 5000
First Name: John  Last Name: Paul  Salary: 10000
First Name: Zara  Last Name: Ali  Salary: 5000
First Name: John  Last Name: Paul  Salary: 10000

Se controlli la tua tabella EMPLOYEE, dovrebbe avere i seguenti record:

mysql> select * from EMPLOYEE;
+----+------------+-----------+--------+
| id | first_name | last_name | salary |
+----+------------+-----------+--------+
| 29 | Zara       | Ali       |   5000 |
| 31 | John       | Paul      |  10000 |
+----+------------+-----------+--------+
2 rows in set (0.00 sec

mysql>

Hibernate Query Language (HQL) è un linguaggio di query orientato agli oggetti, simile a SQL, ma invece di operare su tabelle e colonne, HQL lavora con oggetti persistenti e le loro proprietà. Le query HQL vengono tradotte da Hibernate in query SQL convenzionali, che a loro volta eseguono azioni sul database.

Sebbene sia possibile utilizzare le istruzioni SQL direttamente con Hibernate utilizzando Native SQL, consiglierei di utilizzare HQL quando possibile per evitare problemi di portabilità del database e per sfruttare le strategie di generazione e memorizzazione nella cache di Hibernate.

Parole chiave come SELECT, FROM e WHERE, ecc., Non fanno distinzione tra maiuscole e minuscole, ma proprietà come i nomi di tabelle e colonne sono sensibili al maiuscolo / minuscolo in HQL.

Clausola FROM

Userai FROMse si desidera caricare in memoria un oggetto persistente completo. Di seguito è riportata la semplice sintassi dell'utilizzo della clausola FROM:

String hql = "FROM Employee";
Query query = session.createQuery(hql);
List results = query.list();

Se è necessario qualificare completamente un nome di classe in HQL, è sufficiente specificare il pacchetto e il nome della classe come segue:

String hql = "FROM com.hibernatebook.criteria.Employee";
Query query = session.createQuery(hql);
List results = query.list();

Clausola AS

Il ASLa clausola può essere utilizzata per assegnare alias alle classi nelle query HQL, specialmente quando si hanno query lunghe. Ad esempio, il nostro semplice esempio precedente sarebbe il seguente:

String hql = "FROM Employee AS E";
Query query = session.createQuery(hql);
List results = query.list();

Il AS la parola chiave è facoltativa e puoi anche specificare l'alias direttamente dopo il nome della classe, come segue:

String hql = "FROM Employee E";
Query query = session.createQuery(hql);
List results = query.list();

Clausola SELECT

Il SELECTla clausola fornisce un maggiore controllo sul set di risultati rispetto alla clausola from. Se si desidera ottenere poche proprietà degli oggetti invece dell'oggetto completo, utilizzare la clausola SELECT. Di seguito è riportata la semplice sintassi dell'utilizzo della clausola SELECT per ottenere solo il campo first_name dell'oggetto Employee:

String hql = "SELECT E.firstName FROM Employee E";
Query query = session.createQuery(hql);
List results = query.list();

È notevole qui che Employee.firstName è una proprietà dell'oggetto Employee piuttosto che un campo della tabella EMPLOYEE.

Dove la clausola

Se si desidera restringere gli oggetti specifici restituiti dalla memoria, utilizzare la clausola WHERE. Di seguito è riportata la semplice sintassi dell'utilizzo della clausola WHERE:

String hql = "FROM Employee E WHERE E.id = 10";
Query query = session.createQuery(hql);
List results = query.list();

ORDER BY clausola

Per ordinare i risultati della tua query HQL, dovrai utilizzare il file ORDER BYclausola. È possibile ordinare i risultati in base a qualsiasi proprietà sugli oggetti nel set di risultati in ordine crescente (ASC) o decrescente (DESC). Di seguito è riportata la semplice sintassi dell'utilizzo della clausola ORDER BY:

String hql = "FROM Employee E WHERE E.id > 10 ORDER BY E.salary DESC";
Query query = session.createQuery(hql);
List results = query.list();

Se si desidera ordinare in base a più di una proprietà, è sufficiente aggiungere le proprietà aggiuntive alla fine della clausola order by, separate da virgole come segue:

String hql = "FROM Employee E WHERE E.id > 10 " +
             "ORDER BY E.firstName DESC, E.salary DESC ";
Query query = session.createQuery(hql);
List results = query.list();

Clausola GROUP BY

Questa clausola consente a Hibernate di estrarre informazioni dal database e raggrupparle in base a un valore di un attributo e, in genere, utilizzare il risultato per includere un valore aggregato. Di seguito è riportata la semplice sintassi dell'utilizzo della clausola GROUP BY:

String hql = "SELECT SUM(E.salary), E.firtName FROM Employee E " +
             "GROUP BY E.firstName";
Query query = session.createQuery(hql);
List results = query.list();

Utilizzo di parametri denominati

Hibernate supporta parametri denominati nelle sue query HQL. Ciò semplifica la scrittura di query HQL che accettano l'input dell'utente e non è necessario difendersi dagli attacchi di SQL injection. Di seguito è riportata la semplice sintassi dell'utilizzo di parametri denominati:

String hql = "FROM Employee E WHERE E.id = :employee_id";
Query query = session.createQuery(hql);
query.setParameter("employee_id",10);
List results = query.list();

Clausola UPDATE

Gli aggiornamenti in blocco sono nuovi per HQL con Hibernate 3 e l'eliminazione funziona in modo diverso in Hibernate 3 rispetto a Hibernate 2. L'interfaccia Query ora contiene un metodo chiamato executeUpdate () per eseguire istruzioni HQL UPDATE o DELETE.

Il UPDATEla clausola può essere utilizzata per aggiornare una o più proprietà di uno o più oggetti. Di seguito è riportata la semplice sintassi dell'utilizzo della clausola UPDATE:

String hql = "UPDATE Employee set salary = :salary "  + 
             "WHERE id = :employee_id";
Query query = session.createQuery(hql);
query.setParameter("salary", 1000);
query.setParameter("employee_id", 10);
int result = query.executeUpdate();
System.out.println("Rows affected: " + result);

Clausola DELETE

Il DELETEla clausola può essere utilizzata per eliminare uno o più oggetti. Di seguito è riportata la semplice sintassi dell'utilizzo della clausola DELETE:

String hql = "DELETE FROM Employee "  + 
             "WHERE id = :employee_id";
Query query = session.createQuery(hql);
query.setParameter("employee_id", 10);
int result = query.executeUpdate();
System.out.println("Rows affected: " + result);

Clausola INSERT

Supporta HQL INSERT INTOclausola solo dove i record possono essere inseriti da un oggetto a un altro oggetto. Di seguito è riportata la semplice sintassi dell'utilizzo della clausola INSERT INTO:

String hql = "INSERT INTO Employee(firstName, lastName, salary)"  + 
             "SELECT firstName, lastName, salary FROM old_employee";
Query query = session.createQuery(hql);
int result = query.executeUpdate();
System.out.println("Rows affected: " + result);

Metodi aggregati

HQL supporta una gamma di metodi aggregati, simili a SQL. Funzionano allo stesso modo in HQL come in SQL e di seguito è riportato l'elenco delle funzioni disponibili:

Sr.No. Funzioni e descrizione
1

avg(property name)

La media del valore di una proprietà

2

count(property name or *)

Il numero di volte in cui una proprietà si verifica nei risultati

3

max(property name)

Il valore massimo dei valori della proprietà

4

min(property name)

Il valore minimo dei valori della proprietà

5

sum(property name)

La somma totale dei valori della proprietà

Il distinctparola chiave conta solo i valori univoci nella serie di righe. La seguente query restituirà solo un conteggio univoco -

String hql = "SELECT count(distinct E.firstName) FROM Employee E";
Query query = session.createQuery(hql);
List results = query.list();

Impaginazione tramite Query

Esistono due metodi dell'interfaccia Query per l'impaginazione.

Sr.No. Metodo e descrizione
1

Query setFirstResult(int startPosition)

Questo metodo accetta un numero intero che rappresenta la prima riga del set di risultati, a partire dalla riga 0.

2

Query setMaxResults(int maxResult)

Questo metodo dice a Hibernate di recuperare un numero fisso maxResults di oggetti.

Usando insieme i due metodi precedenti, possiamo costruire un componente di paging nella nostra applicazione web o Swing. Di seguito è riportato l'esempio, che puoi estendere per recuperare 10 righe alla volta:

String hql = "FROM Employee";
Query query = session.createQuery(hql);
query.setFirstResult(1);
query.setMaxResults(10);
List results = query.list();

Hibernate fornisce modi alternativi di manipolare gli oggetti e, a sua volta, i dati disponibili nelle tabelle RDBMS. Uno dei metodi è Criteria API, che consente di creare un oggetto query di criteri a livello di codice in cui è possibile applicare regole di filtro e condizioni logiche.

L'ibernazione Session l'interfaccia fornisce createCriteria() metodo, che può essere utilizzato per creare un file Criteria oggetto che restituisce istanze della classe dell'oggetto di persistenza quando l'applicazione esegue una query di criteri.

Di seguito è riportato l'esempio più semplice di una query di criteri è uno, che restituirà semplicemente ogni oggetto che corrisponde alla classe Employee.

Criteria cr = session.createCriteria(Employee.class);
List results = cr.list();

Restrizioni con criteri

Puoi usare add() metodo disponibile per Criteriaoggetto per aggiungere restrizione per una query di criteri. Di seguito è riportato l'esempio per aggiungere una restrizione per restituire i record con lo stipendio è uguale a 2000 -

Criteria cr = session.createCriteria(Employee.class);
cr.add(Restrictions.eq("salary", 2000));
List results = cr.list();

Di seguito sono riportati alcuni altri esempi che coprono diversi scenari e possono essere utilizzati secondo il requisito:

Criteria cr = session.createCriteria(Employee.class);

// To get records having salary more than 2000
cr.add(Restrictions.gt("salary", 2000));

// To get records having salary less than 2000
cr.add(Restrictions.lt("salary", 2000));

// To get records having fistName starting with zara
cr.add(Restrictions.like("firstName", "zara%"));

// Case sensitive form of the above restriction.
cr.add(Restrictions.ilike("firstName", "zara%"));

// To get records having salary in between 1000 and 2000
cr.add(Restrictions.between("salary", 1000, 2000));

// To check if the given property is null
cr.add(Restrictions.isNull("salary"));

// To check if the given property is not null
cr.add(Restrictions.isNotNull("salary"));

// To check if the given property is empty
cr.add(Restrictions.isEmpty("salary"));

// To check if the given property is not empty
cr.add(Restrictions.isNotEmpty("salary"));

È possibile creare condizioni AND o OR utilizzando le restrizioni di LogicalExpression come segue:

Criteria cr = session.createCriteria(Employee.class);

Criterion salary = Restrictions.gt("salary", 2000);
Criterion name = Restrictions.ilike("firstNname","zara%");

// To get records matching with OR conditions
LogicalExpression orExp = Restrictions.or(salary, name);
cr.add( orExp );

// To get records matching with AND conditions
LogicalExpression andExp = Restrictions.and(salary, name);
cr.add( andExp );

List results = cr.list();

Sebbene tutte le condizioni di cui sopra possono essere utilizzate direttamente con HQL come spiegato nel tutorial precedente.

Impaginazione utilizzando criteri

Esistono due metodi dell'interfaccia Criteria per l'impaginazione.

Sr.No. Metodo e descrizione
1

public Criteria setFirstResult(int firstResult)

Questo metodo accetta un numero intero che rappresenta la prima riga del set di risultati, a partire dalla riga 0.

2

public Criteria setMaxResults(int maxResults)

Questo metodo dice a Hibernate di recuperare un numero fisso maxResults di oggetti.

Usando insieme i due metodi precedenti, possiamo costruire un componente di paging nella nostra applicazione web o Swing. Di seguito è riportato l'esempio, che puoi estendere per recuperare 10 righe alla volta:

Criteria cr = session.createCriteria(Employee.class);
cr.setFirstResult(1);
cr.setMaxResults(10);
List results = cr.list();

Ordinamento dei risultati

L'API Criteria fornisce l'estensione org.hibernate.criterion.Orderclass per ordinare il set di risultati in ordine crescente o decrescente, in base a una delle proprietà dell'oggetto. Questo esempio dimostra come useresti la classe Order per ordinare il set di risultati:

Criteria cr = session.createCriteria(Employee.class);

// To get records having salary more than 2000
cr.add(Restrictions.gt("salary", 2000));

// To sort records in descening order
cr.addOrder(Order.desc("salary"));

// To sort records in ascending order
cr.addOrder(Order.asc("salary"));

List results = cr.list();

Proiezioni e aggregazioni

L'API Criteria fornisce l'estensione org.hibernate.criterion.Projectionsclass, che può essere utilizzato per ottenere la media, il massimo o il minimo dei valori di proprietà. La classe Projections è simile alla classe Restrictions, in quanto fornisce diversi metodi factory statici per ottenereProjection istanze.

Di seguito sono riportati alcuni esempi che coprono diversi scenari e possono essere utilizzati secondo i requisiti:

Criteria cr = session.createCriteria(Employee.class);

// To get total row count.
cr.setProjection(Projections.rowCount());

// To get average of a property.
cr.setProjection(Projections.avg("salary"));

// To get distinct count of a property.
cr.setProjection(Projections.countDistinct("firstName"));

// To get maximum of a property.
cr.setProjection(Projections.max("salary"));

// To get minimum of a property.
cr.setProjection(Projections.min("salary"));

// To get sum of a property.
cr.setProjection(Projections.sum("salary"));

Esempio di query sui criteri

Considera la seguente classe POJO:

public class Employee {
   private int id;
   private String firstName; 
   private String lastName;   
   private int salary;  

   public Employee() {}
   
   public Employee(String fname, String lname, int salary) {
      this.firstName = fname;
      this.lastName = lname;
      this.salary = salary;
   }
   
   public int getId() {
      return id;
   }
   
   public void setId( int id ) {
      this.id = id;
   }
   
   public String getFirstName() {
      return firstName;
   }
   
   public void setFirstName( String first_name ) {
      this.firstName = first_name;
   }
   
   public String getLastName() {
      return lastName;
   }
   
   public void setLastName( String last_name ) {
      this.lastName = last_name;
   }
   
   public int getSalary() {
      return salary;
   }
   
   public void setSalary( int salary ) {
      this.salary = salary;
   }
}

Creiamo la seguente tabella EMPLOYEE per memorizzare gli oggetti Employee:

create table EMPLOYEE (
   id INT NOT NULL auto_increment,
   first_name VARCHAR(20) default NULL,
   last_name  VARCHAR(20) default NULL,
   salary     INT  default NULL,
   PRIMARY KEY (id)
);

Di seguito sarà il file di mappatura.

<?xml version = "1.0" encoding = "utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC 
"-//Hibernate/Hibernate Mapping DTD//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> 

<hibernate-mapping>
   <class name = "Employee" table = "EMPLOYEE">
      
      <meta attribute = "class-description">
         This class contains the employee detail. 
      </meta>
      
      <id name = "id" type = "int" column = "id">
         <generator class="native"/>
      </id>
      
      <property name = "firstName" column = "first_name" type = "string"/>
      <property name = "lastName" column = "last_name" type = "string"/>
      <property name = "salary" column = "salary" type = "int"/>
      
   </class>
</hibernate-mapping>

Infine, creeremo la nostra classe applicativa con il metodo main () per eseguire l'applicazione che useremo Criteria domande -

import java.util.List; 
import java.util.Date;
import java.util.Iterator; 
 
import org.hibernate.HibernateException; 
import org.hibernate.Session; 
import org.hibernate.Transaction;
import org.hibernate.SessionFactory;
import org.hibernate.Criteria;
import org.hibernate.criterion.Restrictions;
import org.hibernate.criterion.Projections;
import org.hibernate.cfg.Configuration;

public class ManageEmployee {
   private static SessionFactory factory; 
   public static void main(String[] args) {
      
      try {
         factory = new Configuration().configure().buildSessionFactory();
      } catch (Throwable ex) { 
         System.err.println("Failed to create sessionFactory object." + ex);
         throw new ExceptionInInitializerError(ex); 
      }
      
      ManageEmployee ME = new ManageEmployee();

      /* Add few employee records in database */
      Integer empID1 = ME.addEmployee("Zara", "Ali", 2000);
      Integer empID2 = ME.addEmployee("Daisy", "Das", 5000);
      Integer empID3 = ME.addEmployee("John", "Paul", 5000);
      Integer empID4 = ME.addEmployee("Mohd", "Yasee", 3000);

      /* List down all the employees */
      ME.listEmployees();

      /* Print Total employee's count */
      ME.countEmployee();

      /* Print Total salary */
      ME.totalSalary();
   }
   
   /* Method to CREATE an employee in the database */
   public Integer addEmployee(String fname, String lname, int salary){
      Session session = factory.openSession();
      Transaction tx = null;
      Integer employeeID = null;
      
      try {
         tx = session.beginTransaction();
         Employee employee = new Employee(fname, lname, salary);
         employeeID = (Integer) session.save(employee); 
         tx.commit();
      } catch (HibernateException e) {
         if (tx!=null) tx.rollback();
         e.printStackTrace(); 
      } finally {
         session.close(); 
      }
      return employeeID;
   }

   /* Method to  READ all the employees having salary more than 2000 */
   public void listEmployees( ) {
      Session session = factory.openSession();
      Transaction tx = null;
      
      try {
         tx = session.beginTransaction();
         Criteria cr = session.createCriteria(Employee.class);
         // Add restriction.
         cr.add(Restrictions.gt("salary", 2000));
         List employees = cr.list();

         for (Iterator iterator = employees.iterator(); iterator.hasNext();){
            Employee employee = (Employee) iterator.next(); 
            System.out.print("First Name: " + employee.getFirstName()); 
            System.out.print("  Last Name: " + employee.getLastName()); 
            System.out.println("  Salary: " + employee.getSalary()); 
         }
         tx.commit();
      } catch (HibernateException e) {
         if (tx!=null) tx.rollback();
         e.printStackTrace(); 
      } finally {
         session.close(); 
      }
   }
   
   /* Method to print total number of records */
   public void countEmployee(){
      Session session = factory.openSession();
      Transaction tx = null;
      
      try {
         tx = session.beginTransaction();
         Criteria cr = session.createCriteria(Employee.class);

         // To get total row count.
         cr.setProjection(Projections.rowCount());
         List rowCount = cr.list();

         System.out.println("Total Coint: " + rowCount.get(0) );
         tx.commit();
      } catch (HibernateException e) {
         if (tx!=null) tx.rollback();
         e.printStackTrace(); 
      } finally {
         session.close(); 
      }
   }
  
   /* Method to print sum of salaries */
   public void totalSalary(){
      Session session = factory.openSession();
      Transaction tx = null;
      
      try {
         tx = session.beginTransaction();
         Criteria cr = session.createCriteria(Employee.class);

         // To get total salary.
         cr.setProjection(Projections.sum("salary"));
         List totalSalary = cr.list();

         System.out.println("Total Salary: " + totalSalary.get(0) );
         tx.commit();
      } catch (HibernateException e) {
         if (tx!=null) tx.rollback();
         e.printStackTrace(); 
      } finally {
         session.close(); 
      }
   }
}

Compilazione ed esecuzione

Ecco i passaggi per compilare ed eseguire l'applicazione sopra menzionata. Assicurati di aver impostato PATH e CLASSPATH in modo appropriato prima di procedere per la compilazione e l'esecuzione.

  • Creare il file di configurazione hibernate.cfg.xml come spiegato nel capitolo sulla configurazione.

  • Crea il file di mappatura Employee.hbm.xml come mostrato sopra.

  • Crea il file sorgente Employee.java come mostrato sopra e compilarlo.

  • Crea il file sorgente ManageEmployee.java come mostrato sopra e compilarlo.

  • Esegui il binario ManageEmployee per eseguire il programma.

Si otterrebbe il seguente risultato e i record verranno creati nella tabella EMPLOYEE.

$java ManageEmployee
.......VARIOUS LOG MESSAGES WILL DISPLAY HERE........

First Name: Daisy  Last Name: Das  Salary: 5000
First Name: John  Last Name: Paul  Salary: 5000
First Name: Mohd  Last Name: Yasee  Salary: 3000
Total Coint: 4
Total Salary: 15000

Se controlli la tua tabella EMPLOYEE, dovrebbe avere i seguenti record:

mysql> select * from EMPLOYEE;
+----+------------+-----------+--------+
| id | first_name | last_name | salary |
+----+------------+-----------+--------+
| 14 | Zara       | Ali       |   2000 |
| 15 | Daisy      | Das       |   5000 |
| 16 | John       | Paul      |   5000 |
| 17 | Mohd       | Yasee     |   3000 |
+----+------------+-----------+--------+
4 rows in set (0.00 sec)
mysql>

È possibile utilizzare SQL nativo per esprimere query del database se si desidera utilizzare funzionalità specifiche del database come i suggerimenti per le query o la parola chiave CONNECT in Oracle. Hibernate 3.x consente di specificare l'SQL scritto a mano, incluse le procedure memorizzate, per tutte le operazioni di creazione, aggiornamento, eliminazione e caricamento.

L'applicazione creerà una query SQL nativa dalla sessione con l'estensione createSQLQuery() metodo sull'interfaccia Session -

public SQLQuery createSQLQuery(String sqlString) throws HibernateException

Dopo aver passato una stringa contenente la query SQL al metodo createSQLQuery (), puoi associare il risultato SQL a un'entità Hibernate esistente, un join o un risultato scalare utilizzando i metodi addEntity (), addJoin () e addScalar () rispettivamente.

Query scalari

La query SQL più semplice consiste nell'ottenere un elenco di scalari (valori) da una o più tabelle. Di seguito è riportata la sintassi per l'utilizzo di SQL nativo per i valori scalari:

String sql = "SELECT first_name, salary FROM EMPLOYEE";
SQLQuery query = session.createSQLQuery(sql);
query.setResultTransformer(Criteria.ALIAS_TO_ENTITY_MAP);
List results = query.list();

Query di entità

Le query precedenti riguardavano la restituzione di valori scalari, sostanzialmente la restituzione dei valori "grezzi" dal set di risultati. Di seguito è riportata la sintassi per ottenere gli oggetti entità nel loro insieme da una query sql nativa tramite addEntity ().

String sql = "SELECT * FROM EMPLOYEE";
SQLQuery query = session.createSQLQuery(sql);
query.addEntity(Employee.class);
List results = query.list();

Query SQL con nome

Di seguito è riportata la sintassi per ottenere oggetti entità da una query sql nativa tramite addEntity () e utilizzando una query SQL denominata.

String sql = "SELECT * FROM EMPLOYEE WHERE id = :employee_id";
SQLQuery query = session.createSQLQuery(sql);
query.addEntity(Employee.class);
query.setParameter("employee_id", 10);
List results = query.list();

Esempio SQL nativo

Considera la seguente classe POJO:

public class Employee {
   private int id;
   private String firstName; 
   private String lastName;   
   private int salary;  

   public Employee() {}
   
   public Employee(String fname, String lname, int salary) {
      this.firstName = fname;
      this.lastName = lname;
      this.salary = salary;
   }
   
   public int getId() {
      return id;
   }
   
   public void setId( int id ) {
      this.id = id;
   }
   
   public String getFirstName() {
      return firstName;
   }
   
   public void setFirstName( String first_name ) {
      this.firstName = first_name;
   }
   
   public String getLastName() {
      return lastName;
   }
   
   public void setLastName( String last_name ) {
      this.lastName = last_name;
   }
   
   public int getSalary() {
      return salary;
   }
   
   public void setSalary( int salary ) {
      this.salary = salary;
   }
}

Creiamo la seguente tabella EMPLOYEE per memorizzare gli oggetti Employee:

create table EMPLOYEE (
   id INT NOT NULL auto_increment,
   first_name VARCHAR(20) default NULL,
   last_name  VARCHAR(20) default NULL,
   salary     INT  default NULL,
   PRIMARY KEY (id)
);

Di seguito sarà il file di mappatura -

<?xml version = "1.0" encoding = "utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC 
"-//Hibernate/Hibernate Mapping DTD//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> 

<hibernate-mapping>
   <class name = "Employee" table = "EMPLOYEE">
      
      <meta attribute = "class-description">
         This class contains the employee detail. 
      </meta>
      
      <id name = "id" type = "int" column = "id">
         <generator class="native"/>
      </id>
      
      <property name = "firstName" column = "first_name" type = "string"/>
      <property name = "lastName" column = "last_name" type = "string"/>
      <property name = "salary" column = "salary" type = "int"/>
      
   </class>
</hibernate-mapping>

Infine, creeremo la nostra classe applicativa con il metodo main () per eseguire l'applicazione che useremo Native SQL domande -

import java.util.*; 
 
import org.hibernate.HibernateException; 
import org.hibernate.Session; 
import org.hibernate.Transaction;
import org.hibernate.SessionFactory;
import org.hibernate.SQLQuery;
import org.hibernate.Criteria;
import org.hibernate.Hibernate;
import org.hibernate.cfg.Configuration;

public class ManageEmployee {
   private static SessionFactory factory; 
   public static void main(String[] args) {
      
      try {
         factory = new Configuration().configure().buildSessionFactory();
      } catch (Throwable ex) { 
         System.err.println("Failed to create sessionFactory object." + ex);
         throw new ExceptionInInitializerError(ex); 
      }
      
      ManageEmployee ME = new ManageEmployee();

      /* Add few employee records in database */
      Integer empID1 = ME.addEmployee("Zara", "Ali", 2000);
      Integer empID2 = ME.addEmployee("Daisy", "Das", 5000);
      Integer empID3 = ME.addEmployee("John", "Paul", 5000);
      Integer empID4 = ME.addEmployee("Mohd", "Yasee", 3000);

      /* List down employees and their salary using Scalar Query */
      ME.listEmployeesScalar();

      /* List down complete employees information using Entity Query */
      ME.listEmployeesEntity();
   }
   
   /* Method to CREATE an employee in the database */
   public Integer addEmployee(String fname, String lname, int salary){
      Session session = factory.openSession();
      Transaction tx = null;
      Integer employeeID = null;
      
      try {
         tx = session.beginTransaction();
         Employee employee = new Employee(fname, lname, salary);
         employeeID = (Integer) session.save(employee); 
         tx.commit();
      } catch (HibernateException e) {
         if (tx!=null) tx.rollback();
         e.printStackTrace(); 
      } finally {
         session.close(); 
      }
      return employeeID;
   }

   /* Method to  READ all the employees using Scalar Query */
   public void listEmployeesScalar( ){
      Session session = factory.openSession();
      Transaction tx = null;
      
      try {
         tx = session.beginTransaction();
         String sql = "SELECT first_name, salary FROM EMPLOYEE";
         SQLQuery query = session.createSQLQuery(sql);
         query.setResultTransformer(Criteria.ALIAS_TO_ENTITY_MAP);
         List data = query.list();

         for(Object object : data) {
            Map row = (Map)object;
            System.out.print("First Name: " + row.get("first_name")); 
            System.out.println(", Salary: " + row.get("salary")); 
         }
         tx.commit();
      } catch (HibernateException e) {
         if (tx!=null) tx.rollback();
         e.printStackTrace(); 
      } finally {
         session.close(); 
      }
   }

   /* Method to READ all the employees using Entity Query */
   public void listEmployeesEntity( ){
      Session session = factory.openSession();
      Transaction tx = null;
      
      try {
         tx = session.beginTransaction();
         String sql = "SELECT * FROM EMPLOYEE";
         SQLQuery query = session.createSQLQuery(sql);
         query.addEntity(Employee.class);
         List employees = query.list();

         for (Iterator iterator = employees.iterator(); iterator.hasNext();){
            Employee employee = (Employee) iterator.next(); 
            System.out.print("First Name: " + employee.getFirstName()); 
            System.out.print("  Last Name: " + employee.getLastName()); 
            System.out.println("  Salary: " + employee.getSalary()); 
         }
         tx.commit();
      } catch (HibernateException e) {
         if (tx!=null) tx.rollback();
         e.printStackTrace(); 
      } finally {
         session.close(); 
      }
   }
}

Compilazione ed esecuzione

Ecco i passaggi per compilare ed eseguire l'applicazione sopra menzionata. Assicurati di aver impostato PATH e CLASSPATH in modo appropriato prima di procedere per la compilazione e l'esecuzione.

  • Creare il file di configurazione hibernate.cfg.xml come spiegato nel capitolo sulla configurazione.

  • Crea il file di mappatura Employee.hbm.xml come mostrato sopra.

  • Crea il file sorgente Employee.java come mostrato sopra e compilarlo.

  • Crea il file sorgente ManageEmployee.java come mostrato sopra e compilarlo.

  • Esegui il binario ManageEmployee per eseguire il programma.

Si otterrebbe il seguente risultato e i record verranno creati nella tabella EMPLOYEE.

$java ManageEmployee
.......VARIOUS LOG MESSAGES WILL DISPLAY HERE........

First Name: Zara, Salary: 2000
First Name: Daisy, Salary: 5000
First Name: John, Salary: 5000
First Name: Mohd, Salary: 3000
First Name: Zara  Last Name: Ali  Salary: 2000
First Name: Daisy  Last Name: Das  Salary: 5000
First Name: John  Last Name: Paul  Salary: 5000
First Name: Mohd  Last Name: Yasee  Salary: 3000

Se controlli la tua tabella EMPLOYEE, dovrebbe avere i seguenti record:

mysql> select * from EMPLOYEE;
+----+------------+-----------+--------+
| id | first_name | last_name | salary |
+----+------------+-----------+--------+
| 26 | Zara       | Ali       |   2000 |
| 27 | Daisy      | Das       |   5000 |
| 28 | John       | Paul      |   5000 |
| 29 | Mohd       | Yasee     |   3000 |
+----+------------+-----------+--------+
4 rows in set (0.00 sec)
mysql>

La memorizzazione nella cache è un meccanismo per migliorare le prestazioni di un sistema. È una memoria buffer che si trova tra l'applicazione e il database. La memoria cache memorizza gli elementi di dati utilizzati di recente per ridurre il più possibile il numero di accessi al database.

La memorizzazione nella cache è importante anche per Hibernate. Utilizza uno schema di memorizzazione nella cache multilivello come spiegato di seguito:

Cache di primo livello

La cache di primo livello è la cache di sessione ed è una cache obbligatoria attraverso la quale devono passare tutte le richieste. L'oggetto Session mantiene un oggetto sotto il proprio potere prima di inviarlo al database.

Se si emettono più aggiornamenti a un oggetto, Hibernate tenta di ritardare l'esecuzione dell'aggiornamento il più a lungo possibile per ridurre il numero di istruzioni SQL di aggiornamento emesse. Se si chiude la sessione, tutti gli oggetti memorizzati nella cache vengono persi e vengono mantenuti o aggiornati nel database.

Cache di secondo livello

La cache di secondo livello è una cache opzionale e la cache di primo livello verrà sempre consultata prima di tentare di individuare un oggetto nella cache di secondo livello. La cache di secondo livello può essere configurata per classe e per raccolta ed è principalmente responsabile della memorizzazione nella cache degli oggetti tra le sessioni.

Qualsiasi cache di terze parti può essere utilizzata con Hibernate. Unorg.hibernate.cache.CacheProvider viene fornita l'interfaccia, che deve essere implementata per fornire a Hibernate un handle per l'implementazione della cache.

Cache a livello di query

Hibernate implementa anche una cache per i set di risultati delle query che si integra strettamente con la cache di secondo livello.

Si tratta di una funzionalità facoltativa e richiede due aree cache fisiche aggiuntive che contengono i risultati delle query memorizzate nella cache e i timestamp dell'ultimo aggiornamento di una tabella. Ciò è utile solo per le query eseguite di frequente con gli stessi parametri.

La cache di secondo livello

Hibernate utilizza la cache di primo livello per impostazione predefinita e non devi fare nulla per utilizzare la cache di primo livello. Andiamo direttamente alla cache di secondo livello opzionale. Non tutte le classi traggono vantaggio dalla memorizzazione nella cache, quindi è importante essere in grado di disabilitare la cache di secondo livello.

La cache di secondo livello di Hibernate viene configurata in due passaggi. Innanzitutto, devi decidere quale strategia di concorrenza utilizzare. Successivamente, configurare la scadenza della cache e gli attributi della cache fisica utilizzando il provider della cache.

Strategie di concorrenza

Una strategia di concorrenza è un mediatore, responsabile dell'archiviazione di elementi di dati nella cache e del loro recupero dalla cache. Se si intende abilitare una cache di secondo livello, sarà necessario decidere, per ciascuna classe e raccolta persistente, quale strategia di concorrenza della cache utilizzare.

  • Transactional - Utilizzare questa strategia per i dati per lo più di lettura in cui è fondamentale prevenire dati obsoleti nelle transazioni simultanee, nel raro caso di un aggiornamento.

  • Read-write - Usa ancora questa strategia per i dati per lo più in lettura, dove è fondamentale prevenire dati obsoleti nelle transazioni simultanee, nel raro caso di un aggiornamento.

  • Nonstrict-read-write- Questa strategia non garantisce la coerenza tra la cache e il database. Utilizzare questa strategia se i dati non cambiano quasi mai e una piccola probabilità di dati obsoleti non è di fondamentale importanza.

  • Read-only- Una strategia di concorrenza adatta ai dati, che non cambia mai. Usalo solo per i dati di riferimento.

Se utilizzeremo la memorizzazione nella cache di secondo livello per il nostro file Employee class, aggiungiamo l'elemento di mappatura richiesto per dire a Hibernate di memorizzare nella cache le istanze Employee utilizzando la strategia di lettura-scrittura.

<?xml version = "1.0" encoding = "utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC 
"-//Hibernate/Hibernate Mapping DTD//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> 
<hibernate-mapping>
   <class name = "Employee" table = "EMPLOYEE">
      
      <meta attribute = "class-description">
         This class contains the employee detail. 
      </meta>
      
      <cache usage = "read-write"/>
      
      <id name = "id" type = "int" column = "id">
         <generator class="native"/>
      </id>
      
      <property name = "firstName" column = "first_name" type = "string"/>
      <property name = "lastName" column = "last_name" type = "string"/>
      <property name = "salary" column = "salary" type = "int"/>
      
   </class>
</hibernate-mapping>

L'attributo usage = "read-write" indica a Hibernate di utilizzare una strategia di concorrenza di lettura-scrittura per la cache definita.

Provider di cache

Il passaggio successivo dopo aver considerato le strategie di concorrenza, utilizzerai le classi candidate alla cache per scegliere un provider di cache. Hibernate ti obbliga a scegliere un unico provider di cache per l'intera applicazione.

Sr.No. Nome e descrizione cache
1

EHCache

Può memorizzare nella cache o su disco e la cache in cluster e supporta la cache dei risultati della query Hibernate opzionale.

2

OSCache

Supporta la memorizzazione nella cache su memoria e disco in una singola JVM con un ricco set di criteri di scadenza e supporto per la cache delle query.

3

warmCache

Una cache del cluster basata su JGroups. Utilizza l'invalidazione in cluster, ma non supporta la cache delle query di Hibernate.

4

JBoss Cache

Una cache cluster replicata completamente transazionale anche basata sulla libreria multicast JGroups. Supporta la replica o l'invalidazione, la comunicazione sincrona o asincrona e il blocco ottimistico e pessimistico. La cache delle query di Hibernate è supportata.

Ogni provider di cache non è compatibile con tutte le strategie di concorrenza. La seguente matrice di compatibilità ti aiuterà a scegliere una combinazione appropriata.

Strategia / fornitore Sola lettura Nonstrictread-write Leggere scrivere Transazionale
EHCache X X X  
OSCache X X X  
SwarmCache X X    
JBoss Cache X     X

Specifichi un provider di cache nel file di configurazione hibernate.cfg.xml. Scegliamo EHCache come nostro provider di cache di secondo livello -

<?xml version = "1.0" encoding = "utf-8"?>
<!DOCTYPE hibernate-configuration SYSTEM 
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
   <session-factory>
   
      <property name = "hibernate.dialect">
         org.hibernate.dialect.MySQLDialect
      </property>
   
      <property name = "hibernate.connection.driver_class">
         com.mysql.jdbc.Driver
      </property>
   
      <!-- Assume students is the database name -->
   
      <property name = "hibernate.connection.url">
         jdbc:mysql://localhost/test
      </property>
   
      <property name = "hibernate.connection.username">
         root
      </property>
   
      <property name = "hibernate.connection.password">
         root123
      </property>
   
      <property name = "hibernate.cache.provider_class">
         org.hibernate.cache.EhCacheProvider
      </property>
   
      <!-- List of XML mapping files -->
      <mapping resource = "Employee.hbm.xml"/>
   
   </session-factory>
</hibernate-configuration>

Ora è necessario specificare le proprietà delle regioni della cache. EHCache ha il proprio file di configurazione,ehcache.xml, che dovrebbe trovarsi nel CLASSPATH dell'applicazione. Una configurazione della cache in ehcache.xml per la classe Employee potrebbe essere simile a questa:

<diskStore path="java.io.tmpdir"/>

<defaultCache
maxElementsInMemory = "1000"
eternal = "false"
timeToIdleSeconds = "120"
timeToLiveSeconds = "120"
overflowToDisk = "true"
/>

<cache name = "Employee"
maxElementsInMemory = "500"
eternal = "true"
timeToIdleSeconds = "0"
timeToLiveSeconds = "0"
overflowToDisk = "false"
/>

Ecco fatto, ora abbiamo la cache di secondo livello abilitata per la classe Employee e Hibernate, ora colpisce la cache di secondo livello ogni volta che navighi su un dipendente o quando carichi un dipendente per identificatore.

È necessario analizzare tutte le classi e scegliere la strategia di memorizzazione nella cache appropriata per ciascuna delle classi. A volte, la memorizzazione nella cache di secondo livello può ridurre le prestazioni dell'applicazione. Pertanto, si consiglia di eseguire prima il benchmark della tua applicazione, senza abilitare la memorizzazione nella cache e successivamente abilitare la memorizzazione nella cache adatta e controllare le prestazioni. Se la memorizzazione nella cache non migliora le prestazioni del sistema, non ha senso abilitare alcun tipo di memorizzazione nella cache.

La cache a livello di query

Per utilizzare la cache delle query, è necessario prima attivarla utilizzando il hibernate.cache.use_query_cache="true"proprietà nel file di configurazione. Impostando questa proprietà su true, fai in modo che Hibernate crei le cache necessarie in memoria per contenere le serie di query e identificatori.

Successivamente, per utilizzare la cache delle query, si utilizza il metodo setCacheable (Boolean) della classe Query. Ad esempio:

Session session = SessionFactory.openSession();
Query query = session.createQuery("FROM EMPLOYEE");
query.setCacheable(true);
List users = query.list();
SessionFactory.closeSession();

Hibernate supporta anche il supporto della cache a grana molto fine attraverso il concetto di una regione della cache. Una regione della cache fa parte della cache a cui è stato assegnato un nome.

Session session = SessionFactory.openSession();
Query query = session.createQuery("FROM EMPLOYEE");
query.setCacheable(true);
query.setCacheRegion("employee");
List users = query.list();
SessionFactory.closeSession();

Questo codice utilizza il metodo per dire a Hibernate di memorizzare e cercare la query nell'area dei dipendenti della cache.

Considera una situazione in cui devi caricare un gran numero di record nel tuo database utilizzando Hibernate. Di seguito è riportato lo snippet di codice per ottenere ciò utilizzando Hibernate -

Session session = SessionFactory.openSession();
Transaction tx = session.beginTransaction();
for ( int i=0; i<100000; i++ ) {
   Employee employee = new Employee(.....);
   session.save(employee);
}
tx.commit();
session.close();

Per impostazione predefinita, Hibernate memorizzerà nella cache tutti gli oggetti persistenti nella cache a livello di sessione e alla fine la tua applicazione cadrà con un OutOfMemoryExceptionda qualche parte intorno alla 50.000esima fila. Puoi risolvere questo problema, se stai usandobatch processing con Hibernate.

Per utilizzare la funzione di elaborazione batch, prima impostare hibernate.jdbc.batch_sizecome dimensione batch a un numero di 20 o 50 a seconda delle dimensioni dell'oggetto. Questo dirà al contenitore di ibernazione che ogni X righe deve essere inserita come batch. Per implementarlo nel tuo codice, avremmo bisogno di apportare piccole modifiche come segue:

Session session = SessionFactory.openSession();
Transaction tx = session.beginTransaction();
for ( int i=0; i<100000; i++ ) {
   Employee employee = new Employee(.....);
   session.save(employee);
   if( i % 50 == 0 ) { // Same as the JDBC batch size
      //flush a batch of inserts and release memory:
      session.flush();
      session.clear();
   }
}
tx.commit();
session.close();

Il codice sopra funzionerà correttamente per l'operazione INSERT, ma se si desidera eseguire l'operazione UPDATE, è possibile ottenere utilizzando il codice seguente:

Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();

ScrollableResults employeeCursor = session.createQuery("FROM EMPLOYEE").scroll();
int count = 0;

while ( employeeCursor.next() ) {
   Employee employee = (Employee) employeeCursor.get(0);
   employee.updateEmployee();
   seession.update(employee); 
   if ( ++count % 50 == 0 ) {
      session.flush();
      session.clear();
   }
}
tx.commit();
session.close();

Esempio di elaborazione in batch

Modifichiamo il file di configurazione da aggiungere hibernate.jdbc.batch_size proprietà -

<?xml version = "1.0" encoding = "utf-8"?>
<!DOCTYPE hibernate-configuration SYSTEM 
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">

<hibernate-configuration>
   <session-factory>
   
      <property name = "hibernate.dialect">
         org.hibernate.dialect.MySQLDialect
      </property>
   
      <property name = "hibernate.connection.driver_class">
         com.mysql.jdbc.Driver
      </property>

      <!-- Assume students is the database name -->
   
      <property name = "hibernate.connection.url">
         jdbc:mysql://localhost/test
      </property>
   
      <property name = "hibernate.connection.username">
         root
      </property>
   
      <property name = "hibernate.connection.password">
         root123
      </property>
   
      <property name = "hibernate.jdbc.batch_size">
         50
      </property>

      <!-- List of XML mapping files -->
      <mapping resource = "Employee.hbm.xml"/>

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

Considera la seguente classe POJO Employee:

public class Employee {
   private int id;
   private String firstName; 
   private String lastName;   
   private int salary;  

   public Employee() {}
   
   public Employee(String fname, String lname, int salary) {
      this.firstName = fname;
      this.lastName = lname;
      this.salary = salary;
   }
   
   public int getId() {
      return id;
   }
   
   public void setId( int id ) {
      this.id = id;
   }
   
   public String getFirstName() {
      return firstName;
   }
   
   public void setFirstName( String first_name ) {
      this.firstName = first_name;
   }
   
   public String getLastName() {
      return lastName;
   }
   
   public void setLastName( String last_name ) {
      this.lastName = last_name;
   }
   
   public int getSalary() {
      return salary;
   }
   
   public void setSalary( int salary ) {
      this.salary = salary;
   }
}

Creiamo la seguente tabella EMPLOYEE per memorizzare gli oggetti Employee:

create table EMPLOYEE (
   id INT NOT NULL auto_increment,
   first_name VARCHAR(20) default NULL,
   last_name  VARCHAR(20) default NULL,
   salary     INT  default NULL,
   PRIMARY KEY (id)
);

Di seguito sarà il file di mappatura per mappare gli oggetti Employee con la tabella EMPLOYEE -

<?xml version = "1.0" encoding = "utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC 
"-//Hibernate/Hibernate Mapping DTD//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> 

<hibernate-mapping>
   <class name = "Employee" table = "EMPLOYEE">
      
      <meta attribute = "class-description">
         This class contains the employee detail. 
      </meta>
      
      <id name = "id" type = "int" column = "id">
         <generator class="native"/>
      </id>
      
      <property name = "firstName" column = "first_name" type = "string"/>
      <property name = "lastName" column = "last_name" type = "string"/>
      <property name = "salary" column = "salary" type = "int"/>
      
   </class>
</hibernate-mapping>

Infine, creeremo la nostra classe applicativa con il metodo main () per eseguire l'applicazione che useremo flush() e clear() metodi disponibili con l'oggetto Session in modo che Hibernate continui a scrivere questi record nel database invece di memorizzarli nella cache.

import java.util.*; 
 
import org.hibernate.HibernateException; 
import org.hibernate.Session; 
import org.hibernate.Transaction;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class ManageEmployee {
   private static SessionFactory factory; 
   public static void main(String[] args) {
      
      try {
         factory = new Configuration().configure().buildSessionFactory();
      } catch (Throwable ex) { 
         System.err.println("Failed to create sessionFactory object." + ex);
         throw new ExceptionInInitializerError(ex); 
      }
      ManageEmployee ME = new ManageEmployee();

      /* Add employee records in batches */
      ME.addEmployees( );
   }
   
   /* Method to create employee records in batches */
   public void addEmployees( ){
      Session session = factory.openSession();
      Transaction tx = null;
      Integer employeeID = null;
      
      try {
         tx = session.beginTransaction();
         for ( int i=0; i<100000; i++ ) {
            String fname = "First Name " + i;
            String lname = "Last Name " + i;
            Integer salary = i;
            Employee employee = new Employee(fname, lname, salary);
            session.save(employee);
         	if( i % 50 == 0 ) {
               session.flush();
               session.clear();
            }
         }
         tx.commit();
      } catch (HibernateException e) {
         if (tx!=null) tx.rollback();
         e.printStackTrace(); 
      } finally {
         session.close(); 
      }
      return ;
   }
}

Compilazione ed esecuzione

Ecco i passaggi per compilare ed eseguire l'applicazione sopra menzionata. Assicurati di aver impostato PATH e CLASSPATH in modo appropriato prima di procedere per la compilazione e l'esecuzione.

  • Crea il file di configurazione hibernate.cfg.xml come spiegato sopra.

  • Crea il file di mappatura Employee.hbm.xml come mostrato sopra.

  • Crea il file sorgente Employee.java come mostrato sopra e compilarlo.

  • Crea il file sorgente ManageEmployee.java come mostrato sopra e compilarlo.

  • Esegui il binario ManageEmployee per eseguire il programma, che creerà 100000 record nella tabella EMPLOYEE.

Come hai appreso in Hibernate, un oggetto verrà creato e mantenuto. Una volta modificato l'oggetto, è necessario salvarlo nuovamente nel database. Questo processo continua fino alla prossima volta che l'oggetto è necessario e verrà caricato dall'archivio persistente.

Quindi un oggetto attraversa diverse fasi del suo ciclo di vita e Interceptor Interfacefornisce metodi, che possono essere chiamati in diverse fasi per eseguire alcune attività richieste. Questi metodi sono callback dalla sessione all'applicazione, consentendo all'applicazione di ispezionare e / o manipolare le proprietà di un oggetto persistente prima che venga salvato, aggiornato, eliminato o caricato. Di seguito è riportato l'elenco di tutti i metodi disponibili nell'interfaccia di Interceptor:

Sr.No. Metodo e descrizione
1

findDirty()

Questo metodo viene chiamato quando il flush() metodo viene chiamato su un oggetto Session.

2

instantiate()

Questo metodo viene chiamato quando viene creata un'istanza di una classe persistente.

3

isUnsaved()

Questo metodo viene chiamato quando un oggetto viene passato a saveOrUpdate() metodo/

4

onDelete()

Questo metodo viene chiamato prima che un oggetto venga eliminato.

5

onFlushDirty()

Questo metodo viene chiamato quando Hibernate rileva che un oggetto è sporco (cioè è stato modificato) durante un'operazione di svuotamento, ovvero aggiornamento.

6

onLoad()

Questo metodo viene chiamato prima che un oggetto venga inizializzato.

7

onSave()

Questo metodo viene chiamato prima che un oggetto venga salvato.

8

postFlush()

Questo metodo viene chiamato dopo che si è verificato un flush e un oggetto è stato aggiornato in memoria.

9

preFlush()

Questo metodo viene chiamato prima di un flush.

Hibernate Interceptor ci dà il controllo totale su come un oggetto apparirà sia all'applicazione che al database.

Come utilizzare gli intercettatori?

Per costruire un intercettore, puoi implementare Interceptor classe direttamente o estendere EmptyInterceptorclasse. Di seguito sono riportati i semplici passaggi per utilizzare la funzionalità Hibernate Interceptor.

Crea intercettori

Estenderemo EmptyInterceptor nel nostro esempio in cui il metodo di Interceptor verrà chiamato automaticamente quando Employeeoggetto viene creato e aggiornato. È possibile implementare più metodi in base alle proprie esigenze.

import java.io.Serializable;
import java.util.Date;
import java.util.Iterator;

import org.hibernate.EmptyInterceptor;
import org.hibernate.Transaction;
import org.hibernate.type.Type;

public class MyInterceptor extends EmptyInterceptor {
   private int updates;
   private int creates;
   private int loads;

   public void onDelete(Object entity, Serializable id,
      Object[] state, String[] propertyNames, Type[] types) {
       // do nothing
   }

   // This method is called when Employee object gets updated.
   public boolean onFlushDirty(Object entity, Serializable id,
      Object[] currentState, Object[] previousState, String[] propertyNames,
      Type[] types) {
         if ( entity instanceof Employee ) {
            System.out.println("Update Operation");
            return true; 
         }
         return false;
   }
	
   public boolean onLoad(Object entity, Serializable id,
      Object[] state, String[] propertyNames, Type[] types) {
         // do nothing
         return true;
   }
   
   // This method is called when Employee object gets created.
   public boolean onSave(Object entity, Serializable id,
      Object[] state, String[] propertyNames, Type[] types) {
         if ( entity instanceof Employee ) {
            System.out.println("Create Operation");
            return true; 
         }
         return false;
   }
   
   //called before commit into database
   public void preFlush(Iterator iterator) {
      System.out.println("preFlush");
   }
   
   //called after committed into database
   public void postFlush(Iterator iterator) {
      System.out.println("postFlush");
   }
}

Crea classi POJO

Ora, modifichiamo un po 'il nostro primo esempio in cui abbiamo usato la tabella EMPLOYEE e la classe Employee con cui giocare -

public class Employee {
   private int id;
   private String firstName; 
   private String lastName;   
   private int salary;  

   public Employee() {}
   
   public Employee(String fname, String lname, int salary) {
      this.firstName = fname;
      this.lastName = lname;
      this.salary = salary;
   }
   
   public int getId() {
      return id;
   }
   
   public void setId( int id ) {
      this.id = id;
   }
   
   public String getFirstName() {
      return firstName;
   }
   
   public void setFirstName( String first_name ) {
      this.firstName = first_name;
   }
   
   public String getLastName() {
      return lastName;
   }
   
   public void setLastName( String last_name ) {
      this.lastName = last_name;
   }
   
   public int getSalary() {
      return salary;
   }
   
   public void setSalary( int salary ) {
      this.salary = salary;
   }
}

Crea tabelle di database

Il secondo passo sarebbe creare tabelle nel tuo database. Ci sarebbe una tabella corrispondente a ciascun oggetto, sei disposto a fornire la persistenza. Considera gli oggetti spiegati sopra, devono essere memorizzati e recuperati nella seguente tabella RDBMS:

create table EMPLOYEE (
   id INT NOT NULL auto_increment,
   first_name VARCHAR(20) default NULL,
   last_name  VARCHAR(20) default NULL,
   salary     INT  default NULL,
   PRIMARY KEY (id)
);

Crea file di configurazione della mappatura

Questo passaggio consiste nel creare un file di mappatura che istruisca Hibernate - come mappare la classe o le classi definite alle tabelle del database.

<?xml version = "1.0" encoding = "utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC 
"-//Hibernate/Hibernate Mapping DTD//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> 

<hibernate-mapping>
   <class name = "Employee" table = "EMPLOYEE">
      
      <meta attribute = "class-description">
         This class contains the employee detail. 
      </meta>
      
      <id name = "id" type = "int" column = "id">
         <generator class="native"/>
      </id>
      
      <property name = "firstName" column = "first_name" type = "string"/>
      <property name = "lastName" column = "last_name" type = "string"/>
      <property name = "salary" column = "salary" type = "int"/>
      
   </class>
</hibernate-mapping>

Crea classe di applicazione

Infine, creeremo la nostra classe dell'applicazione con il metodo main () per eseguire l'applicazione. Qui, va notato che durante la creazione dell'oggetto sessione, abbiamo usato la nostra classe Interceptor come argomento.

import java.util.List; 
import java.util.Date;
import java.util.Iterator; 
 
import org.hibernate.HibernateException; 
import org.hibernate.Session; 
import org.hibernate.Transaction;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class ManageEmployee {
   private static SessionFactory factory; 
   public static void main(String[] args) {
      
      try {
         factory = new Configuration().configure().buildSessionFactory();
      } catch (Throwable ex) { 
         System.err.println("Failed to create sessionFactory object." + ex);
         throw new ExceptionInInitializerError(ex); 
      }

      ManageEmployee ME = new ManageEmployee();

      /* Add few employee records in database */
      Integer empID1 = ME.addEmployee("Zara", "Ali", 1000);
      Integer empID2 = ME.addEmployee("Daisy", "Das", 5000);
      Integer empID3 = ME.addEmployee("John", "Paul", 10000);

      /* List down all the employees */
      ME.listEmployees();

      /* Update employee's records */
      ME.updateEmployee(empID1, 5000);

      /* Delete an employee from the database */
      ME.deleteEmployee(empID2);

      /* List down new list of the employees */
      ME.listEmployees();
   }
   
   /* Method to CREATE an employee in the database */
   public Integer addEmployee(String fname, String lname, int salary){
      Session session = factory.openSession( new MyInterceptor() );
      Transaction tx = null;
      Integer employeeID = null;
      
      try {
         tx = session.beginTransaction();
         Employee employee = new Employee(fname, lname, salary);
         employeeID = (Integer) session.save(employee); 
         tx.commit();
      } catch (HibernateException e) {
         if (tx!=null) tx.rollback();
         e.printStackTrace(); 
      } finally {
         session.close(); 
      }
      return employeeID;
   }
   
   /* Method to  READ all the employees */
   public void listEmployees( ){
      Session session = factory.openSession( new MyInterceptor() );
      Transaction tx = null;
      
      try {
         tx = session.beginTransaction();
         List employees = session.createQuery("FROM Employee").list(); 
         for (Iterator iterator = employees.iterator(); iterator.hasNext();){
            Employee employee = (Employee) iterator.next(); 
            System.out.print("First Name: " + employee.getFirstName()); 
            System.out.print("  Last Name: " + employee.getLastName()); 
            System.out.println("  Salary: " + employee.getSalary()); 
         }
         tx.commit();
      } catch (HibernateException e) {
         if (tx!=null) tx.rollback();
         e.printStackTrace(); 
      } finally {
         session.close(); 
      }
   }
   
   /* Method to UPDATE salary for an employee */
   public void updateEmployee(Integer EmployeeID, int salary ){
      Session session = factory.openSession( new MyInterceptor() );
      Transaction tx = null;
      
      try {
         tx = session.beginTransaction();
         Employee employee = (Employee)session.get(Employee.class, EmployeeID); 
         employee.setSalary( salary );
		 session.update(employee); 
         tx.commit();
      } catch (HibernateException e) {
         if (tx!=null) tx.rollback();
         e.printStackTrace(); 
      } finally {
         session.close(); 
      }
   }
   
   /* Method to DELETE an employee from the records */
   public void deleteEmployee(Integer EmployeeID){
      Session session = factory.openSession( new MyInterceptor() );
      Transaction tx = null;
      
      try {
         tx = session.beginTransaction();
         Employee employee = (Employee)session.get(Employee.class, EmployeeID); 
         session.delete(employee); 
         tx.commit();
      } catch (HibernateException e) {
         if (tx!=null) tx.rollback();
         e.printStackTrace(); 
      } finally {
         session.close(); 
      }
   }
}

Compilazione ed esecuzione

Ecco i passaggi per compilare ed eseguire l'applicazione sopra menzionata. Assicurati di aver impostato PATH e CLASSPATH in modo appropriato prima di procedere per la compilazione e l'esecuzione.

  • Creare il file di configurazione hibernate.cfg.xml come spiegato nel capitolo sulla configurazione.

  • Crea il file di mappatura Employee.hbm.xml come mostrato sopra.

  • Crea il file sorgente Employee.java come mostrato sopra e compilarlo.

  • Creare il file sorgente MyInterceptor.java come mostrato sopra e compilarlo.

  • Crea il file sorgente ManageEmployee.java come mostrato sopra e compilarlo.

  • Esegui il binario ManageEmployee per eseguire il programma.

Si otterrebbe il seguente risultato e i record verranno creati nella tabella EMPLOYEE.

$java ManageEmployee
.......VARIOUS LOG MESSAGES WILL DISPLAY HERE........

Create Operation
preFlush
postFlush
Create Operation
preFlush
postFlush
Create Operation
preFlush
postFlush
First Name: Zara  Last Name: Ali  Salary: 1000
First Name: Daisy  Last Name: Das  Salary: 5000
First Name: John  Last Name: Paul  Salary: 10000
preFlush
postFlush
preFlush
Update Operation
postFlush
preFlush
postFlush
First Name: Zara  Last Name: Ali  Salary: 5000
First Name: John  Last Name: Paul  Salary: 10000
preFlush
postFlush

Se controlli la tua tabella EMPLOYEE, dovrebbe avere i seguenti record:

mysql> select * from EMPLOYEE;
+----+------------+-----------+--------+
| id | first_name | last_name | salary |
+----+------------+-----------+--------+
| 29 | Zara       | Ali       |   5000 |
| 31 | John       | Paul      |  10000 |
+----+------------+-----------+--------+
2 rows in set (0.00 sec
mysql>