Hibernate - Mappature SortedMap
UN SortedMap è una raccolta java simile a Mapche memorizza gli elementi in coppie chiave-valore e fornisce un ordinamento totale sulle sue chiavi. Gli elementi duplicati non sono consentiti nella mappa. La mappa viene ordinata in base all'ordinamento naturale delle sue chiavi, o da un comparatore normalmente fornito al momento della creazione della mappa ordinata.
Una SortedMap viene mappata con un elemento <map> nella tabella di mappatura e una mappa ordinata può essere inizializzata con java.util.TreeMap.
Definisci tabelle RDBMS
Considera una situazione in cui dobbiamo archiviare i record dei nostri dipendenti nella tabella EMPLOYEE che avrà la seguente struttura:
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)
);
Inoltre, si supponga che ogni dipendente possa avere uno o più certificati associati a lui / lei. Memorizzeremo le informazioni relative al certificato in una tabella separata che ha la seguente struttura:
create table CERTIFICATE (
id INT NOT NULL auto_increment,
certificate_type VARCHAR(40) default NULL,
certificate_name VARCHAR(30) default NULL,
employee_id INT default NULL,
PRIMARY KEY (id)
);
Ci sarà one-to-many relazione tra gli oggetti EMPLOYEE e CERTIFICATE.
Definisci classi POJO
Implementiamo una classe POJO Employee, che verrà utilizzato per rendere persistenti gli oggetti relativi alla tabella EMPLOYEE e con una raccolta di certificati in formato List variabile.
import java.util.*;
public class Employee {
private int id;
private String firstName;
private String lastName;
private int salary;
private SortedMap certificates;
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;
}
public SortedMap getCertificates() {
return certificates;
}
public void setCertificates( SortedMap certificates ) {
this.certificates = certificates;
}
}
Dobbiamo definire un'altra classe POJO corrispondente alla tabella CERTIFICATE in modo che gli oggetti certificato possano essere archiviati e recuperati nella tabella CERTIFICATE. Questa classe dovrebbe anche implementare l'interfaccia Comparable e il metodo compareTo che verranno utilizzati per ordinare gli elementi chiave di SortedMap nel caso in cui imposti sort = "natural" nel tuo file di mappatura (vedi sotto il file di mappatura).
public class Certificate implements Comparable <String>{
private int id;
private String name;
public Certificate() {}
public Certificate(String name) {
this.name = name;
}
public int getId() {
return id;
}
public void setId( int id ) {
this.id = id;
}
public String getName() {
return name;
}
public void setName( String name ) {
this.name = name;
}
public int compareTo(String that){
final int BEFORE = -1;
final int AFTER = 1;
if (that == null) {
return BEFORE;
}
Comparable thisCertificate = this;
Comparable thatCertificate = that;
if(thisCertificate == null) {
return AFTER;
} else if(thatCertificate == null) {
return BEFORE;
} else {
return thisCertificate.compareTo(thatCertificate);
}
}
}
Definisci file di mappatura ibernazione
Sviluppiamo il nostro file di mappatura che istruisce Hibernate su come mappare le classi definite alle tabelle del database. L'elemento <map> verrà utilizzato per definire la regola per la mappa utilizzata.
<?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>
<map name = "certificates" cascade="all" sort="MyClass">
<key column = "employee_id"/>
<index column = "certificate_type" type = "string"/>
<one-to-many class="Certificate"/>
</map>
<property name = "firstName" column = "first_name" type = "string"/>
<property name = "lastName" column = "last_name" type = "string"/>
<property name = "salary" column = "salary" type = "int"/>
</class>
<class name = "Certificate" table = "CERTIFICATE">
<meta attribute = "class-description">
This class contains the certificate records.
</meta>
<id name = "id" type = "int" column = "id">
<generator class="native"/>
</id>
<property name = "name" column = "certificate_name" type = "string"/>
</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. Hai già familiarità con la maggior parte dei dettagli di mappatura, ma vediamo di nuovo tutti gli elementi del file di mappatura -
Il documento di mappatura è un documento XML con estensione <hibernate-mapping> come elemento radice che contiene due elementi <class> corrispondenti a ciascuna classe.
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 l'attributo dell'elemento class e il nome della tabella del database viene specificato utilizzando il table attributo.
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.
Il <map>l'elemento viene utilizzato per impostare la relazione tra le classi Certificate e Employee. Abbiamo usato il filecascadeattributo nell'elemento <map> per dire a Hibernate di rendere persistenti gli oggetti Certificate contemporaneamente agli oggetti Employee. Ilname l'attributo è impostato su definito SortedMapvariabile nella classe genitore, nel nostro caso sono i certificati . Ilsort l'attributo può essere impostato su natural per avere un ordinamento naturale o può essere impostato su una classe personalizzata che implementa java.util.Comparator. Abbiamo usato una classeMyClass che implementa java.util.Comparator per invertire l'ordine di ordinamento implementato in Certificate classe.
Il <index>elemento viene utilizzato per rappresentare le parti chiave della coppia chiave / valore mappa. La chiave verrà archiviata nella colonna certificate_type utilizzando un tipo di stringa.
Il <key>elemento è la colonna nella tabella CERTIFICATE che contiene la chiave esterna per l'oggetto genitore, ad es. tabella DIPENDENTE.
Il <one-to-many>indica che un oggetto Employee è correlato a molti oggetti Certificate e, di conseguenza, all'oggetto Certificate deve essere associato un genitore Employee. Puoi usare entrambi<one-to-one>, <many-to-one> o <many-to-many> elementi in base alle vostre esigenze.
Se usiamo sort="natural"quindi non è necessario creare una classe separata perché la classe Certificate ha già implementato l'interfaccia Comparable e hibernate utilizzerà il metodo compareTo () definito nella classe Certificate per confrontare le chiavi SortedMap. Ma stiamo usando una classe di confronto personalizzataMyClassnel nostro file di mappatura, quindi dovremmo creare questa classe in base al nostro algoritmo di ordinamento. Facciamo un ordinamento discendente delle chiavi disponibili nella mappa.
import java.util.Comparator;
public class MyClass implements Comparator <String>{
public int compare(String o1, String o2) {
final int BEFORE = -1;
final int AFTER = 1;
/* To reverse the sorting order, multiple by -1 */
if (o2 == null) {
return BEFORE * -1;
}
Comparable thisCertificate = o1;
Comparable thatCertificate = o2;
if(thisCertificate == null) {
return AFTER * 1;
} else if(thatCertificate == null) {
return BEFORE * -1;
} else {
return thisCertificate.compareTo(thatCertificate) * -1;
}
}
}
Infine, creeremo la nostra classe dell'applicazione con il metodo main () per eseguire l'applicazione. Useremo questa applicazione per salvare pochi record dei Dipendenti insieme ai loro certificati e quindi applicheremo le operazioni CRUD su quei record.
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();
/* Let us have a set of certificates for the first employee */
TreeMap set1 = new TreeMap();
set1.put("ComputerScience", new Certificate("MCA"));
set1.put("BusinessManagement", new Certificate("MBA"));
set1.put("ProjectManagement", new Certificate("PMP"));
/* Add employee records in the database */
Integer empID1 = ME.addEmployee("Manoj", "Kumar", 4000, set1);
/* Another set of certificates for the second employee */
TreeMap set2 = new TreeMap();
set2.put("ComputerScience", new Certificate("MCA"));
set2.put("BusinessManagement", new Certificate("MBA"));
/* Add another employee record in the database */
Integer empID2 = ME.addEmployee("Dilip", "Kumar", 3000, set2);
/* List down all the employees */
ME.listEmployees();
/* Update employee's salary records */
ME.updateEmployee(empID1, 5000);
/* Delete an employee from the database */
ME.deleteEmployee(empID2);
/* List down all the employees */
ME.listEmployees();
}
/* Method to add an employee record in the database */
public Integer addEmployee(String fname, String lname, int salary, TreeMap cert){
Session session = factory.openSession();
Transaction tx = null;
Integer employeeID = null;
try{
tx = session.beginTransaction();
Employee employee = new Employee(fname, lname, salary);
employee.setCertificates(cert);
employeeID = (Integer) session.save(employee);
tx.commit();
} catch (HibernateException e) {
if (tx!=null) tx.rollback();
e.printStackTrace();
} finally {
session.close();
}
return employeeID;
}
/* Method to list all the employees detail */
public void listEmployees( ){
Session session = factory.openSession();
Transaction tx = null;
try {
tx = session.beginTransaction();
List employees = session.createQuery("FROM Employee").list();
for (Iterator iterator1 = employees.iterator(); iterator1.hasNext();){
Employee employee = (Employee) iterator1.next();
System.out.print("First Name: " + employee.getFirstName());
System.out.print(" Last Name: " + employee.getLastName());
System.out.println(" Salary: " + employee.getSalary());
SortedMap<String, Certificate> map = employee.getCertificates();
for(Map.Entry<String,Certificate> entry : map.entrySet()){
System.out.print("\tCertificate Type: " + entry.getKey());
System.out.println(", Name: " + (entry.getValue()).getName());
}
}
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();
}
}
}
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 Certificate.java come mostrato sopra e compilarlo.
Crea il file sorgente MyClass.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 sullo schermo e nello stesso tempo verranno creati record nelle tabelle EMPLOYEE e CERTIFICATE. Puoi vedere che il tipo di certificato è stato ordinato in ordine inverso. Puoi provare cambiando il tuo file di mappatura, semplicemente impostatosort="natural" ed esegui il tuo programma e confronta i risultati.
$java ManageEmployee
.......VARIOUS LOG MESSAGES WILL DISPLAY HERE........
First Name: Manoj Last Name: Kumar Salary: 4000
Certificate Type: ProjectManagement, Name: PMP
Certificate Type: ComputerScience, Name: MCA
Certificate Type: BusinessManagement, Name: MBA
First Name: Dilip Last Name: Kumar Salary: 3000
Certificate Type: ComputerScience, Name: MCA
Certificate Type: BusinessManagement, Name: MBA
First Name: Manoj Last Name: Kumar Salary: 5000
Certificate Type: ProjectManagement, Name: PMP
Certificate Type: ComputerScience, Name: MCA
Certificate Type: BusinessManagement, Name: MBA
Se controlli le tabelle EMPLOYEE e CERTIFICATE, dovrebbero avere i seguenti record:
mysql> select * from EMPLOYEE;
+----+------------+-----------+--------+
| id | first_name | last_name | salary |
+----+------------+-----------+--------+
| 74 | Manoj | Kumar | 5000 |
+----+------------+-----------+--------+
1 row in set (0.00 sec)
mysql> select * from CERTIFICATE;
+----+--------------------+------------------+-------------+
| id | certificate_type | certificate_name | employee_id |
+----+--------------------+------------------+-------------+
| 52 | BusinessManagement | MBA | 74 |
| 53 | ComputerScience | MCA | 74 |
| 54 | ProjectManagement | PMP | 74 |
+----+--------------------+------------------+-------------+
3 rows in set (0.00 sec)
mysql>