使用Annotation并对DAO层封装具有分页功能的S2SH整合实例
李顺利
2010年1月24日
目录
关键词... 2
前言... 2
开发环境... 2
开发步骤... 2
环境的集成... 2
Struts2.1.8所需Jar包... 2
Hibernate3.3所需Jar包... 3
Spring3.0所需Jar包... 3
基于Annotation的Struts配置... 4
基于Annotation的Hibernate配置... 5
基于Annotation的Spring配置... 10
DAO层封装... 12
分页... 19
业务逻辑... 21
测试... 22
实例结果... 23
参考网站... 23
源码下载... 23
学习探讨... 23
关键词
使用Annotation并对DAO层封装具有分页功能的S2SH整合实例,李顺利,Annotation,DAO层封装,分页,SSH整合,实例,黎活明,传智播客,巴巴运动网
前言
现在Annotation越来越流行,最近一段时间也学了一些,EJB3.0、Hibernate、Spring等都很好地支持Annotation,而且熟悉了Annotation的话整个项目开发时间会缩短,代码封装比较好,但是封装带来的就是代码阅读就比较困难了。Annotation也是一门知识,可以选择使用Annotation还是其他。个人认为由Sun官方支持的EJB规范会越来越流行,此时如果使用基于Annotation的SSH框架很容易转移到Struts+EJB+Spring的项目中,而且使用Annotation,很容易实现0配置,像在这个实例中就一个配置,这样避免了配置文件多而不知所措的情况。
开发环境
Jdk1.5+Struts2.1.8+Hibernate3.3+Spring3.0+MySql5.0+MyEclipse8.0
开发步骤
环境的集成
到官网下载上面开发环境中的框架和工具,安装完成后。在Myeclipse中新建名为SSHWithAnnotationDemo的web project,添加SSH整合所需要的包,这里详细说一下需要哪些包?
Struts2.1.8所需Jar包
xwork-core-2.1.6.jar、aopalliance-1.0.jar、commons-logging-1.0.4.jar、commons-fileupload-1.2.1.jarcommons-io-1.3.2.jar、freemarker-2.3.15.jar、ognl-2.7.3.jar、struts2-convention-plugin-2.1.8.1.jar、struts2-core-2.1.8.1.jar、struts2-spring-plugin-2.1.8.jar
其中下文会对struts2-convention-plugin插件进行详细讲解。
Hibernate3.3所需Jar包
slf4j-log4j12.jar、antlr-2.7.6.jar、commons-collections-3.1.jar、dom4j-1.6.1.jar、ejb3-persistence.jar、hibernate3.jar、hibernate-annotations.jar、hibernate-commons-annotations.jar、javassist-3.9.0.GA.jar、jta-1.1.jarlog4j.jar、slf4j-api-1.5.8.jar
Spring3.0所需Jar包
org.springframework.web-3.0.0.RC1.jar、org.springframework.aop-3.0.0.RC1.jar、org.springframework.asm-3.0.0.RC1.jarorg.springframework.beans-3.0.0.RC1.jar、
org.springframework.context-3.0.0.RC1.jar、org.springframework.core-3.0.0.RC1.jar、org.springframework.expression-3.0.0.RC1.jar、org.springframework.jdbc-3.0.0.RC1.jar、org.springframework.orm-3.0.0.RC1.jar、org.springframework.test-3.0.0.RC1.jar、org.springframework.transaction-3.0.0.RC1.jar
还有一些其他的辅助Jar包:
mysql-connector-java-5.1.7-bin.jar、aspectjweaver.jar、commons-dbcp-1.2.2.jar、commons-pool.jar、junit-4.6.jar
上面的Jar包都可以在相应的框架Jar文件夹里面找到,具体的Jar包作用如果不清楚的话请Google一下。为了方便,顺利提供所有这些Jar包下载。
顺利提供下载:
文 件 名:Struts2.1.8+Hibernate3.3+Spring3.0整合所需Jar包.rar
下载地址:http://usc.googlecode.com/files/Struts2.1.8%2BHibernate3.3%2BSpring3.0%E6%95%B4%E5%90%88%E6%89%80%E9%9C%80Jar%E5%8C%85.rar
加入Jar包后,就可以进行SSH框架的整合了。
基于Annotation的Struts配置
使用Annotation对Struts配置可以实现0配置,这个时候就不需要对Struts.xml进行任何的配置,0配置的实现主要是使用struts2-convention-plugin插件。大致介绍下convention-plugin插件。
1. 默认所有的结果页面都存储在WEB-INF/content下
2. 命名规则:去掉类名的Action部分。然后将将每个分部的首字母转为小写,用’-’分割。
a) 举例:TestAction,那么访问的时候就是test.action;
b) 举例:StudentListAction,那么访问的时候就是student-list.action。
3. 常用的Annotation
a) @Controller:申明Struts为控制层;
b) @Scope("prototype"):申明Struts的范围为原型;
c) @Results:全局的结果集,可以配置execute执行后跳转的页面。
像@Results({ @Result(name = "success", location = "teacher/teacherList.jsp"), @Result(name = "input", location = "/index.jsp") })
通过convention-plugin插件就可以很简单的配置Struts的配置, 如果想更好地了解convention-plugin插件请查看下面的网站或者自己Google一下。
http://cwiki.apache.org/WW/convention-plugin.html
http://javeye.javaeye.com/blog/358744
http://yzl45.javaeye.com/blog/346632
代码举例:
import org.apache.struts2.convention.annotation.Result; import org.apache.struts2.convention.annotation.Results; import org.springframework.context.annotation.Scope; import org.springframework.stereotype.Controller;
import com.opensymphony.xwork2.ActionSupport; /** * 测试convention-plugin插件 */
@Controller @Scope("prototype") @Results( { @Result(name = "success", location = "test/test.jsp"), @Result(name = "input", location = "/index.jsp") }) //成功的页面会跳到WebRoot/WEB-INF/content/test/test.jsp,失败会跳到WebRoot/index.jsp public class TestAction extends ActionSupport { /* * @see com.opensymphony.xwork2.ActionSupport#execute() */ @Override public String execute() throws Exception { System.out.println("测试convention-plugin插件"); return INPUT; } }
|
基于Annotation的Hibernate配置
Hibernate的Annotation方式很类似于EJB中的JPA,主要的Annotation注解是:@Entity、@Table、@Id、@GeneratedValue、@Column 。具体的注解请上网查看一下。这里介绍一种简便的方法生成基于Annotation的Hibernate持久类。
1. 使用Myeclipse添加对Hibernate的支持
右键项目,选择MyEclipse后选择Add hibernate Capabilities(一般都会先添加对Spring的支持后在添加对Hibernate的支持,这样会使用Spring管理Hibernate)
这个时候就不需要选择Jar包了,Hibernate的Jar已经加入进来,Next,选择Spring的配置文件,这样可以使用Spring进行管理Hibernate(这也是为什么要先添加对Spirng的支持),Next
选择已经存在的Spring配置文件
后选择已经创建好的DateSource。
即可,详情请阅读Struts+Spring+Hibernate整合注册登录——使用Myeclipse快速开发,里面有详细的介绍。
2. 进入生成DB Brower视图(可以通过windows->show View找到)
找到后连接MySql数据库后,即可生成Hibernate的持久类
生成的实例代码
@Entity @Table(name = "student", catalog = "test") public class Student implements java.io.Serializable {
// Fields
private Integer no; private String name; private String sex; private Integer age; private Double score; private Date eduTime;
// Constructors
/** default constructor */ public Student() { }
/** minimal constructor */ public Student(String name, String sex) { this.name = name; this.sex = sex; }
/** full constructor */ public Student(String name, String sex, Integer age, Double score, Date eduTime) { this.name = name; this.sex = sex; this.age = age; this.score = score; this.eduTime = eduTime; }
// Property accessors @Id @GeneratedValue @Column(name = "no", unique = true, nullable = false) public Integer getNo() { return this.no; }
public void setNo(Integer no) { this.no = no; }
@Column(name = "name", nullable = false, length = 20) public String getName() { return this.name; } //…… } |
基于Annotation的Spring配置
类似上面添加对Spring的支持(在Hibernate支持前添加至此),主要是applicationContext.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: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-3.0.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.0.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd"> <!--配置文件导入 --> <bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"> <property name="location"> <value>classpath:dataSource.properties</value> </property> </bean>
<!--数据源 --> <bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"> <property name="driverClassName" value="${mysql.database.driver}"></property> <property name="url" value="${mysql.database.url}"></property> <property name="username" value="${mysql.database.user}"></property> <property name="password" value="${mysql.database.password}"></property> <property name="maxActive" value="${mysql.database.maxActive}"></property> <property name="maxIdle" value="${mysql.database.maxIdle}"></property> <property name="maxWait" value="${mysql.database.maxWait}"></property> </bean>
<!--session工厂,里面可以配置Hibernate的映射文件,使用annotatedClasses--> <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean"> <property name="dataSource"> <ref bean="dataSource" /> </property> <property name="hibernateProperties"> <props> <!--hibernate的方言,建议改成MySQL5Dialect--> <prop key="hibernate.dialect"> org.hibernate.dialect.MySQL5Dialect </prop> <!--开发的时候尽量打开true --> <prop key="hibernate.show_sql">false</prop> </props> </property>
<!--主键Bean类 --> <property name="annotatedClasses"> <list> <value>org.usc.beans.Student</value> <value>org.usc.beans.Teacher</value> </list> </property> </bean>
<!-- 配置事务管理器 --> <bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager"> <property name="sessionFactory"> <ref bean="sessionFactory" /> </property> </bean>
<!-- 配置事务的传播特性 --> <tx:advice id="txAdvice" transaction-manager="transactionManager"> <tx:attributes> <tx:method name="save*" propagation="REQUIRED" /> <tx:method name="update*" propagation="REQUIRED" /> <tx:method name="delete*" propagation="REQUIRED" /> <tx:method name="*" read-only="true" /> </tx:attributes> </tx:advice>
<!-- 那些类的哪些方法参与事务 --> <aop:config> <aop:pointcut id="allServiceMethod" expression="execution(* org.usc.daos.*.*.*(..))" /> <aop:advisor pointcut-ref="allServiceMethod" advice-ref="txAdvice" /> </aop:config>
<!-- 使Spring关注Annotation --> <context:annotation-config />
<!-- 让Spring通过自动扫描来查询和管理Bean --> <context:component-scan base-package="org.usc" />
</beans> |
上面的注释都很详细,请大家查看,数据源通过dataSource.properties读入。
dataSource.properties:
#mysql mysql.database.driver=com.mysql.jdbc.Driver mysql.database.url=jdbc\:mysql\://127.0.0.1\:3306/test?useUnicode\=true&amp;characterEncoding\=utf-8 mysql.database.user=root mysql.database.password=lishunli mysql.database.maxActive=100 mysql.database.maxIdle=30 mysql.database.maxWait=500
|
至此,基于Annotation的SSH框架的基本已经搭建完成。
DAO层封装
通过对泛型的支持,Dao层封装才更能体现封装性,只要基础封装类,就可以使用Dao层的CURD方法,很方便。
IBaseDao泛型接口类:
package org.usc.daos.base;
import java.io.Serializable; import java.util.LinkedHashMap; import java.util.List;
import org.usc.beans.base.QueryResult;
/** * DAO层封装接口,包含常用的CURD和分页操作 * * @author <a href="http://www.blogjava.net/lishunli/" target="_blank">ShunLi</a> * @notes Created on 2010-1-24<br> * Revision of last commit:$Revision: 635 $<br> * Author of last commit:$Author: [email protected] $<br> * Date of last commit:$Date: 2010-01-25 19:06:35 +0800 (周一, 25 一月 2010) $<br> * <p> */ public interface IBaseDao<T> {
/** * 根据属性查找对象 * * @param propertyName * 属性(对应Bean) * @param value * 属性 * @return 根据属性查找对象 */ public List<T> findByProperty(String propertyName, Object value);
/** * 根据实体查找对象 * * @param entiey * 实体(T类型) * @return 根据属性查找对象 */ public List<T> findByEntity(Object entiey);
/** * 获取记录总数 * * @param entityClass * 实体类 * @return */ public int getCount();
/** * 保存实体 * * @param entity * 实体id */ public void save(Object entity);
/** * 更新实体 * * @param entity * 实体id */ public void update(Object entity);
/** * 删除实体 * * @param entityClass * 实体类 * @param entityids * 实体id数组 */ public void delete(Serializable... entityids);
/** * 获取实体 * * @param <T> * @param entityClass * 实体类 * @param entityId * 实体id * @return */ public T find(Serializable entityId);
/** * 获取分页数据 * @param firstindex 开始索引 * @param maxresult 每页显示记录数 * @param wherejpql where语句 * @param queryParams 查询参数 * @param orderby 排序序列 * @return 分页数据 */ public QueryResult<T> getScrollData(final int firstindex, final int maxresult, final String wherejpql, final Object[] queryParams, final LinkedHashMap<String, String> orderby);
/** * 获取分页数据 * @param firstindex 开始索引 * @param maxresult 每页显示记录数 * @param wherejpql where语句 * @param queryParams 查询参数 * @return 分页数据 */ public QueryResult<T> getScrollData(final int firstindex, final int maxresult, final String wherejpql, final Object[] queryParams);
/** * 获取分页数据 * @param firstindex 开始索引 * @param maxresult 每页显示记录数 * @param orderby 排序序列 * @return 分页数据 */ public QueryResult<T> getScrollData(final int firstindex, final int maxresult, final LinkedHashMap<String, String> orderby);
/** * 获取分页数据 * @param firstindex 开始索引 * @param maxresult 每页显示记录数 * @return 分页数据 */ public QueryResult<T> getScrollData(final int firstindex, final int maxresult);
/** * 获取所有对象 * * @return 所有对象 */ public QueryResult<T> getScrollData(); }
|
BaseDaoSupport泛型实现类:
package org.usc.daos.base;
import java.beans.Introspector; import java.beans.PropertyDescriptor; import java.io.Serializable; import java.lang.reflect.Method; import java.sql.SQLException; import java.util.LinkedHashMap; import java.util.List;
import javax.annotation.Resource; import javax.persistence.EmbeddedId; import javax.persistence.Entity;
import org.hibernate.HibernateException; import org.hibernate.Query; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.springframework.orm.hibernate3.HibernateCallback; import org.springframework.orm.hibernate3.support.HibernateDaoSupport; import org.usc.beans.base.QueryResult; import org.usc.utils.base.GenericsUtils;
/** * DAO层封装使用了泛型,包含常用的CURD和分页操作 * * @author <a href="http://www.blogjava.net/lishunli/" target="_blank">ShunLi</a> * @notes Created on 2010-1-24<br> * Revision of last commit:$Revision: 650 $<br> * Author of last commit:$Author: [email protected] $<br> * Date of last commit:$Date: 2010-03-09 20:44:14 +0800 (周二, 09 三月 2010) $<br> * <p> */ @SuppressWarnings("unchecked") public abstract class BaseDaoSupport<T> extends HibernateDaoSupport implements IBaseDao<T> { protected Class<T> entityClass = GenericsUtils.getSuperClassGenricType(this.getClass()); protected String entityClassName = getEntityName(this.entityClass); protected String keyFieldName = getKeyFieldName(this.entityClass);
// 为父类HibernateDaoSupport注入sessionFactory的值 @Resource(name = "sessionFactory") public void setSuperSessionFactory(SessionFactory sessionFactory) { super.setSessionFactory(sessionFactory); }
/* * @see org.usc.daos.DAO#findByEntity(java.lang.Object) */ public List<T> findByEntity(Object entiey) { return super.getHibernateTemplate().findByExample(entiey); }
/* * @see org.usc.daos.DAO#findByProperty(java.lang.String, java.lang.Object) */ public List<T> findByProperty(String propertyName, Object value) { String queryString = "from " + entityClassName + " o where o." + propertyName + "= ?"; return super.getHibernateTemplate().find(queryString, value); }
/* * @see org.usc.daos.DAO#delete(java.io.Serializable[]) */ public void delete(Serializable... entityids) { for (Object id : entityids) { super.getHibernateTemplate().delete(find((Serializable) id)); } }
/* * @see org.usc.daos.DAO#find(java.io.Serializable) */ public T find(Serializable entityId) { if (null != entityId) return (T) super.getHibernateTemplate().get(entityClass, entityId); return null; }
/* * @see org.usc.daos.DAO#getCount() */ public int getCount() { String hql = "select count( " + keyFieldName + ") from " + entityClassName; int count = Integer.parseInt(super.getHibernateTemplate().find(hql).get(0).toString()); return count; }
public void save(Object entity) { super.getHibernateTemplate().save(entity); }
/* * @see org.usc.daos.DAO#update(java.lang.Object) */ public void update(Object entity) { super.getHibernateTemplate().update(entity); }
/* * @see org.usc.daos.DAO#getScrollData(int, int, java.lang.String, java.lang.Object[], java.util.LinkedHashMap) */ public QueryResult<T> getScrollData(final int firstindex, final int maxresult, final String wherejpql, final Object[] queryParams, final LinkedHashMap<String, String> orderby) { final QueryResult<T> queryResult = new QueryResult<T>();
super.getHibernateTemplate().execute(new HibernateCallback<T>() { public T doInHibernate(Session session) throws HibernateException, SQLException { String hql = "from " + entityClassName + " o " + (wherejpql == null || "".equals(wherejpql.trim()) ? "" : " where " + wherejpql) + buildOrderby(orderby); Query query = session.createQuery(hql); setQueryParams(query, queryParams);// where queryResult.setTotalRecord(query.list().size());// first get size
if (firstindex != -1 && maxresult != -1) query.setFirstResult(firstindex).setMaxResults(maxresult);// last page
queryResult.setResultList(query.list());
return null; }
});
return queryResult;
}
/* * @see org.usc.daos.DAO#getScrollData(int, int, java.lang.String, java.lang.Object[]) */ public QueryResult<T> getScrollData(int firstindex, int maxresult, String wherejpql, Object[] queryParams) { return getScrollData(firstindex, maxresult, wherejpql, queryParams, null); }
/* * @see org.usc.daos.DAO#getScrollData(int, int, java.util.LinkedHashMap) */ public QueryResult<T> getScrollData(final int firstindex, final int maxresult, final LinkedHashMap<String, String> orderby) { return getScrollData(firstindex, maxresult, null, null, orderby);
}
/* * @see org.usc.daos.DAO#getScrollData(int, int) */ public QueryResult<T> getScrollData(final int firstindex, final int maxresult) { return getScrollData(firstindex, maxresult, null, null, null); }
/* * @see org.usc.daos.DAO#getScrollData() */ public QueryResult<T> getScrollData() { return getScrollData(-1, -1, null, null, null); }
/* * @see org.usc.daos.DAO#save(java.lang.Object) */
/** * 获取实体的名称 * * @param <E> * @param clazz * 实体类 * @return */ protected static <E> String getEntityName(Class<E> clazz) { String entityname = clazz.getSimpleName(); Entity entity = clazz.getAnnotation(Entity.class); if (entity.name() != null && !"".equals(entity.name())) { entityname = entity.name(); } return entityname; }
/** * 获取实体的主键 * * @param <E> * @param clazz * 实体类 * @return 主键名 */ protected static <E> String getKeyFieldName(Class<E> clazz) { try { PropertyDescriptor[] propertyDescriptors = Introspector.getBeanInfo(clazz).getPropertyDescriptors(); for (PropertyDescriptor propertydesc : propertyDescriptors) { Method method = propertydesc.getReadMethod(); if (null != method && null != method.getAnnotation(javax.persistence.Id.class)) { return propertydesc.getName(); } } } catch (Exception e) { e.printStackTrace(); } return "id"; }
/** * 设置HQL里边的属性值 * * @param query * @param queryParams */ protected static void setQueryParams(Query query, Object[] queryParams) { if (queryParams != null && queryParams.length > 0) { for (int i = 0; i < queryParams.length; i++) { query.setParameter(i, queryParams[i]);// 从0开始 } } }
/** * 组装order by语句 * * @param orderby * @return */ protected static String buildOrderby(LinkedHashMap<String, String> orderby) { StringBuffer orderbyql = new StringBuffer(""); if (orderby != null && orderby.size() > 0) { orderbyql.append(" order by "); for (String key : orderby.keySet()) { orderbyql.append("o.").append(key).append(" ").append(orderby.get(key)).append(","); } orderbyql.deleteCharAt(orderbyql.length() - 1); } return orderbyql.toString(); }
protected static <E> String getCountField(Class<E> clazz) { String out = "o"; try { PropertyDescriptor[] propertyDescriptors = Introspector.getBeanInfo(clazz).getPropertyDescriptors(); for (PropertyDescriptor propertydesc : propertyDescriptors) { Method method = propertydesc.getReadMethod(); if (method != null && method.isAnnotationPresent(EmbeddedId.class)) { PropertyDescriptor[] ps = Introspector.getBeanInfo(propertydesc.getPropertyType()).getPropertyDescriptors(); out = "o." + propertydesc.getName() + "." + (!ps[1].getName().equals("class") ? ps[1].getName() : ps[0].getName()); break; } } } catch (Exception e) { e.printStackTrace(); } return out; } }
|
注意
//父类HibernateDaoSupport注入sessionFactory的值 @Resource(name = "sessionFactory") public void setSuperSessionFactory(SessionFactory sessionFactory) { super.setSessionFactory(sessionFactory); } |
泛型实现类的关键是对
public QueryResult<T> getScrollData(final int firstindex, final int maxresult, final String wherejpql, final Object[] queryParams, final LinkedHashMap<String, String> orderby) |
方法的实现和分页的实现都借鉴了传智博客黎活明老师在巴巴运动网中的设计,通过其中的泛型工具类和Hibernate的HibernateCallback()的方法来实现分页数据的传递,想详细了解请下载巴巴运动网的前几个视频观看。
分页
分页用到的一些辅助类
page.jsp
<%@ page language="java" pageEncoding="UTF-8"%> <%@ taglib uri="/struts-tags" prefix="s"%> 当前页:第 <s:property value="#request.pageView.currentPage" /> 页 | 总记录数: <s:property value="#request.pageView.totalRecord" /> 条 | 每页显示: <s:property value="#request.pageView.maxResult" /> 条 | 总页数: <s:property value="#request.pageView.totalPage" /> 页 | <s:if test="#request.pageView.currentPage > 1"> <a href="javascript:topage(1)">首页</a> <a href="javascript:topage('<s:property value="#request.pageView.currentPage - 1"/>')">上一页</a> </s:if> <s:else> 首页 上一页 </s:else> <s:iterator begin="#request.pageView.pageIndex.startIndex" end="#request.pageView.pageIndex.endIndex" var="wp"> <s:if test="#request.pageView.currentPage== #wp"> <font color="#FF0000"><s:property value="#wp" /></font> </s:if> <s:else> <a href="javascript:topage('<s:property value="#wp"/>')"><s:property value="#wp" /></a> </s:else> </s:iterator> <s:if test="#request.pageView.currentPage < #request.pageView.totalPage"> <a href="javascript:topage('<s:property value="#request.pageView.currentPage + 1"/>')">下一页</a> <a href="javascript:topage('<s:property value="#request.pageView.totalPage"/>')">末页</a> </s:if> <s:else> 下一页 末页 </s:else>
|
base.js
function topage(page) { var form = document.forms[0]; form.page.value = page; form.submit(); } |
业务逻辑
例子:IStudentService.java 业务逻辑接口,面向接口编程
/** * 学生服务类接口 * * @author <a href="http://www.blogjava.net/lishunli/" target="_blank">ShunLi</a> * @notes Created on 2010-1-21<br> * Revision of last commit:$Revision: 633 $<br> * Author of last commit:$Author: [email protected] $<br> * Date of last commit:$Date: 2010-01-25 16:47:53 +0800 (周一, 25 一月 2010) $<br> * <p> */ public interface IStudentService extends IBaseDao<Student> { /** * 根据姓名查找学生 * * @param value * 姓名 * @return 该姓名的学生集 */ public abstract List<Student> findByName(String value); } |
TeacherServiceBean业务逻辑类,用@Service声明此类为业务逻辑层的类
/** * 老师服务实现类 * * @author <a href="http://www.blogjava.net/lishunli/" target="_blank">ShunLi</a> * @notes Created on 2010-1-17<br> * Revision of last commit:$Revision: 633 $<br> * Author of last commit:$Author: [email protected] $<br> * Date of last commit:$Date: 2010-01-25 16:47:53 +0800 (周一, 25 一月 2010) $<br> * <p> */ @Service // 声明此类为业务逻辑层的类 public class TeacherServiceBean extends BaseDaoSupport<Teacher> implements ITeacherService {
/* * @see org.usc.services.student.IStudentService#findByName(java.lang.String) */ public List<Teacher> findByPositional(String value) { return super.findByProperty("positional", value); }
}
|
调用业务逻辑
@Autowired private IStudentService studentService; |
上面的@Autowired和@Resource(name = "sessionFactory")功能差不多,就是注入相应的对象
测试
基于Annotation的SSH框架的Junit测试的难点在于如何读取Spring的配置,最佳解决方案是加入注解
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = { "classpath:/applicationContext.xml" }) @TestExecutionListeners( { DependencyInjectionTestExecutionListener.class }) public class StudentServiceTest |
这样就可以在单元测试的时候读取Spring的配置文件,方便测试,提供部分测试代码
@Autowired private IStudentService studentService;
@Test public void testGetScrollData5() { LinkedHashMap<String, String> orderby = new LinkedHashMap<String, String>(); orderby.put("no", "asc"); QueryResult<Student> scrollData = studentService.getScrollData(0, 5, "o.sex=? and o.age=?", new Object[] { "男", 20 }, orderby); for (Student student : scrollData.getResultList()) { System.out.println(student); } System.out.println(scrollData.getTotalRecord()); } |
测试结果
感谢 PK时发型不乱 网友认真测试我的Demo并提出了一个很重要的问题,就是如果项目部署在Tomcat5.5里的话会有问题的(可以自己修改部分代码调试通过),测试环境建议Tomcat6及以上。最后,真诚地感谢 PK时发型不乱 网友。
实例结果
参考网站
struts2采用convention-plugin实现零配置
基于Annotation的Struts2.0+Hibernate3.3+Spring2.5整合开发 (1)
基于Annotation的Struts2.0+Hibernate3.3+Spring2.5整合开发 (2)
基于Annotation的Struts2.0+Hibernate3.3+Spring2.5整合开发 (3)
源码下载
顺利提供下载:(源码没有相应的Jar包,需要下载下面的整合Jar包添加进后才可以运行)
文 件 名:SSHWithAnnotationDemo.rar
下载地址:http://usc.googlecode.com/files/SSHWithAnnotationDemo.rar
顺利提供下载:
文 件 名:Struts2.1.8+Hibernate3.3+Spring3.0整合所需Jar包.rar
下载地址:http://usc.googlecode.com/files/Struts2.1.8%2BHibernate3.3%2BSpring3.0%E6%95%B4%E5%90%88%E6%89%80%E9%9C%80Jar%E5%8C%85.rar
学习探讨
如果有什么建议或意见可以通过Q:506817493 或 E:[email protected],大家一起交流学习。敬请期待下篇博文:DAO层封装具有分页功能的S2SH整合实例,介绍使用传统的配置文件进行DAO层封装和具有分页功能的实例。
使用配置文件对DAO层封装具有分页功能的S2SH整合实例
顺利完成于2010年3月10日
博客中的一些下载已经放到了百度云了,请根据需要下载。 【点我去百度云下载】
最后弱弱地说一下,如果可以的话,转载请提供出处( ),谢谢。