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