Spring è uno dei framework Java EE più utilizzati e Hibernate è il framework ORM più popolare. Ecco perché la combinazione Spring Hibernate è molto utilizzata nelle applicazioni enterprise. Di recente ho scritto molto per il Tutorial di Spring e il Tutorial di Hibernate, quindi era ora di pubblicare un post sull’integrazione di spring hibernate.
Spring Hibernate
Oggi in questo tutorial, useremo Spring 4 e lo integreremo con Hibernate 3 e poi aggiorneremo lo stesso progetto per utilizzare Hibernate 4. Poiché ci sono molte versioni sia per Spring che per Hibernate e l’artefatto Spring ORM supporta sia Hibernate 3 che Hibernate 4, è bene che elenchi tutte le dipendenze che ho usato nel mio progetto. Nota che ho notato che tutte le versioni di Spring e Hibernate non sono compatibili, le versioni seguenti hanno funzionato per me quindi penso che siano compatibili. Se stai utilizzando altre versioni e ricevi `java.lang.NoClassDefFoundError`, significa che non sono compatibili. Principalmente è perché le classi di Hibernate sono spostate da un pacchetto a un altro causando questo errore. Ad esempio la classe `org.hibernate.engine.FilterDefinition` è stata spostata a `org.hibernate.engine.spi.FilterDefinition` nelle ultime versioni di Hibernate.
- Versione del Framework Spring: 4.0.3.RELEASE
- Versione del nucleo di Hibernate e di Hibernate EntityManager: 3.6.9.Final e 4.3.5.Final
- Versione di Spring ORM: 4.0.3.RELEASE
Configurazione del Database
I am using MySQL database for my project, so below setup.sql script will create the necessary table for this example.
CREATE TABLE `Person` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(20) NOT NULL DEFAULT '',
`country` varchar(20) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;
commit;
Struttura del Progetto Esempio di Integrazione Spring Hibernate
Ecco la struttura finale del progetto, esamineremo ciascun componente uno per uno.
Dependency Maven
Guarderemo prima nel nostro file pom.xml per tutte le dipendenze necessarie e le relative versioni.
<project xmlns="https://maven.apache.org/POM/4.0.0" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.springframework.samples</groupId>
<artifactId>SpringHibernateExample</artifactId>
<version>0.0.1-SNAPSHOT</version>
<properties>
<!-- Generic properties -->
<java.version>1.6</java.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<!-- Spring -->
<spring-framework.version>4.0.3.RELEASE</spring-framework.version>
<!-- Hibernate / JPA -->
<!-- <hibernate.version>4.3.5.Final</hibernate.version> -->
<hibernate.version>3.6.9.Final</hibernate.version>
<!-- Logging -->
<logback.version>1.0.13</logback.version>
<slf4j.version>1.7.5</slf4j.version>
</properties>
<dependencies>
<!-- Spring and Transactions -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>${spring-framework.version}</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>${spring-framework.version}</version>
</dependency>
<!-- Spring ORM support -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-orm</artifactId>
<version>${spring-framework.version}</version>
</dependency>
<!-- Logging with SLF4J & LogBack -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>${slf4j.version}</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>${logback.version}</version>
<scope>runtime</scope>
</dependency>
<!-- Hibernate -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>${hibernate.version}</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>${hibernate.version}</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.9</version>
</dependency>
<dependency>
<groupId>commons-dbcp</groupId>
<artifactId>commons-dbcp</artifactId>
<version>1.4</version>
</dependency>
</dependencies>
</project>
Dipendenze importanti per il progetto di integrazione Spring e Hibernate sono:
- spring-context e spring-tx per le funzionalità principali di Spring. Nota che sto utilizzando la versione 4.0.3.RELEASE.
- La dipendenza spring-orm per il supporto Spring ORM, è necessaria per l’integrazione di Hibernate nel nostro progetto Spring.
- Le dipendenze hibernate-entitymanager e hibernate-core per il framework Hibernate. Nota che la versione è 3.6.9.Final; per utilizzare Hibernate 4, è sufficiente cambiarla in 4.3.5.Final, come indicato nel file pom.xml sopra.
- mysql-connector-java per il driver MySQL per la connessione al database.
Classe Modello o Entity Bean
Possiamo utilizzare il mapping basato su XML di Hibernate così come il mapping basato su annotazioni JPA. Qui sto utilizzando le annotazioni JPA per il mapping perché Hibernate fornisce un’implementazione JPA.
package com.journaldev.model;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
/**
* Entity bean with JPA annotations
* Hibernate provides JPA implementation
* @author pankaj
*
*/
@Entity
@Table(name="Person")
public class Person {
@Id
@Column(name="id")
@GeneratedValue(strategy=GenerationType.IDENTITY)
private int id;
private String name;
private String country;
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 String getCountry() {
return country;
}
public void setCountry(String country) {
this.country = country;
}
@Override
public String toString(){
return "id="+id+", name="+name+", country="+country;
}
}
Classi DAO
Implementeremo due metodi nelle nostre classi DAO, il primo per salvare l’oggetto Persona nella tabella e il secondo che recupererà tutti i record dalla tabella e restituirà la lista delle Persone.
package com.journaldev.dao;
import java.util.List;
import com.journaldev.model.Person;
public interface PersonDAO {
public void save(Person p);
public List<Person> list();
}
L’implementazione della classe DAO sarebbe come segue.
package com.journaldev.dao;
import java.util.List;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import com.journaldev.model.Person;
public class PersonDAOImpl implements PersonDAO {
private SessionFactory sessionFactory;
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
@Override
public void save(Person p) {
Session session = this.sessionFactory.openSession();
Transaction tx = session.beginTransaction();
session.persist(p);
tx.commit();
session.close();
}
@SuppressWarnings("unchecked")
@Override
public List<Person> list() {
Session session = this.sessionFactory.openSession();
List<Person> personList = session.createQuery("from Person").list();
session.close();
return personList;
}
}
Nota che questo è l’unico punto in cui stiamo utilizzando classi correlate ad Hibernate. Questo modello rende la nostra implementazione flessibile e facile da migrare da una tecnologia all’altra. Ad esempio, se vogliamo utilizzare il framework ORM iBatis, tutto ciò di cui abbiamo bisogno è fornire un’implementazione DAO per iBatis e quindi modificare il file di configurazione dei bean di Spring. Nell’esempio precedente, sto utilizzando la gestione delle transazioni di sessione di Hibernate. Ma possiamo anche utilizzare la gestione delle transazioni dichiarativa di Spring utilizzando l’annotazione @Transactional
, leggi di più su Gestione delle transazioni di Spring.
File di configurazione dei bean di Spring per l’integrazione di Hibernate 3
Iniziamo prima con le configurazioni del bean di spring di cui abbiamo bisogno per l’integrazione di Hibernate 3, esamineremo i dettagli in seguito.
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="https://www.springframework.org/schema/beans"
xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xmlns:aop="https://www.springframework.org/schema/aop"
xmlns:tx="https://www.springframework.org/schema/tx"
xsi:schemaLocation="https://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
https://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop-4.0.xsd
https://www.springframework.org/schema/tx https://www.springframework.org/schema/tx/spring-tx-4.0.xsd">
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close">
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
<property name="url" value="jdbc:mysql://localhost:3306/TestDB" />
<property name="username" value="pankaj" />
<property name="password" value="pankaj123" />
</bean>
<!-- Hibernate 3 XML SessionFactory Bean definition-->
<!-- <bean id="hibernate3SessionFactory"
class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="mappingResources">
<list>
<value>person.hbm.xml</value>
</list>
</property>
<property name="hibernateProperties">
<value>
hibernate.dialect=org.hibernate.dialect.MySQLDialect
</value>
</property>
</bean> -->
<!-- Hibernate 3 Annotation SessionFactory Bean definition-->
<bean id="hibernate3AnnotatedSessionFactory"
class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="dataSource" />
<property name="annotatedClasses">
<list>
<value>com.journaldev.model.Person</value>
</list>
</property>
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
<prop key="hibernate.current_session_context_class">thread</prop>
<prop key="hibernate.show_sql">false</prop>
</props>
</property>
</bean>
<bean id="personDAO" class="com.journaldev.dao.PersonDAOImpl">
<property name="sessionFactory" ref="hibernate3AnnotatedSessionFactory" />
</bean>
</beans>
Ci sono due modi per fornire i dettagli della connessione al database a Hibernate, prima passando tutto in hibernateProperties
e secondo creando un DataSource e quindi passandolo a hibernate. Preferisco il secondo approccio, ecco perché abbiamo una dipendenza da Apache Commons DBCP per creare un BasicDataSource
impostando le proprietà della connessione al database. Per l’integrazione di Spring e Hibernate 3, Spring ORM fornisce due classi – org.springframework.orm.hibernate3.LocalSessionFactoryBean
quando i mapping di hibernate sono basati su XML e org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean
per il mapping basato su annotazioni. Ho fornito una semplice configurazione del bean di LocalSessionFactoryBean
nei commenti, se stai usando mapping basati su XML. AnnotationSessionFactoryBean
estende la classe LocalSessionFactoryBean
, quindi ha tutte le proprietà di base per l’integrazione di hibernate. Le proprietà sono autoesplicative e principalmente legate ad hibernate, quindi non entrerò nei dettagli. Ma se ti stai chiedendo da dove arrivano hibernateProperties, annotatedClasses, devi guardare nel codice sorgente della classe di bean. Nota la definizione del bean di personDAO, come ho detto prima se dovessimo passare a un altro framework ORM, dobbiamo cambiare la classe di implementazione qui e impostare qualsiasi altra proprietà di cui abbiamo bisogno.
Programma di prova Spring 4 Hibernate 3
La nostra configurazione è pronta adesso, scriviamo un programma semplice per testare la nostra applicazione.
package com.journaldev.main;
import java.util.List;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.journaldev.dao.PersonDAO;
import com.journaldev.model.Person;
public class SpringHibernateMain {
public static void main(String[] args) {
ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("spring.xml");
PersonDAO personDAO = context.getBean(PersonDAO.class);
Person person = new Person();
person.setName("Pankaj"); person.setCountry("India");
personDAO.save(person);
System.out.println("Person::"+person);
List list = personDAO.list();
for(Person p : list){
System.out.println("Person List::"+p);
}
//chiudi risorse
context.close();
}
}
Quando eseguiamo il programma sopra, otteniamo molta output relativa a Hibernate perché non ho configurato correttamente il logging, ma questo esula dall’ambito di questo tutorial. Tuttavia, otteniamo il seguente output generato dal nostro programma.
Person::id=3, name=Pankaj, country=India
Person List::id=1, name=Pankaj, country=India
Person List::id=2, name=Pankaj, country=India
Person List::id=3, name=Pankaj, country=India
Modifiche all’integrazione Spring 4 Hibernate 4
Adesso cambiamo la nostra applicazione per utilizzare Hibernate 4 invece di Hibernate 3. Per questa migrazione, dobbiamo apportare solo le seguenti modifiche alla configurazione.
-
Cambia la versione di Hibernate in 4.3.5.Final nel file pom.xml, come mostrato nei commenti sopra.
-
Cambia il file di configurazione dei bean di Spring, fino ad ora dovresti aver capito che il file di configurazione dei bean di Spring è la chiave per l’integrazione del framework Spring e Hibernate. Il seguente file di configurazione dei bean di Spring funzionerà per le versioni Spring 4 e Hibernate 4.
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="https://www.springframework.org/schema/beans" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xmlns:aop="https://www.springframework.org/schema/aop" xmlns:tx="https://www.springframework.org/schema/tx" xsi:schemaLocation="https://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd https://www.springframework.org/schema/aop https://www.springframework.org/schema/aop/spring-aop-4.0.xsd https://www.springframework.org/schema/tx https://www.springframework.org/schema/tx/spring-tx-4.0.xsd"> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"> <property name="driverClassName" value="com.mysql.jdbc.Driver" /> <property name="url" value="jdbc:mysql://localhost:3306/TestDB" /> <property name="username" value="pankaj" /> <property name="password" value="pankaj123" /> </bean> <!-- Definizione del bean SessionFactory di Hibernate 4 --> <bean id="hibernate4AnnotatedSessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"> <property name="dataSource" ref="dataSource" /> <property name="annotatedClasses"> <list> <value>com.journaldev.model.Person</value> </list> </property> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop> <prop key="hibernate.current_session_context_class">thread</prop> <prop key="hibernate.show_sql">false</prop> </props> </property> </bean> <bean id="personDAO" class="com.journaldev.dao.PersonDAOImpl"> <property name="sessionFactory" ref="hibernate4AnnotatedSessionFactory" /> </bean> </beans>
Per Hibernate 4, è necessario utilizzare
org.springframework.orm.hibernate4.LocalSessionFactoryBean
per il bean SessionFactory, Spring ORM ha unito entrambe le classi per Hibernate 3 e ora c’è una sola classe, questo è utile per evitare confusione. Tutte le altre configurazioni sono le stesse di prima.
Ecco fatto, il nostro progetto è stato migrato con successo a Hibernate 4, bello vero? Basta cambiare la classe SpringHibernateMain
per utilizzare spring4.xml
per la configurazione dei bean e funzionerà correttamente, otterrai lo stesso output di prima. Puoi scaricare il progetto finale dal link sottostante e sperimentare con altre configurazioni per imparare di più.
Source:
https://www.digitalocean.com/community/tutorials/spring-hibernate-integration-example-tutorial