建一个服务层的类,先定义它的接口
PersonService.java
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();
}
package cn.itcast.service;<br/><br/>import java.util.List;<br/><br/>import cn.itcast.bean.Person;<br/><br/>public interface PersonService {<br/><br/> public void save(Person person);<br/><br/> public void update(Person person);<br/><br/> public Person getPerson(Integer personid);<br/><br/> public void delete(Integer personid);<br/><br/> public List<Person> getPersons();<br/><br/>}
PersonServiceBean.java
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();
}
}
package cn.itcast.service.impl;<br/><br/>import java.util.List;<br/><br/>import javax.annotation.Resource;<br/><br/>import org.hibernate.SessionFactory;<br/>import org.springframework.transaction.annotation.Propagation;<br/>import org.springframework.transaction.annotation.Transactional;<br/><br/>import cn.itcast.bean.Person;<br/>import cn.itcast.service.PersonService;<br/><br/>@Transactional<br/>public class PersonServiceBean implements PersonService {<br/> /*<br/> session是通过sessionFactory得到的,目前sessionFactory已经在Spring容器里面被管理了,采用依赖注入可以<br/> 得到sessionFactory,在beans.xml里有这一句<context:annotation-config/>,说明可以采用注解的方式注入<br/> @Resource默认是按名称去匹配的,当对象注入到字段里面上去之后呢,我们就可以通过这个字段来得到session了。<br/> */<br/> @Resource<br/> private SessionFactory sessionFactory;<br/><br/> //方法执行前打开事务<br/> public void save(Person person) {<br/> /*<br/> 在得到session后,有一点要注意的是以前得到session是通过sessionFactory.openSession,在这里要注意,因为Spring<br/> 自动帮我们管理事务,也就是说它会自动帮我们管理session这个对象,这时候我们只需要调用getCurrentSession这个方法<br/> 从Spring容器里得到当前被Spring容器管理的session,而不能采用openSession,如果采用的是openSession的话,<br/> 你打开的session是不受Spring容器管理的,也就是说Spring容器无法对你打开的session进行事务打开,提交。。<br/> 所以要用getCurrentSession方法取得容器中被管理的那个session<br/> */<br/> sessionFactory.getCurrentSession().persist(person);<br/> /*<br/> 不建议使用save方法,persist也是JPA规范里面规定的一个方法,也是用于保存实体的,这<br/> 方法名字上更合理些,因为叫"持久化"比叫"保存"更合理些,实际上两个方法的作用是一样的<br/> */<br/> }<br/> //方法执行后结束事务<br/><br/> public void update(Person person) {<br/> /*<br/> 做更新一般是这样的,当你的对象变成游离状态的对象的时候,这时候才需要对它进行更新。<br/> 如果这对象正处于被容器session管理,tuo管状态的时候,我们不需要调用更新方法也能对它进行更新(调用set方法就行了)<br/> 一般update里面的对象是处于游离状态的<br/> */<br/> sessionFactory.getCurrentSession().merge(person);<br/> /*<br/> 不建议大家用update,merge方法跟JPA里面的方法是对应起来的,同样也是用于把对游离对象的更新同步到数据库,<br/> 返回的是一个tuo管状态的对象<br/> */<br/> }<br/><br/> //一般情况下,如果只是获取数据的话,是不需要开启事务的,因为开事务会对应用的性能产生影响的<br/> @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)<br/> public Person getPerson(Integer personid) {<br/> return (Person) sessionFactory.getCurrentSession().get(Person.class,<br/> personid);<br/> }<br/><br/> public void delete(Integer personid) {<br/> sessionFactory.getCurrentSession().delete(<br/> sessionFactory.getCurrentSession().load(Person.class,personid));<br/> /*<br/> 删除的时候,要求一个实体对象做参数,实体对象怎么获取呢?可以采用get获取,也可以采用load获取。<br/> 这里建议大家采用load,load的性能比get好一些,因为get方法有个数据装配的过程,就是说把数据从数据库<br/> 查询出来后,再把数据封装到实体对象里面去。load方法就没有数据封装的过程,相对效率高很多<br/> */<br/> }<br/><br/> @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)<br/> @SuppressWarnings("unchecked")<br/> public List<Person> getPersons() {<br/> return sessionFactory.getCurrentSession().createQuery("from Person").list();<br/> }<br/><br/>}
开发完业务bean了,每当开发完业务bean,先不要急着跟控制层进行集成,也就是说 CC霜排行榜不要在控制层急于使用业务层对象。
开发完业务层后,需要对业务方法进行单元测试,这是我们在开发过程中需要养成的比较好的习惯。
Person.java
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;
}
}
package cn.itcast.bean;<br/><br/>public class Person {<br/> private Integer id;<br/> private String name;<br/><br/> public Person() {<br/> }<br/><br/> public Person(String name) {<br/> this.name = name;<br/> }<br/><br/> public Integer getId() {<br/> return id;<br/> }<br/><br/> public void setId(Integer id) {<br/> this.id = id;<br/> }<br/><br/> public String getName() {<br/> return name;<br/> }<br/><br/> public void setName(String name) {<br/> this.name = name;<br/> }<br/>}
<?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:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">
<context:annotation-config/>
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
<property name="driverClassName" value="org.gjt.mm.mysql.Driver"/>
<property name="url" value="jdbc:mysql://localhost:3306/springjdbc?useUnicode=true&characterEncoding=UTF-8"/>
<property name="username" value="root"/>
<property name="password" value="456"/>
<!-- 连接池启动时的初始值 -->
<property name="initialSize" value="1"/>
<!-- 连接池的最大值 -->
<property name="maxActive" value="500"/>
<!-- 最大空闲值.当经过一个高峰时间后,连接池可以慢慢将已经用不到的连接慢慢释放一部分,一直减少到maxIdle为止 -->
<property name="maxIdle" value="2"/>
<!-- 最小空闲值.当空闲的连接数少于阀值时,连接池就会预申请去一些连接,以免洪峰来时来不及申请 -->
<property name="minIdle" value="1"/>
</bean>
<!--通过这个配置就可以定义一个sessionFactory,这个对象在容器里面只存在一个,它是一个单例的形式-->
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
<property name="dataSource" ref="dataSource"/> <!--数据源-->
<property name="mappingResources">
<list>
<value>cn/itcast/bean/Person.hbm.xml</value><!--实体bean的映射元数据-->
</list>
</property>
<property name="hibernateProperties">
<value>
hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
hibernate.hbm2ddl.auto=update<!--代表要不要根据映射元数据来生成数据库表结构-->
hibernate.show_sql=false <!--是否打印Hibernate执行的sql-->
hibernate.format_sql=false <!--是否要对它进行格式化-->
<!--这两个主要在测试阶段比较有用-->
</value>
</property>
</bean>
<!--配置事务管理,使用的事务管理器是Spring为我们提供的,针对Hibernate的一个事务管理器-->
<!--只要是通过sessionFactory对象创建的session都会纳入到这个事务管理器中-->
<bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
<!--配置事务采用的申明方式,事务申明的方式有两种:1种是基于XML的方式,1种是基于注解的方式
,这里是使用注解方式来申明事务-->
<!--这段打开了对@Transaction注解的支持,这里用到的事务管理器就是前面提到的txManager-->
<tx:annotation-driven transaction-manager="txManager"/>
<bean id="personService" class="cn.itcast.service.impl.PersonServiceBean"/>
</beans>
<?xml version="1.0" encoding="UTF-8"?><br/><beans xmlns="http://www.springframework.org/schema/beans"<br/> xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"<br/> xmlns:context="http://www.springframework.org/schema/context"<br/> xmlns:aop="http://www.springframework.org/schema/aop"<br/> xmlns:tx="http://www.springframework.org/schema/tx"<br/> xsi:schemaLocation="http://www.springframework.org/schema/beans<br/> http://www.springframework.org/schema/beans/spring-beans-2.5.xsd<br/> http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-2.5.xsd<br/> http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-2.5.xsd<br/> http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-2.5.xsd"><br/> <context:annotation-config/><br/> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"><br/> <property name="driverClassName" value="org.gjt.mm.mysql.Driver"/><br/> <property name="url" value="jdbc:mysql://localhost:3306/springjdbc?useUnicode=true&characterEncoding=UTF-8"/><br/> <property name="username" value="root"/><br/> <property name="password" value="456"/><br/> <!-- 连接池启动时的初始值 --><br/> <property name="initialSize" value="1"/><br/> <!-- 连接池的最大值 --><br/> <property name="maxActive" value="500"/><br/> <!-- 最大空闲值.当经过一个高峰时间后,连接池可以慢慢将已经用不到的连接慢慢释放一部分,一直减少到maxIdle为止 --><br/> <property name="maxIdle" value="2"/><br/> <!-- 最小空闲值.当空闲的连接数少于阀值时,连接池就会预申请去一些连接,以免洪峰来时来不及申请 --><br/> <property name="minIdle" value="1"/><br/> </bean><br/><br/> <!--通过这个配置就可以定义一个sessionFactory,这个对象在容器里面只存在一个,它是一个单例的形式--><br/> <bean id="sessionFactory" class="org.springframework.orm.hibernate3.LocalSessionFactoryBean"><br/> <property name="dataSource" ref="dataSource"/> <!--数据源--><br/> <property name="mappingResources"><br/> <list><br/> <value>cn/itcast/bean/Person.hbm.xml</value><!--实体bean的映射元数据--><br/> </list><br/> </property><br/> <property name="hibernateProperties"><br/> <value><br/> hibernate.dialect=org.hibernate.dialect.MySQL5Dialect<br/> hibernate.hbm2ddl.auto=update<!--代表要不要根据映射元数据来生成数据库表结构--><br/> hibernate.show_sql=false <!--是否打印Hibernate执行的sql--><br/> hibernate.format_sql=false <!--是否要对它进行格式化--><br/> <!--这两个主要在测试阶段比较有用--><br/> </value><br/> </property><br/> </bean><br/><br/> <!--配置事务管理,使用的事务管理器是Spring为我们提供的,针对Hibernate的一个事务管理器--><br/> <!--只要是通过sessionFactory对象创建的session都会纳入到这个事务管理器中--><br/> <bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"><br/> <property name="sessionFactory" ref="sessionFactory"/><br/> </bean><br/><br/> <!--配置事务采用的申明方式,事务申明的方式有两种:1种是基于XML的方式,1种是基于注解的方式<br/> ,这里是使用注解方式来申明事务--><br/> <!--这段打开了对@Transaction注解的支持,这里用到的事务管理器就是前面提到的txManager--><br/> <tx:annotation-driven transaction-manager="txManager"/><br/><br/> <bean id="personService" class="cn.itcast.service.impl.PersonServiceBean"/><br/></beans>
打开数据库,如果存在person表的话,就把它删掉,因为在beans.xml里的 Hibernate属性配置,配置成hibernate.hbm2ddl.auto=update,所以它会自动的根据我们配置的元数据来生成数据库表。
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());
}
}
}
PersonServiceTest.java<br/>package junit.test;<br/><br/>import java.util.List;<br/><br/>import org.junit.BeforeClass;<br/>import org.junit.Test;<br/>import org.springframework.context.ApplicationContext;<br/>import org.springframework.context.support.ClassPathXmlApplicationContext;<br/><br/>import cn.itcast.bean.Person;<br/>import cn.itcast.service.PersonService;<br/><br/>public class PersonServiceTest {<br/> private static PersonService personService;<br/><br/> @BeforeClass<br/> //这个方法是在当单元测试PersonServiceTest实例被构建出来后就会执行<br/> //可以在这个方法里面做一些初始化的操作<br/> public static void setUpBeforeClass() throws Exception {<br/> try {<br/> ApplicationContext applicationContext = new ClassPathXmlApplicationContext("beans.xml");<br/> personService = (PersonService)applicationContext.getBean("personService");<br/> } catch (RuntimeException e) {<br/> e.printStackTrace();<br/> }<br/> }<br/><br/> @Test<br/> public void testSave() {<br/> personService.save(new Person("小张"));<br/> }<br/><br/> @Test<br/> public void testUpdate() {<br/> Person person = personService.getPerson(1);<br/> //....<br/> person.setName("小丽");<br/> personService.update(person);<br/> }<br/><br/> @Test<br/> public void testGetPerson() {<br/> Person person = personService.getPerson(1);<br/> System.out.println(person.getName());<br/> }<br/><br/> @Test<br/> public void testDelete() {<br/> personService.delete(1);<br/> }<br/><br/> @Test<br/> public void testGetPersons() {<br/> List<Person> persons = personService.getPersons();<br/> for(Person person : persons){<br/> System.out.println(person.getName());<br/> }<br/> }<br/><br/>}
运行单元测试的testSave方法,运行成功,看数据库表,表是生成了,数据也进去了,如图:
运行单元测试的testGetPerson方法,运行成功,控制台输出:
小张
运行单元测试的testUpdate方法,运行成功,数据改变了,如图:
运行单元测试的testGetPersons方法,运行成功,控制台输出:小丽
运行单元测试的testDelete方法,运行成功,数据被删了,如图:
这些业务方法都通过了 Junit单元测试,也代表我们的业务代码编写是正确的。一旦确定我们业务层是没问题的,接下来就要进行Struts的集成了。