Exemplo de Integração Spring Hibernate Tutorial (Spring 4 + Hibernate 3 e Hibernate 4)

Primavera é um dos frameworks Java EE mais utilizados e Hibernate é o framework ORM mais popular. É por isso que a combinação Spring Hibernate é amplamente utilizada em aplicações empresariais. Recentemente, tenho escrito muito sobre Spring Tutorial e Hibernate Tutorial, então um post sobre integração spring hibernate estava pendente há muito tempo.

Spring Hibernate

Hoje, neste tutorial, vamos usar o Spring 4 e integrá-lo com o Hibernate 3 e, em seguida, atualizar o mesmo projeto para usar o Hibernate 4. Como há 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 eu usei 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 são compatíveis. Se você estiver usando outras versões e receber o erro java.lang.NoClassDefFoundError, significa que elas não são compatíveis. Na maioria das vezes, isso ocorre porque as classes do Hibernate foram 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 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

A imagem abaixo mostra a estrutura final do projeto, vamos analisar cada um dos componentes um por um.

Dependências do Maven

Vamos primeiro olhar para o 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 do Spring e Hibernate são:

  • spring-context e spring-tx para funcionalidades principais do Spring. Observe que estou usando a versão 4.0.3.RELEASE.
  • Dependência spring-orm para suporte ao Spring ORM, é necessário para integração do hibernate em nosso projeto Spring.
  • Dependências hibernate-entitymanager e hibernate-core para o framework Hibernate. Observe que a versão é 3.6.9.Final, para usar o Hibernate 4, tudo o que precisamos fazer é alterá-lo 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 Bean

Podemos usar o mapeamento baseado em XML do Hibernate, assim como o mapeamento baseado em anotações JPA. Aqui estou utilizando anotações JPA para o mapeamento, porque o Hibernate fornece 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 para 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 seria semelhante ao que está 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. Esse 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 de ORM iBatis, tudo o que precisamos fazer é fornecer uma implementação DAO para o iBatis e depois alterar o arquivo de configuração de beans do Spring. No exemplo acima, estou usando o gerenciamento de transações do Hibernate por sessão. 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 com o Hibernate 3

Vamos primeiro dar uma olhada nas configurações de beans de mola que precisamos para integração do Hibernate 3, vamos detalhar 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 Spring e Hibernate 3, Spring ORM fornece duas classes – org.springframework.orm.hibernate3.LocalSessionFactoryBean quando os mapeamentos hibernate são baseados em XML e org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean para mapeamento baseado em anotações. Eu forneci uma configuração simples de bean de LocalSessionFactoryBean em comentários, se você estiver usando mapeamentos baseados em XML. AnnotationSessionFactoryBean estende a classe LocalSessionFactoryBean, então ele possui todas as propriedades básicas para integração do hibernate. As propriedades são autoexplicativas e principalmente relacionadas ao hibernate, então não entrarei em muitos detalhes para elas. Mas se você estiver se perguntando de onde vem hibernateProperties, annotatedClasses, você precisa olhar para o código fonte da classe bean. Observe a definição de bean de personDAO, como eu disse anteriormente, se precisarmos mudar para algum outro framework ORM, precisamos alterar a classe de implementação aqui e definir quaisquer outras propriedades que precisarmos.

Programa de Teste 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();	
	}
}

Quando executamos o programa acima, obtemos muitas saídas relacionadas ao Hibernate porque eu não configurei o logging adequadamente, mas isso está fora do escopo deste tutorial. No entanto, obtemos a seguinte saída gerada pelo 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

Mudanças na integração Spring 4 Hibernate 4

Agora vamos mudar nossa aplicação para usar Hibernate 4 em vez de Hibernate 3. Para essa migração, precisamos fazer apenas as seguintes mudanças de configuração.

  1. Alterar a versão do hibernate para 4.3.5.Final no arquivo pom.xml, conforme mostrado nos comentários acima.

  2. Altere o arquivo de configuração do Spring bean, até agora você deve ter percebido que o arquivo de configuração do Spring bean é fundamental para a integração do framework Spring e 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 unificou 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é. Apenas altere a classe SpringHibernateMain para usar o spring4.xml para a configuração dos beans e funcionará bem, você obterá a mesma saída de antes. Você pode baixar o projeto final no link abaixo e brincar com mais configurações para aprender mais.

Baixe o Projeto de Integração Spring Hibernate

Source:
https://www.digitalocean.com/community/tutorials/spring-hibernate-integration-example-tutorial