Spring Hibernate集成示例教程(Spring 4 + Hibernate 3和Hibernate 4)

Spring 是最常用的 Java EE 框架之一,Hibernate 是最流行的 ORM 框架。這就是為什麼企業應用中經常使用 Spring Hibernate 組合的原因。最近我寫了很多關於 Spring 教程Hibernate 教程,所以一篇關於 spring hibernate 整合 的文章已經是時候了。

Spring Hibernate

今天在這個教程中,我們將使用 Spring 4 並將其與 Hibernate 3 集成,然後將同一個項目更新為使用 Hibernate 4。由於 Spring 和 Hibernate 都有很多版本,而且 Spring ORM 部件支持 Hibernate 3 和 Hibernate 4,所以最好我列出我項目中使用的所有依賴項。請注意,我已經注意到並不是所有的 Spring 和 Hibernate 版本都是兼容的,下面的版本對我來說是可以的。如果你正在使用其他版本並收到 `java.lang.NoClassDefFoundError`,那麼這意味著它們不兼容。主要是因為 Hibernate 的類已從一個包移動到另一個包,導致了此錯誤。例如,最新的 Hibernate 版本將 `org.hibernate.engine.FilterDefinition` 類移動到 `org.hibernate.engine.spi.FilterDefinition`。

  • Spring 框架版本:4.0.3.RELEASE
  • Hibernate 核心和 Hibernate EntityManager 版本:3.6.9.Final 和 4.3.5.Final
  • Spring ORM 版本:4.0.3.RELEASE

數據庫設置

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;

Spring Hibernate 集成示例項目結構

以下圖顯示了最終的項目結構,我們將逐一查看每個組件。

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 支持,它是我們 Spring 項目中與 Hibernate 集成所需的。
  • hibernate-entitymanager 和 hibernate-core 依賴項用於 Hibernate 框架。請注意,版本是 3.6.9.Final,如果要使用 Hibernate 4,我們只需將其更改為 4.3.5.Final,如上面的 pom.xml 文件中所註釋的那樣。
  • mysql-connector-java 用於 MySQL 數據庫連接的 MySQL 驅動程序。

模型類或實體 Bean

我們可以使用 Hibernate 基於 XML 的映射,也可以使用 JPA 注釋的映射。這裡我使用 JPA 注釋進行映射,因為 Hibernate 提供了 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 類

我們將在 DAO 類中實現兩個方法,第一個是將 Person 物件保存到表中,第二個是從表中提取所有記錄並返回 Persons 列表。

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 框架,我們只需要為 iBatis 提供一個 DAO 實現,然後更改 Spring bean 配置文件。在上面的示例中,我使用了 Hibernate 會話事務管理。但我們還可以使用 Spring 声明式事务管理,使用 @Transactional 注釋,詳細內容請參閱 Spring 事務管理

用於 Hibernate 3 整合的 Spring Bean 配置文件

讓我們首先看一下我們需要為Hibernate 3整合所需的Spring Bean配置,稍後我們將進一步詳細介紹。

<?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中傳遞所有信息,第二種方法是創建一個數據源,然後將其傳遞給Hibernate。我更喜歡第二種方法,這就是為什麼我們需要Apache Commons DBCP依賴庫來創建一個BasicDataSource並設置數據庫連接屬性。對於Spring和Hibernate 3的整合,Spring ORM提供了兩個類 – 當Hibernate映射是基於XML的時,使用org.springframework.orm.hibernate3.LocalSessionFactoryBean,而基於註解的映射則使用org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean。如果您使用的是基於XML的映射,我在注釋中提供了LocalSessionFactoryBean的簡單bean配置。 AnnotationSessionFactoryBean繼承了LocalSessionFactoryBean類,因此它具有Hibernate集成的所有基本屬性。這些屬性是自解釋的,大多數與Hibernate相關,所以我不會詳細介紹它們。但是,如果您想知道hibernatePropertiesannotatedClasses是從哪裡來的,您需要查看bean類的源代碼。請注意personDAO的bean定義,正如我之前所說,如果我們必須切換到其他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 list = personDAO.list();
		
		for(Person p : list){
			System.out.println("Person List::"+p);
		}
		// 關閉資源
		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. 在 pom.xml 文件中將 Hibernate 版本更改為 4.3.5.Final,如上面的註釋所示。

  2. 更改 Spring Bean 配置文件,到目前為止您一定已經明白 Spring Bean 配置文件是整合 Spring 和 Hibernate 框架的關鍵。下面的 Spring Bean 配置文件適用於 Spring 4 和 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>
    
    <!-- Hibernate 4 SessionFactory Bean 定義 -->
    <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>
    

    對於 Hibernate 4,我們需要使用 org.springframework.orm.hibernate4.LocalSessionFactoryBean 作為 SessionFactory bean,Spring ORM 已經合併了 Hibernate 3 的兩個類別,現在只有一個類別,這有助於避免混淆。所有其他配置與之前相同。

就这样,我们的项目已成功迁移到Hibernate 4,很整洁,不是吗?只需将SpringHibernateMain类更改为使用spring4.xml作为bean配置,它将正常工作,您将获得与之前相同的输出。您可以从下面的链接下载最终项目,并尝试使用更多的配置来学习更多。

下载Spring Hibernate集成项目

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