Spring Hibernate Integration Example 教程(Spring 4 + Hibernate 3 和 Hibernate 4)
春天是最常用的Java EE框架之一,而Hibernate是最受欢迎的ORM框架。这就是为什么在企业应用中经常使用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 Framework Version: 4.0.3.RELEASE
- Hibernate Core and Hibernate EntityManager Version: 3.6.9.Final and 4.3.5.Final
- Spring ORM Version: 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整合示例项目的结构:
示例项目结构的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 and spring-tx for core Spring functionalities. Notice that I am using version 4.0.3.RELEASE.
- spring-orm dependency for Spring ORM support, it’s required for hibernate integration in our spring project.
- hibernate-entitymanager and hibernate-core dependencies for Hibernate framework. Notice that version is 3.6.9.Final, for using Hibernate 4 all we need is to change it to 4.3.5.Final as commented in above pom.xml file.
- mysql-connector-java for MySQL driver for database connection.
模型类或实体Bean
我们可以使用Hibernate的基于XML的映射,也可以使用基于JPA注解的映射。在这里我使用JPA注解进行映射,因为Hibernate提供了JPA的实现。
package com.Olivia.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 scdev
*
*/
@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对象保存到表中,第二种是从表中获取所有记录并返回Person列表。
package com.Olivia.dao;
import java.util.List;
import com.Olivia.model.Person;
public interface PersonDAO {
public void save(Person p);
public List<Person> list();
}
上述的DAO类实现会是如下的样子。
package com.Olivia.dao;
import java.util.List;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import com.Olivia.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="scdev" />
<property name="password" value="scdev123" />
</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.Olivia.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.Olivia.dao.PersonDAOImpl">
<property name="sessionFactory" ref="hibernate3AnnotatedSessionFactory" />
</bean>
</beans>
我们可以通过两种方式将数据库连接细节提供给Hibernate。第一种方式是通过将所有内容传递给hibernateProperties,第二种方式是创建一个DataSource,然后将其传递给Hibernate。我更喜欢第二种方法,这就是为什么我们有Apache Commons DBCP依赖,以设置数据库连接属性来创建BasicDataSource。对于Spring和Hibernate 3的集成,Spring ORM提供了两个类 – 当Hibernate映射基于XML时,使用org.springframework.orm.hibernate3.LocalSessionFactoryBean,在使用注解进行映射时使用org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean。我已经在注释中提供了LocalSessionFactoryBean的简单bean配置,如果您使用的是基于XML的映射。AnnotationSessionFactoryBean扩展了LocalSessionFactoryBean类,因此它具有所有用于Hibernate集成的基本属性。这些属性具有自解释性,并且大多数与Hibernate相关,因此我不会详细介绍它们。但是,如果您想知道hibernateProperties和annotatedClasses是从哪里来的,您需要查看bean类的源代码。请注意personDAO的bean定义,正如我之前所说,如果我们必须切换到其他ORM框架,我们需要在这里更改实现类并设置任何其他属性。
春天的第四个Hibernate 3测试程序
现在我们的设置已经准备好了,让我们编写一个简单的程序来测试我们的应用。
package com.Olivia.main;
import java.util.List;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import com.Olivia.dao.PersonDAO;
import com.Olivia.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 3改为使用Hibernate 4。对于这次迁移,我们只需要进行以下配置更改。
-
- 将pom.xml文件中的Hibernate版本更改为4.3.5.Final,如上所示的注释。
更改Spring Bean配置文件,到目前为止,您一定已经明白了Spring Bean配置文件是集成Spring和Hibernate框架的关键。下面的Spring Bean配置文件适用于Spring 4和Hibernate 4版本。
com.Olivia.model.Person
org.hibernate.dialect.MySQLDialectthreadfalse
对于Hibernate 4,我们需要使用org.springframework.orm.hibernate4.LocalSessionFactoryBean来配置SessionFactory Bean,Spring ORM已经将Hibernate 3的两个类合并为一个类,这样可以避免混淆。其他所有配置与以前相同。
就是这样,我们的项目成功迁移到了Hibernate 4,很不错吧。只需要将SpringHibernateMain类更改为使用spring4.xml来配置bean,它就能正常工作,你会得到与之前相同的输出结果。你可以从下面的链接下载最终项目,并通过更多的配置进行尝试,以获取更多的学习经验。
下载 Spring Hibernate 整合项目