Spring é um dos frameworks Java EE mais utilizados e Hibernate é o framework ORM mais popular. É por isso que a combinação Spring Hibernate é muito utilizada em aplicações empresariais. Recentemente, tenho escrito muito sobre Tutorial Spring e Tutorial Hibernate, então um post sobre integração spring hibernate era necessário há muito tempo.
Spring Hibernate
Hoje neste tutorial, vamos usar o Spring 4 e integrá-lo com o Hibernate 3 e depois atualizar o mesmo projeto para usar o Hibernate 4. Como existem muitas versões tanto para o Spring quanto para o Hibernate e o artefato Spring ORM suporta tanto o Hibernate 3 quanto o Hibernate 4, é bom que eu liste todas as dependências que utilizei no meu projeto. Note que observei que nem todas as versões do Spring e do Hibernate são compatíveis, as versões abaixo funcionaram para mim, então acredito que sejam compatíveis. Se estiver usando outras versões e receber java.lang.NoClassDefFoundError
, significa que elas não são compatíveis. Na maioria das vezes, isso ocorre porque as classes do Hibernate são movidas de um pacote para outro, causando esse erro. Por exemplo, a classe org.hibernate.engine.FilterDefinition
foi movida para org.hibernate.engine.spi.FilterDefinition
nas versões mais recentes do Hibernate.
- Versão do Spring Framework: 4.0.3.RELEASE
- Versão do Hibernate Core e do Hibernate EntityManager: 3.6.9.Final e 4.3.5.Final
- Versão do Spring ORM: 4.0.3.RELEASE
Configuração do Banco de Dados
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;
Estrutura do Projeto de Exemplo de Integração Spring Hibernate
Abaixo, a imagem mostra a estrutura final do projeto. Vamos analisar cada um dos componentes um por um.
Dependências do Maven
Primeiramente, examinaremos nosso arquivo pom.xml para todas as dependências necessárias e suas versões.
<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>
Dependências importantes para o projeto de integração Spring e Hibernate são:
- spring-context e spring-tx para funcionalidades essenciais do Spring. Observe que estou usando a versão 4.0.3.RELEASE.
- spring-orm para suporte ao ORM do Spring, é necessário para a integração do Hibernate em nosso projeto Spring.
- hibernate-entitymanager e hibernate-core para o framework Hibernate. Observe que a versão é 3.6.9.Final; para usar o Hibernate 4, basta alterar para 4.3.5.Final, conforme comentado no arquivo pom.xml acima.
- mysql-connector-java para o driver MySQL para conexão com o banco de dados.
Classe de Modelo ou Entidade
Podemos usar o mapeamento baseado em XML do Hibernate, bem como o mapeamento baseado em anotações JPA. Aqui estou usando as anotações JPA para o mapeamento porque o Hibernate fornece uma implementação 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;
}
}
Classes DAO
Iremos implementar dois métodos em nossas classes DAO, o primeiro para salvar o objeto Pessoa na tabela e o segundo que irá buscar todos os registros da tabela e retornar a lista de Pessoas.
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();
}
A implementação da classe DAO acima seria como abaixo.
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;
}
}
Observe que este é o único lugar onde estamos usando classes relacionadas ao Hibernate. Este padrão torna nossa implementação flexível e fácil de migrar de uma tecnologia para outra. Por exemplo, se quisermos usar o framework ORM iBatis, tudo o que precisamos fazer é fornecer uma implementação DAO para o iBatis e, em seguida, alterar o arquivo de configuração do bean do Spring. No exemplo acima, estou usando o gerenciamento de transações de sessão do Hibernate. Mas também podemos usar o gerenciamento de transações declarativo do Spring usando a anotação @Transactional
, leia mais em Gerenciamento de Transações do Spring.
Arquivo de Configuração de Beans do Spring para Integração do Hibernate 3
Vamos primeiro analisar as configurações de bean de spring que precisamos para integração com o Hibernate 3, vamos nos aprofundar mais tarde.
<?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>
Existem duas maneiras pelas quais podemos fornecer detalhes de conexão com o banco de dados ao Hibernate, primeiro passando tudo em hibernateProperties
e segundo criando um DataSource e então passando-o para o Hibernate. Prefiro a segunda abordagem, por isso temos a dependência do Apache Commons DBCP para criar um BasicDataSource
configurando as propriedades de conexão com o banco de dados. Para integração com Spring e Hibernate 3, Spring ORM fornece duas classes – org.springframework.orm.hibernate3.LocalSessionFactoryBean
quando os mapeamentos do Hibernate são baseados em XML e org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean
para mapeamento baseado em anotações. Eu forneci uma configuração de bean simples de LocalSessionFactoryBean
em comentários, se estiver usando mapeamentos baseados em XML. AnnotationSessionFactoryBean
estende a classe LocalSessionFactoryBean
, então ela tem todas as propriedades básicas para integração com o Hibernate. As propriedades são autoexplicativas e principalmente relacionadas ao Hibernate, então não vou me aprofundar muito nelas. Mas se você estiver se perguntando de onde vêm hibernateProperties, annotatedClasses, você precisa olhar o código-fonte da classe de bean. Observe a definição do bean de personDAO, como mencionei anteriormente, se precisarmos mudar para algum outro framework ORM, precisamos alterar a classe de implementação aqui e definir quaisquer outras propriedades que precisamos.
Programa de Teste do Spring 4 Hibernate 3
Nossa configuração está pronta agora, vamos escrever um programa simples para testar nossa aplicação.
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);
}
//fechar recursos
context.close();
}
}
Ao executarmos o programa acima, obtemos muita saída relacionada ao Hibernate porque não configurei o registro adequadamente, mas isso está fora do escopo deste tutorial. No entanto, obtemos a seguinte saída gerada por nosso programa.
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
Alterações na integração do Spring 4 Hibernate 4
Agora vamos alterar nossa aplicação para usar o Hibernate 4 em vez do Hibernate 3. Para esta migração, precisamos fazer apenas as seguintes alterações de configuração.
-
Altere a versão do hibernate para 4.3.5.Final no arquivo pom.xml, conforme mostrado nos comentários acima.
-
Altere o arquivo de configuração do Spring Bean. Até agora, você deve ter percebido que o arquivo de configuração do Spring Bean é a chave para a integração do framework Spring com o Hibernate. O arquivo de configuração do Spring Bean abaixo funcionará para as versões 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> <!-- Definição do Bean Hibernate 4 SessionFactory --> <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>
Para o Hibernate 4, precisamos usar
org.springframework.orm.hibernate4.LocalSessionFactoryBean
para o bean SessionFactory. O Spring ORM fundiu ambas as classes para o Hibernate 3, agora há uma única classe, o que é bom para evitar confusão. Todas as outras configurações são as mesmas que antes.
É isso, nosso projeto foi migrado com sucesso para o Hibernate 4, legal não é? Apenas altere a classe SpringHibernateMain
para usar spring4.xml
para a configuração dos beans e funcionará bem, você obterá a mesma saída que antes. Você pode baixar o projeto final pelo link abaixo e brincar com mais configurações para aprender mais.
Source:
https://www.digitalocean.com/community/tutorials/spring-hibernate-integration-example-tutorial