Spring Hibernate 集成示例教程(Spring 4 + Hibernate 3 和 Hibernate 4)
Spring是最常用的 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 框架版本: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 集成示例项目结构
下图显示了最终的项目结构,我们将逐一介绍每个组件。
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 框架的 hibernate-entitymanager 和 hibernate-core 依赖项。请注意,版本是 3.6.9.Final,要使用 Hibernate 4,我们只需将其更改为 4.3.5.Final,如上面的 pom.xml 文件中所述。
- mysql-connector-java 用于 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 对象保存到表中,其次从表中提取所有记录并返回 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;
}
}
Notice that this is the only place where we are using Hibernate related classes. This pattern makes our implementation flexible and easy to migrate from one technology to another. For example, if we want to use iBatis ORM framework, all we need is to provide a DAO implementation for iBatis and then change the spring bean configuration file. In above example, I am using Hibernate session transaction management. But we can also use Spring declarative transaction management using @Transactional
annotation, read more at Spring Transaction Management.
Spring Bean Configuration File for Hibernate 3 Integration
Let’s first look at the spring bean configurations we need for Hibernate 3 integration, we will look into detail later on.
<?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>
There are two ways we can provide database connection details to Hibernate, first by passing everything in hibernateProperties
and second by creating a DataSource and then passing it to hibernate. I prefer the second approach, that’s why we have Apache Commons DBCP dependency to create a BasicDataSource
by setting database connection properties. For Spring and Hibernate 3 integration, Spring ORM provides two classes - org.springframework.orm.hibernate3.LocalSessionFactoryBean
when hibernate mappings are XML based and org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean
for annotations based mapping. I have provided simple bean configuration of LocalSessionFactoryBean
in comments, if you are using XML based mappings. AnnotationSessionFactoryBean
extends LocalSessionFactoryBean
class, so it has all the basic properties for hibernate integration. The properties are self understood and mostly hibernate related, so I will not go into much detail for them. But if you are wondering from where hibernateProperties, annotatedClasses are coming, you need to look into the bean class source code. Notice the bean definition of personDAO, like I said earlier if we have to switch to some other ORM framework, we need to change the implementation class here and set any other properties we need.
Spring 4 Hibernate 3 Test Program
Our setup is ready now, let’s write a simple program to test our application.
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();
}
}
When we execute above program, we get a lot of output related to Hibernate because I haven’t setup logging properly, but that’s out of scope of this tutorial. However we get following output generated by our program.
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 integration changes
Now let’s change our application to use Hibernate 4 instead of Hibernate 3. For this migration, we need to make only following configuration changes.
-
Change the hibernate version to 4.3.5.Final in the pom.xml file, as shown in comments above.
-
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>
对于 Hibernate 4,我们需要使用
org.springframework.orm.hibernate4.LocalSessionFactoryBean
SessionFactory bean,Spring ORM 已将 Hibernate 3 的两个类合并,现在只有一个类,这有利于避免混淆。所有其他配置与以前相同。
就这样,我们的项目成功迁移到 Hibernate 4,是不是很棒。只需更改SpringHibernateMain
用于spring4.xml
bean 配置的类,它就会正常工作,您将获得与以前相同的输出。您可以从以下链接下载最终项目,并尝试更多配置以了解更多信息。
下载 Spring Hibernate 集成项目