Spring集成的Hibernate编码与测试

接下来要做的是,在业务层或DAO层里面,怎么通过Spring来使用sessionFactory呢?
   建一个服务层的类,先定义它的接口
PersonService.java

Java代码 复制代码
  1. package cn.itcast.service;   
  2.   
  3. import java.util.List;   
  4.   
  5. import cn.itcast.bean.Person;   
  6.   
  7. public interface PersonService {   
  8.   
  9.     public void save(Person person);   
  10.   
  11.     public void update(Person person);   
  12.   
  13.     public Person getPerson(Integer personid);   
  14.   
  15.     public void delete(Integer personid);   
  16.   
  17.     public List<Person> getPersons();   
  18.   
  19. }  
package cn.itcast.service;

import java.util.List;

import cn.itcast.bean.Person;

public interface PersonService {

	public void save(Person person);

	public void update(Person person);

	public Person getPerson(Integer personid);

	public void delete(Integer personid);

	public List<Person> getPersons();

}




PersonServiceBean.java

Java代码 复制代码
  1. package cn.itcast.service.impl;   
  2.   
  3. import java.util.List;   
  4.   
  5. import javax.annotation.Resource;   
  6.   
  7. import org.hibernate.SessionFactory;   
  8. import org.springframework.transaction.annotation.Propagation;   
  9. import org.springframework.transaction.annotation.Transactional;   
  10.   
  11. import cn.itcast.bean.Person;   
  12. import cn.itcast.service.PersonService;   
  13.   
  14. @Transactional  
  15. public class PersonServiceBean implements PersonService {   
  16.     /*  
  17.      session是通过sessionFactory得到的,目前sessionFactory已经在Spring容器里面被管理了,采用依赖注入可以  
  18.      得到sessionFactory,在beans.xml里有这一句<context:annotation-config/>,说明可以采用注解的方式注入  
  19.      @Resource默认是按名称去匹配的,当对象注入到字段里面上去之后呢,我们就可以通过这个字段来得到session了。  
  20.      */  
  21.     @Resource  
  22.     private SessionFactory sessionFactory;   
  23.   
  24.     //方法执行前打开事务   
  25.     public void save(Person person) {   
  26.         /*  
  27.          在得到session后,有一点要注意的是以前得到session是通过sessionFactory.openSession,在这里要注意,因为Spring  
  28.         自动帮我们管理事务,也就是说它会自动帮我们管理session这个对象,这时候我们只需要调用getCurrentSession这个方法  
  29.         从Spring容器里得到当前被Spring容器管理的session,而不能采用openSession,如果采用的是openSession的话,  
  30.         你打开的session是不受Spring容器管理的,也就是说Spring容器无法对你打开的session进行事务打开,提交。。  
  31.         所以要用getCurrentSession方法取得容器中被管理的那个session  
  32.         */  
  33.         sessionFactory.getCurrentSession().persist(person);   
  34.         /*  
  35.          不建议使用save方法,persist也是JPA规范里面规定的一个方法,也是用于保存实体的,这  
  36.          方法名字上更合理些,因为叫"持久化"比叫"保存"更合理些,实际上两个方法的作用是一样的  
  37.          */  
  38.     }   
  39.     //方法执行后结束事务   
  40.   
  41.     public void update(Person person) {   
  42.         /*  
  43.           做更新一般是这样的,当你的对象变成游离状态的对象的时候,这时候才需要对它进行更新。  
  44.           如果这对象正处于被容器session管理,tuo管状态的时候,我们不需要调用更新方法也能对它进行更新(调用set方法就行了)  
  45.           一般update里面的对象是处于游离状态的  
  46.          */  
  47.         sessionFactory.getCurrentSession().merge(person);   
  48.         /*  
  49.           不建议大家用update,merge方法跟JPA里面的方法是对应起来的,同样也是用于把对游离对象的更新同步到数据库,  
  50.           返回的是一个tuo管状态的对象  
  51.          */  
  52.     }   
  53.   
  54.     //一般情况下,如果只是获取数据的话,是不需要开启事务的,因为开事务会对应用的性能产生影响的   
  55.     @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)   
  56.     public Person getPerson(Integer personid) {   
  57.         return (Person) sessionFactory.getCurrentSession().get(Person.class,   
  58.                 personid);   
  59.     }   
  60.   
  61.     public void delete(Integer personid) {   
  62.         sessionFactory.getCurrentSession().delete(   
  63.                         sessionFactory.getCurrentSession().load(Person.class,personid));   
  64.         /*  
  65.          删除的时候,要求一个实体对象做参数,实体对象怎么获取呢?可以采用get获取,也可以采用load获取。  
  66.          这里建议大家采用load,load的性能比get好一些,因为get方法有个数据装配的过程,就是说把数据从数据库  
  67.          查询出来后,再把数据封装到实体对象里面去。load方法就没有数据封装的过程,相对效率高很多  
  68.          */  
  69.     }   
  70.   
  71.     @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)   
  72.     @SuppressWarnings("unchecked")   
  73.     public List<Person> getPersons() {   
  74.         return sessionFactory.getCurrentSession().createQuery("from Person").list();   
  75.     }   
  76.   
  77. }  
package cn.itcast.service.impl;

import java.util.List;

import javax.annotation.Resource;

import org.hibernate.SessionFactory;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import cn.itcast.bean.Person;
import cn.itcast.service.PersonService;

@Transactional
public class PersonServiceBean implements PersonService {
	/*
	 session是通过sessionFactory得到的,目前sessionFactory已经在Spring容器里面被管理了,采用依赖注入可以
	 得到sessionFactory,在beans.xml里有这一句<context:annotation-config/>,说明可以采用注解的方式注入
	 @Resource默认是按名称去匹配的,当对象注入到字段里面上去之后呢,我们就可以通过这个字段来得到session了。
	 */
	@Resource
	private SessionFactory sessionFactory;

	//方法执行前打开事务
	public void save(Person person) {
		/*
		 在得到session后,有一点要注意的是以前得到session是通过sessionFactory.openSession,在这里要注意,因为Spring
	 	自动帮我们管理事务,也就是说它会自动帮我们管理session这个对象,这时候我们只需要调用getCurrentSession这个方法
	 	从Spring容器里得到当前被Spring容器管理的session,而不能采用openSession,如果采用的是openSession的话,
	 	你打开的session是不受Spring容器管理的,也就是说Spring容器无法对你打开的session进行事务打开,提交。。
	 	所以要用getCurrentSession方法取得容器中被管理的那个session
	 	*/
		sessionFactory.getCurrentSession().persist(person);
		/*
		 不建议使用save方法,persist也是JPA规范里面规定的一个方法,也是用于保存实体的,这
		 方法名字上更合理些,因为叫"持久化"比叫"保存"更合理些,实际上两个方法的作用是一样的
		 */
	}
	//方法执行后结束事务

	public void update(Person person) {
		/*
		  做更新一般是这样的,当你的对象变成游离状态的对象的时候,这时候才需要对它进行更新。
		  如果这对象正处于被容器session管理,tuo管状态的时候,我们不需要调用更新方法也能对它进行更新(调用set方法就行了)
		  一般update里面的对象是处于游离状态的
		 */
		sessionFactory.getCurrentSession().merge(person);
		/*
		  不建议大家用update,merge方法跟JPA里面的方法是对应起来的,同样也是用于把对游离对象的更新同步到数据库,
		  返回的是一个tuo管状态的对象
		 */
	}

	//一般情况下,如果只是获取数据的话,是不需要开启事务的,因为开事务会对应用的性能产生影响的
	@Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
	public Person getPerson(Integer personid) {
		return (Person) sessionFactory.getCurrentSession().get(Person.class,
				personid);
	}

	public void delete(Integer personid) {
		sessionFactory.getCurrentSession().delete(
						sessionFactory.getCurrentSession().load(Person.class,personid));
		/*
		 删除的时候,要求一个实体对象做参数,实体对象怎么获取呢?可以采用get获取,也可以采用load获取。
		 这里建议大家采用load,load的性能比get好一些,因为get方法有个数据装配的过程,就是说把数据从数据库
		 查询出来后,再把数据封装到实体对象里面去。load方法就没有数据封装的过程,相对效率高很多
		 */
	}

	@Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
	@SuppressWarnings("unchecked")
	public List<Person> getPersons() {
		return sessionFactory.getCurrentSession().createQuery("from Person").list();
	}

}


开发完业务bean了,每当开发完业务bean,先不要急着跟控制层进行集成,也就是说不要在控制层急于使用业务层对象。
开发完业务层后,需要对业务方法进行单元测试,这是我们在开发过程中需要养成的比较好的习惯。
Person.java

Java代码 复制代码
  1. package cn.itcast.bean;   
  2.   
  3. public class Person {   
  4.     private Integer id;   
  5.     private String name;   
  6.   
  7.     public Person() {   
  8.     }   
  9.   
  10.     public Person(String name) {   
  11.         this.name = name;   
  12.     }   
  13.   
  14.     public Integer getId() {   
  15.         return id;   
  16.     }   
  17.   
  18.     public void setId(Integer id) {   
  19.         this.id = id;   
  20.     }   
  21.   
  22.     public String getName() {   
  23.         return name;   
  24.     }   
  25.   
  26.     public void setName(String name) {   
  27.         this.name = name;   
  28.     }   
  29. }  
package cn.itcast.bean;

public class Person {
	private Integer id;
	private String name;

	public Person() {
	}

	public Person(String name) {
		this.name = name;
	}

	public Integer getId() {
		return id;
	}

	public void setId(Integer id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}
}

 

Xml代码 复制代码
  1. <?xml version="1.0" encoding="UTF-8"?>  
  2. <beans xmlns="http://www.springframework.org/schema/beans"  
  3.        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"  
  4.        xmlns:context="http://www.springframework.org/schema/context"  
  5.        xmlns:aop="http://www.springframework.org/schema/aop"  
  6.        xmlns:tx="http://www.springframework.org/schema/tx"  
  7.        xsi:schemaLocation="http://www.springframework.org/schema/beans   
  8.            http://www.springframework.org/schema/beans/spring-beans-2.5.xsd   
  9.            http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd   
  10.            http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd   
  11.            http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">  
  12.      <context:annotation-config/>  
  13.      <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">  
  14.         <property name="driverClassName" value="org.gjt.mm.mysql.Driver"/>  
  15.         <property name="url" value="jdbc:mysql://localhost:3306/springjdbc?useUnicode=true&amp;characterEncoding=UTF-8"/>  
  16.         <property name="username" value="root"/>  
  17.         <property name="password" value="456"/>  
  18.          <!-- 连接池启动时的初始值 -->  
  19.          <property name="initialSize" value="1"/>  
  20.          <!-- 连接池的最大值 -->  
  21.          <property name="maxActive" value="500"/>  
  22.          <!-- 最大空闲值.当经过一个高峰时间后,连接池可以慢慢将已经用不到的连接慢慢释放一部分,一直减少到maxIdle为止 -->  
  23.          <property name="maxIdle" value="2"/>  
  24.          <!--  最小空闲值.当空闲的连接数少于阀值时,连接池就会预申请去一些连接,以免洪峰来时来不及申请 -->  
  25.          <property name="minIdle" value="1"/>  
  26.       </bean>  
  27.   
  28.     <!--通过这个配置就可以定义一个sessionFactory,这个对象在容器里面只存在一个,它是一个单例的形式-->  
  29.     <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">  
  30.          <property name="dataSource" ref="dataSource"/> <!--数据源-->  
  31.          <property name="mappingResources">  
  32.             <list>  
  33.               <value>cn/itcast/bean/Person.hbm.xml</value><!--实体bean的映射元数据-->  
  34.             </list>  
  35.          </property>  
  36.          <property name="hibernateProperties">  
  37.             <value>  
  38.                 hibernate.dialect=org.hibernate.dialect.MySQL5Dialect   
  39.                 hibernate.hbm2ddl.auto=update<!--代表要不要根据映射元数据来生成数据库表结构-->  
  40.                 hibernate.show_sql=false <!--是否打印Hibernate执行的sql-->  
  41.                 hibernate.format_sql=false <!--是否要对它进行格式化-->  
  42.                 <!--这两个主要在测试阶段比较有用-->  
  43.               </value>  
  44.          </property>  
  45.     </bean>  
  46.   
  47.     <!--配置事务管理,使用的事务管理器是Spring为我们提供的,针对Hibernate的一个事务管理器-->  
  48.     <!--只要是通过sessionFactory对象创建的session都会纳入到这个事务管理器中-->  
  49.     <bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">  
  50.         <property name="sessionFactory" ref="sessionFactory"/>  
  51.     </bean>  
  52.   
  53.     <!--配置事务采用的申明方式,事务申明的方式有两种:1种是基于XML的方式,1种是基于注解的方式   
  54.     ,这里是使用注解方式来申明事务-->  
  55.     <!--这段打开了对@Transaction注解的支持,这里用到的事务管理器就是前面提到的txManager-->  
  56.     <tx:annotation-driven transaction-manager="txManager"/>  
  57.   
  58.     <bean id="personService" class="cn.itcast.service.impl.PersonServiceBean"/>  
  59. </beans>  



打开数据库,如果存在person表的话,就把它删掉,因为在beans.xml里的Hibernate属性配置,配置成hibernate.hbm2ddl.auto=update,所以它会自动的根据我们配置的元数据来生成数据库表。

Java代码 复制代码
  1. PersonServiceTest.java   
  2. package junit.test;   
  3.   
  4. import java.util.List;   
  5.   
  6. import org.junit.BeforeClass;   
  7. import org.junit.Test;   
  8. import org.springframework.context.ApplicationContext;   
  9. import org.springframework.context.support.ClassPathXmlApplicationContext;   
  10.   
  11. import cn.itcast.bean.Person;   
  12. import cn.itcast.service.PersonService;   
  13.   
  14. public class PersonServiceTest {   
  15.     private static PersonService personService;   
  16.   
  17.     @BeforeClass  
  18.     //这个方法是在当单元测试PersonServiceTest实例被构建出来后就会执行   
  19.     //可以在这个方法里面做一些初始化的操作   
  20.     public static void setUpBeforeClass() throws Exception {   
  21.         try {   
  22.             ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");   
  23.             personService = (PersonService)applicationContext.getBean("personService");   
  24.         } catch (RuntimeException e) {   
  25.             e.printStackTrace();   
  26.         }   
  27.     }   
  28.   
  29.     @Test  
  30.     public void testSave() {   
  31.         personService.save(new Person("小张"));   
  32.     }   
  33.   
  34.     @Test  
  35.     public void testUpdate() {   
  36.         Person person = personService.getPerson(1);   
  37.         //....   
  38.         person.setName("小丽");   
  39.         personService.update(person);   
  40.     }   
  41.   
  42.     @Test  
  43.     public void testGetPerson() {   
  44.         Person person = personService.getPerson(1);   
  45.         System.out.println(person.getName());   
  46.     }   
  47.   
  48.     @Test  
  49.     public void testDelete() {   
  50.         personService.delete(1);   
  51.     }   
  52.   
  53.     @Test  
  54.     public void testGetPersons() {   
  55.         List<Person> persons = personService.getPersons();   
  56.         for(Person person : persons){   
  57.             System.out.println(person.getName());   
  58.         }   
  59.     }   
  60.   
  61. }  
PersonServiceTest.java
package junit.test;

import java.util.List;

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

import cn.itcast.bean.Person;
import cn.itcast.service.PersonService;

public class PersonServiceTest {
	private static PersonService personService;

	@BeforeClass
	//这个方法是在当单元测试PersonServiceTest实例被构建出来后就会执行
	//可以在这个方法里面做一些初始化的操作
	public static void setUpBeforeClass() throws Exception {
		try {
			ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");
			personService = (PersonService)applicationContext.getBean("personService");
		} catch (RuntimeException e) {
			e.printStackTrace();
		}
	}

	@Test
	public void testSave() {
		personService.save(new Person("小张"));
	}

	@Test
	public void testUpdate() {
		Person person = personService.getPerson(1);
		//....
		person.setName("小丽");
		personService.update(person);
	}

	@Test
	public void testGetPerson() {
		Person person = personService.getPerson(1);
		System.out.println(person.getName());
	}

	@Test
	public void testDelete() {
		personService.delete(1);
	}

	@Test
	public void testGetPersons() {
		List<Person> persons = personService.getPersons();
		for(Person person : persons){
			System.out.println(person.getName());
		}
	}

}



运行单元测试的testSave方法,运行成功,看数据库表,表是生成了,数据也进去了,如图:


运行单元测试的testGetPerson方法,运行成功,控制台输出:
小张

运行单元测试的testUpdate方法,运行成功,数据改变了,如图:



运行单元测试的testGetPersons方法,运行成功,控制台输出:小丽

运行单元测试的testDelete方法,运行成功,数据被删了,如图:




这些业务方法都通过了单元测试,也代表我们的业务代码编写是正确的。一旦确定我们业务层是没问题的,接下来就要进行Struts的集成了。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值