Spring和Hibernate整合的关键是:Hibernate的SessionFactory由Spring的IOC容器来创建、Hibernate的事务由Spring的AOP来进行管理。 注意:由于进行整合,Hibernate的配置文件(hibernate.cfg.xml)中的配置,可以全部写到Spring的配置文件当中,因此可以删除hibernate.cfg.xml文件


Hibernate整合前整合后
SessionFactory由开发者创建由Spring IOC容器创建
Transaction由开发者维护(细粒度事务)由Spring AOP实现动态注入(粗粒度事务)


(1)添加jar包

(2)将hibernate配置转移到Spring的配置当中

(3)dao层和service层代码准备

(4)将dao层和service层的类注入到Spring的配置当中

(5)测试


1、添加jar包

添加spring-aop、spring-jdbc、spring-orm相关jar包


spring-aop相关jar包


aopalliance-.jar

aspectjrt.jar

aspectjweaver.jar

spring-aop-3.2.5.RELEASE.jar



spring-jdbc相关jar包


spring-jdbc-3.2.5.RELEASE.jar

spring-tx-3.2.5.RELEASE.jar



spring-orm相关jar包


spring-orm-3.2.5.RELEASE.jar



2、将hibernate配置转移到Spring的配置当中


2.1、删除hibernate.cfg.xml文件

只要删除hibernate.cfg.xml文件即可

2.2、添加bean-base.xml文件

这里面主要保存了原来hibernate.cfg.xml中的配置,主要包括以下三方面内容:数据库连接信息、Hibernate的SessionFactory对象的创建和配置、Hibernate的事务管理。

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/tx
     	http://www.springframework.org/schema/tx/spring-tx.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">

    <!-- 导入外部的properties配置文件 -->
	<context:property-placeholder location="classpath:db.properties" />

	<!-- 配置c3p0数据源 -->
	<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
		<property name="driverClass" value="${driverClass}"></property>
		<property name="jdbcUrl" value="${jdbcUrl}"></property>
		<property name="user" value="${user}"></property>
		<property name="password" value="${password}"></property>
		<!--初始化时获取三个连接,取值应在minPoolSize与maxPoolSize之间。Default: 3 -->
		<property name="initialPoolSize" value="${initialPoolSize}"></property>
		<!--连接池中保留的最小连接数。Default: 3 -->
		<property name="minPoolSize" value="${minPoolSize}"></property>
		<!--连接池中保留的最大连接数。Default: 15 -->
		<property name="maxPoolSize" value="${maxPoolSize}"></property>
		<!--当连接池中的连接耗尽的时候c3p0一次同时获取的连接数。Default: 3 -->
		<property name="acquireIncrement" value="${acquireIncrement}"></property>
		<!--最大空闲时间,1800秒内未使用则连接被丢弃,若为0则永不丢弃。Default: 0 -->
		<property name="maxIdleTime" value="${maxIdleTime}"></property>
	</bean>

<!-- 
	<bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource">
		<property name="driverClass" value="com.mysql.jdbc.Driver"></property>
		<property name="jdbcUrl" value="jdbc:mysql://127.0.0.1:3306/tax_sys"></property>
		<property name="user" value="root"></property>
		<property name="password" value="root"></property>
		<property name="initialPoolSize" value="3"></property>
		<property name="minPoolSize" value="3"></property>
		<property name="maxPoolSize" value="15"></property>
		<property name="acquireIncrement" value="3"></property>
		<property name="maxIdleTime" value="1800"></property>
	</bean>
 -->
	
	<!-- SessionFactory -->
	<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
		<property name="dataSource" ref="dataSource"></property>
		<property name="hibernateProperties">
			<props>
				<prop key="hibernate.dialect">org.hibernate.dialect.MySQL5Dialect</prop>
				<prop key="hibernate.show_sql">true</prop>
				<prop key="hibernate.format_sql">false</prop>
				<prop key="hibernate.hbm2ddl.auto">update</prop>
			</props>
		</property>
		<property name="mappingLocations">
			<list>
				<value>classpath:com/rk/*/entity/*.hbm.xml</value>
			</list>
		</property>
	</bean>
	
	<!-- 事务管理 -->
	<bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
		<property name="sessionFactory" ref="sessionFactory"></property>
	</bean>
	
	<!-- 事务通知 -->
	<tx:advice id="txAdvice" transaction-manager="txManager">
		<tx:attributes>
			<tx:method name="find*" read-only="true"/>
			<tx:method name="get*" read-only="true"/>
			<tx:method name="load*" read-only="true"/>
			<tx:method name="search*" read-only="true"/>
			<tx:method name="list*" read-only="true"/>
			<tx:method name="*" read-only="false" rollback-for="Throwable"/>
		</tx:attributes>
	</tx:advice>
	
	<!-- 利用aop植入事务 -->
	<aop:config>
		<aop:pointcut id="pt" expression="bean(*Service)"/>
		<!-- <aop:pointcut id="pt" expression="execution(* com.rk.test.service.impl.*.*(..))"/> -->
		<aop:advisor advice-ref="txAdvice" pointcut-ref="pt"/>
	</aop:config>

</beans>

在上述配置当中,我们有两处优化的地方:

(1)将数据库的配置参数放置到一个db.properties文件中保存

driverClass=com.mysql.jdbc.Driver
jdbcUrl=jdbc:mysql://127.0.0.1:3306/tax_sys?useUnicode=true&characterEncoding=utf8
user=root
password=root
initialPoolSize=4
minPoolSize=2
maxPoolSize=12
acquireIncrement=2
maxIdleTime=1800

同时,注意bean-base.xml文件中这一配置

    <!-- 导入外部的properties配置文件 -->
	<context:property-placeholder location="classpath:db.properties" />


(2)应用事务时,切入点表达式的改进

原来

<aop:pointcut id="pt" expression="execution(* com.rk.test.service.impl.*.*(..))"/>

转变后

<aop:pointcut id="pt" expression="bean(*Service)"/>



2.3、将bean-base.xml文件引入到applicationContext.xml文件中

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/tx
     	http://www.springframework.org/schema/tx/spring-tx.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">
	
	<import resource="classpath:bean-base.xml"/>

</beans>

重点是下面这一句

<import resource="classpath:bean-base.xml"/>



3、dao层和service层代码准备

PersonDao.java

package com.rk.test.dao;

import java.io.Serializable;

import com.rk.test.entity.Person;

public interface PersonDao {
	Person findById(Serializable id);
	void save(Person p);
}

PersonDaoImpl.java

package com.rk.test.dao.impl;

import java.io.Serializable;

import org.hibernate.Session;
import org.hibernate.SessionFactory;

import com.rk.test.dao.PersonDao;
import com.rk.test.entity.Person;

public class PersonDaoImpl implements PersonDao {
	private SessionFactory sessionFactory;
	public void setSessionFactory(SessionFactory sessionFactory) {
		this.sessionFactory = sessionFactory;
	}
	
	public Person findById(Serializable id) {
		Session session = sessionFactory.getCurrentSession();
		Person p = (Person) session.get(Person.class, id);
		return p;
	}

	public void save(Person p) {
		Session session = sessionFactory.getCurrentSession();
		session.save(p);
	}

}

PersonService.java

package com.rk.test.service;

import java.io.Serializable;

import com.rk.test.entity.Person;

public interface PersonService {
	Person findById(Serializable id);
	void save(Person p);
}

PersonServiceImpl.java

package com.rk.test.service.impl;

import java.io.Serializable;

import com.rk.test.dao.PersonDao;
import com.rk.test.entity.Person;
import com.rk.test.service.PersonService;

public class PersonServiceImpl implements PersonService {
	private PersonDao personDao;
	public void setPersonDao(PersonDao personDao) {
		this.personDao = personDao;
	}
	
	public Person findById(Serializable id) {
//		Person p = new Person();
//		p.setpName("小红");
//		personDao.save(p);
		return personDao.findById(id);
	}

	public void save(Person p) {
		personDao.save(p);
//		int i = 1/ 0;
	}

}



4、将dao层和service层的类注入到Spring的配置当中

bean-dao.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/tx
     	http://www.springframework.org/schema/tx/spring-tx.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">

	<bean id="personDao" class="com.rk.test.dao.impl.PersonDaoImpl">
		<property name="sessionFactory" ref="sessionFactory"></property>
	</bean>

</beans>

bean-service.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/tx
     	http://www.springframework.org/schema/tx/spring-tx.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">

	<bean id="personService" class="com.rk.test.service.impl.PersonServiceImpl">
		<property name="personDao" ref="personDao"></property>
	</bean>

</beans>

applicationContext.xml引入 bean-dao.xml、bean-service.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xmlns:p="http://www.springframework.org/schema/p"
    xmlns:context="http://www.springframework.org/schema/context"
    xmlns:tx="http://www.springframework.org/schema/tx"
    xmlns:aop="http://www.springframework.org/schema/aop"
    xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/tx
     	http://www.springframework.org/schema/tx/spring-tx.xsd
        http://www.springframework.org/schema/aop
        http://www.springframework.org/schema/aop/spring-aop.xsd">
	
	<import resource="classpath:bean-base.xml"/>
	<import resource="classpath:com/rk/*/config/bean-*.xml"/>

</beans>

重点是下面这一句

<import resource="classpath:com/rk/*/config/bean-*.xml"/>


5、测试

测试分为两方面:

(1)普通测试:能够读取一条数据、能够保存一条数据

(2)事务测试:只读事务中不能存储数据、事务出现异常要进行回滚

package com.rk.test;

import org.junit.Before;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import com.rk.test.entity.Person;
import com.rk.test.service.PersonService;

public class TestMerge {
	private ApplicationContext ac;
	@Before
	public void init()
	{
		ac = new ClassPathXmlApplicationContext("applicationContext.xml");
	}
	
	@Test
	public void testFindById()
	{
		PersonService personService = (PersonService) ac.getBean("personService");
		Person p = personService.findById("4028d081564ac44401564ac4478b0000");
		System.out.println(p);
	}
	
	@Test
	public void testSave()
	{
		PersonService personService = (PersonService) ac.getBean("personService");
		Person p = new Person();
		p.setpName("Lucy");
		personService.save(p);
	}
	
	@Test
	public void testTransactionReadOnly()//只读事务,如果在只读事务中出现更新操作则回滚
	{
		PersonService personService = (PersonService) ac.getBean("personService");
		Person p = personService.findById("4028d081564ac44401564ac4478b0000");
		System.out.println(p);
	}
	
	@Test
	public void testTransactionRollback()//回滚事务,如果操作中出现有任务异常则回滚先前的操作
	{
		PersonService personService = (PersonService) ac.getBean("personService");
		Person p = new Person();
		p.setpName("Lily");
		personService.save(p);
	}
	
}