Поиск по сайту:

Учебник по примеру интеграции Spring Hibernate (Spring 4 + Hibernate 3 и Hibernate 4)


Весенняя спячка

Сегодня в этом руководстве мы будем использовать Spring 4 и интегрировать его с Hibernate 3, а затем обновить тот же проект для использования Hibernate 4. Поскольку существует множество версий для Spring и Hibernate, а артефакт Spring ORM поддерживает как Hibernate 3, так и Hibernate 4. , хорошо, что я перечисляю все зависимости, которые я использовал в своем проекте. Обратите внимание, что я заметил, что все весенние и спящие версии несовместимы, у меня работали следующие версии, поэтому я думаю, что они совместимы. Если вы используете какие-то другие версии и получаете java.lang.NoClassDefFoundError, это означает, что они несовместимы. В основном это связано с тем, что классы Hibernate перемещаются из одного пакета в другой, вызывая эту ошибку. Например, класс org.hibernate.engine.FilterDefinition перемещен в org.hibernate.engine.spi.FilterDefinition в последних версиях спящего режима.

  • Версия Spring Framework: 4.0.3.RELEASE
  • Версия Hibernate Core и Hibernate EntityManager: 3.6.9.Final и 4.3.5.Final
  • Версия Spring ORM: 4.0.3.RELEASE

Настройка базы данных

Я использую базу данных MySQL для своего проекта, поэтому ниже скрипт setup.sql создаст необходимую таблицу для этого примера.

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;

Пример структуры проекта Spring Hibernate Integration

Зависимости Maven

Сначала мы посмотрим в наш файл pom.xml на наличие всех необходимых зависимостей и их версий.

<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>

Важные зависимости для проекта интеграции Spring и Hibernate:

  • spring-context и spring-tx для основных функций Spring. Обратите внимание, что я использую версию 4.0.3.RELEASE.
  • зависимость spring-orm для поддержки Spring ORM, она необходима для интеграции гибернации в наш весенний проект.
  • зависимости hibernate-entitymanager и hibernate-core для платформы Hibernate. Обратите внимание, что версия 3.6.9.Final, для использования Hibernate 4 все, что нам нужно, это изменить ее на 4.3.5.Final, как указано в файле pom.xml выше.
  • mysql-connector-java для драйвера MySQL для подключения к базе данных.

Класс модели или объектный компонент

Мы можем использовать сопоставление на основе Hibernate XML, а также сопоставление на основе аннотаций JPA. Здесь я использую аннотации JPA для сопоставления, потому что спящий режим обеспечивает реализацию 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;
	}
}

Классы ДАО

Мы реализуем два метода в наших классах DAO: первый для сохранения объекта Person в таблице, а второй — для извлечения всех записей из таблицы и возврата списка пользователей.

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

Выше реализация класса DAO будет такой, как показано ниже.

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;
	}

}

Обратите внимание, что это единственное место, где мы используем классы, связанные с Hibernate. Этот шаблон делает нашу реализацию гибкой и простой для перехода с одной технологии на другую. Например, если мы хотим использовать фреймворк iBatis ORM, все, что нам нужно, — это предоставить реализацию DAO для iBatis, а затем изменить файл конфигурации bean-компонента Spring. В приведенном выше примере я использую управление транзакциями сеанса Hibernate. Но мы также можем использовать декларативное управление транзакциями Spring с помощью аннотации @Transactional, подробнее читайте в Spring Transaction Management.

Файл конфигурации Spring Bean для интеграции Hibernate 3

Давайте сначала рассмотрим конфигурации bean-компонентов Spring, которые нам нужны для интеграции с Hibernate 3, а позже мы рассмотрим их подробно.

<?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>

Есть два способа предоставить информацию о подключении к базе данных в Hibernate: во-первых, передав все в hibernateProperties, а во-вторых, создав DataSource, а затем передав его в hibernate. Я предпочитаю второй подход, поэтому у нас есть зависимость Apache Commons DBCP для создания BasicDataSource путем установки свойств подключения к базе данных. Для интеграции Spring и Hibernate 3 Spring ORM предоставляет два класса — org.springframework.orm.hibernate3.LocalSessionFactoryBean, когда сопоставления hibernate основаны на XML, и org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean для сопоставления на основе аннотаций. Я предоставил простую конфигурацию компонента LocalSessionFactoryBean в комментариях, если вы используете сопоставления на основе XML. AnnotationSessionFactoryBean расширяет класс LocalSessionFactoryBean, поэтому он обладает всеми основными свойствами для интеграции в спящий режим. Свойства понятны сами по себе и в основном связаны со спящим режимом, поэтому я не буду вдаваться в подробности. Но если вам интересно, откуда взялись hibernateProperties, annotatedClasses, вам нужно заглянуть в исходный код класса bean-компонента. Обратите внимание на определение bean-компонента personDAO, как я уже говорил ранее, если нам нужно переключиться на какую-то другую структуру ORM, нам нужно изменить здесь класс реализации и установить любые другие свойства, которые нам нужны.

Тестовая программа Spring 4 Hibernate 3

Наша установка готова, давайте напишем простую программу для тестирования нашего приложения.

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<Person> list = personDAO.list();
		
		for(Person p : list){
			System.out.println("Person List::"+p);
		}
		//close resources
		context.close();	
	}
}

Когда мы выполняем вышеуказанную программу, мы получаем много вывода, связанного с Hibernate, потому что я не настроил ведение журнала должным образом, но это выходит за рамки этого руководства. Однако мы получаем следующий вывод, сгенерированный нашей программой.

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

Изменения интеграции Spring 4 Hibernate 4

Теперь давайте изменим наше приложение, чтобы использовать Hibernate 4 вместо Hibernate 3. Для этой миграции нам нужно внести только следующие изменения конфигурации.

  1. Change the hibernate version to 4.3.5.Final in the pom.xml file, as shown in comments above.

  2. Change the spring bean configuration file, till now you must have figured out that Spring bean configuration file is the key for integration of spring and hibernate framework. Below spring bean configuration file will work for Spring 4 and Hibernate 4 versions.

    <?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 4 SessionFactory Bean definition -->
    <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>
    

    For hibernate 4, we need to use org.springframework.orm.hibernate4.LocalSessionFactoryBean for SessionFactory bean, Spring ORM has merged both the classes for Hibernate 3 and there is a single class now, this is good to avoid confusion. All the other configurations are same as before.

Вот и все, наш проект успешно перенесен на Hibernate 4, аккуратно, не правда ли. Просто измените класс SpringHibernateMain, чтобы использовать spring4.xml для конфигурации bean-компонентов, и он будет работать нормально, вы получите тот же результат, что и раньше. Вы можете загрузить окончательный проект по ссылке ниже и поиграть с другими конфигурациями, чтобы узнать больше.

Скачать проект интеграции Spring Hibernate