李顺利
随笔-50  评论-170  文章-0  trackbacks-0

使用Annotation并对DAO层封装具有分页功能的S2SH整合实例

 

李顺利

2010124

目录

关键词... 2

前言... 2

开发环境... 2

开发步骤... 2

环境的集成... 2

Struts2.1.8所需Jar... 2

Hibernate3.3所需Jar... 3

Spring3.0所需Jar... 3

基于AnnotationStruts配置... 4

基于AnnotationHibernate配置... 5

基于AnnotationSpring配置... 10

DAO层封装... 12

分页... 19

业务逻辑... 21

测试... 22

实例结果... 23

参考网站... 23

源码下载... 23

学习探讨... 23

 

 


关键词

使用Annotation并对DAO层封装具有分页功能的S2SH整合实例,李顺利,AnnotationDAO层封装,分页,SSH整合,实例,黎活明,传智播客,巴巴运动网

前言

       现在Annotation越来越流行,最近一段时间也学了一些,EJB3.0HibernateSpring等都很好地支持Annotation,而且熟悉了Annotation的话整个项目开发时间会缩短,代码封装比较好,但是封装带来的就是代码阅读就比较困难了。Annotation也是一门知识,可以选择使用Annotation还是其他。个人认为由Sun官方支持的EJB规范会越来越流行,此时如果使用基于AnnotationSSH框架很容易转移到Struts+EJB+Spring的项目中,而且使用Annotation,很容易实现0配置,像在这个实例中就一个配置,这样避免了配置文件多而不知所措的情况。

开发环境

Jdk1.5+Struts2.1.8+Hibernate3.3+Spring3.0+MySql5.0+MyEclipse8.0

开发步骤

环境的集成

到官网下载上面开发环境中的框架和工具,安装完成后。在Myeclipse中新建名为SSHWithAnnotationDemoweb project,添加SSH整合所需要的包,这里详细说一下需要哪些包?

Struts2.1.8所需Jar

xwork-core-2.1.6.jaraopalliance-1.0.jarcommons-logging-1.0.4.jarcommons-fileupload-1.2.1.jarcommons-io-1.3.2.jarfreemarker-2.3.15.jarognl-2.7.3.jarstruts2-convention-plugin-2.1.8.1.jarstruts2-core-2.1.8.1.jarstruts2-spring-plugin-2.1.8.jar

       clip_image002

其中下文会对struts2-convention-plugin插件进行详细讲解。

Hibernate3.3所需Jar

slf4j-log4j12.jarantlr-2.7.6.jarcommons-collections-3.1.jardom4j-1.6.1.jarejb3-persistence.jarhibernate3.jarhibernate-annotations.jarhibernate-commons-annotations.jarjavassist-3.9.0.GA.jarjta-1.1.jarlog4j.jarslf4j-api-1.5.8.jar

       clip_image004

Spring3.0所需Jar

org.springframework.web-3.0.0.RC1.jarorg.springframework.aop-3.0.0.RC1.jarorg.springframework.asm-3.0.0.RC1.jarorg.springframework.beans-3.0.0.RC1.jar

org.springframework.context-3.0.0.RC1.jarorg.springframework.core-3.0.0.RC1.jarorg.springframework.expression-3.0.0.RC1.jarorg.springframework.jdbc-3.0.0.RC1.jarorg.springframework.orm-3.0.0.RC1.jarorg.springframework.test-3.0.0.RC1.jarorg.springframework.transaction-3.0.0.RC1.jar

 

clip_image005

还有一些其他的辅助Jar包:

mysql-connector-java-5.1.7-bin.jaraspectjweaver.jarcommons-dbcp-1.2.2.jarcommons-pool.jarjunit-4.6.jar

clip_image006

上面的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框架的整合了。


基于AnnotationStruts配置

使用AnnotationStruts配置可以实现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;

    }

}

 

基于AnnotationHibernate配置

HibernateAnnotation方式很类似于EJB中的JPA,主要的Annotation注解是:@Entity@Table@Id@GeneratedValue@Column 。具体的注解请上网查看一下。这里介绍一种简便的方法生成基于AnnotationHibernate持久类。

1.  使用Myeclipse添加对Hibernate的支持

右键项目,选择MyEclipse后选择Add hibernate Capabilities(一般都会先添加对Spring的支持后在添加对Hibernate的支持,这样会使用Spring管理Hibernate

clip_image008

clip_image010

这个时候就不需要选择Jar包了,HibernateJar已经加入进来,Next,选择Spring的配置文件,这样可以使用Spring进行管理Hibernate(这也是为什么要先添加对Spirng的支持),Next

clip_image012

选择已经存在的Spring配置文件

clip_image014

后选择已经创建好的DateSource

clip_image016

clip_image018

即可,详情请阅读Struts+Spring+Hibernate整合注册登录——使用Myeclipse快速开发,里面有详细的介绍。

2.  进入生成DB Brower视图(可以通过windows->show View找到)

clip_image020

找到后连接MySql数据库后,即可生成Hibernate的持久类clip_image022

clip_image024

生成的实例代码

@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;

    }

//……

}

基于AnnotationSpring配置

类似上面添加对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;amp;characterEncoding\=utf-8

mysql.database.user=root

mysql.database.password=lishunli

mysql.database.maxActive=100

mysql.database.maxIdle=30

mysql.database.maxWait=500

 

至此,基于AnnotationSSH框架的基本已经搭建完成。

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: nhjsjmz@gmail.com $<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: nhjsjmz@gmail.com $<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)

方法的实现和分页的实现都借鉴了传智博客黎活明老师在巴巴运动网中的设计,通过其中的泛型工具类和HibernateHibernateCallback()的方法来实现分页数据的传递,想详细了解请下载巴巴运动网的前几个视频观看。

分页

分页用到的一些辅助类

clip_image026

clip_image028

 

clip_image029

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>&nbsp;

    <a href="javascript:topage('<s:property value="#request.pageView.currentPage - 1"/>')">上一页</a>&nbsp;

</s:if>

<s:else>

首页 &nbsp;上一页&nbsp;

</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>&nbsp;

    </s:if>

    <s:else>

        <a href="javascript:topage('<s:property value="#wp"/>')"><s:property value="#wp" /></a>&nbsp;

    </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>&nbsp;

    <a href="javascript:topage('<s:property value="#request.pageView.totalPage"/>')">末页</a>&nbsp;

</s:if>

<s:else>

下一页 &nbsp;末页&nbsp;

</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: nhjsjmz@gmail.com $<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: nhjsjmz@gmail.com $<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")功能差不多,就是注入相应的对象

测试

基于AnnotationSSH框架的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());

    }

测试结果

clip_image031

clip_image033

感谢  PK时发型不乱  网友认真测试我的Demo并提出了一个很重要的问题,就是如果项目部署在Tomcat5.5里的话会有问题的(可以自己修改部分代码调试通过),测试环境建议Tomcat6及以上。最后,真诚地感谢 PK时发型不乱  网友。

实例结果

clip_image035

clip_image037

参考网站

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
请复制上面的链接下载 

学习探讨

如果有什么建议或意见可以通过Q506817493 Eleeshunli@qq.com,大家一起交流学习。敬请期待下篇博文:DAO层封装具有分页功能的S2SH整合实例,介绍使用传统的配置文件进行DAO层封装和具有分页功能的实例。

使用配置文件对DAO层封装具有分页功能的S2SH整合实例

 

顺利完成于2010310



博客中的一些下载已经放到了百度云了,请根据需要下载。【点我去百度云下载】

最后弱弱地说一下,如果可以的话,转载请提供出处( ),谢谢。
posted on 2010-03-10 14:59 李顺利 阅读(9941) 评论(14)  编辑  收藏

评论:
# re: 使用Annotation并对DAO层封装具有分页功能的S2SH整合实例 2010-03-11 08:37 | 黄燕青
既然用了sping3.0,就可以不用struts2,听说现在的spring3 MVC的注解功能比struts2的强,struts2的现在搞的不伦不类了  回复  更多评论
  
# re: 使用Annotation并对DAO层封装具有分页功能的S2SH整合实例 2010-03-11 08:55 | 李顺利
@黄燕青
你好,谢谢你的回复,也许你还是对Struts2由偏见,实际上Struts2已经做的越来越好了  回复  更多评论
  
# re: 使用Annotation并对DAO层封装具有分页功能的S2SH整合实例 2010-03-11 10:10 | 4628241
辛苦了.值得借鉴  回复  更多评论
  
# re: 使用Annotation并对DAO层封装具有分页功能的S2SH整合实例 2010-03-11 20:37 | 一农
太复杂了,没必要这么复杂。
建议看看springside或则我们的simplejee。  回复  更多评论
  
# re: 使用Annotation并对DAO层封装具有分页功能的S2SH整合实例[未登录] 2011-09-06 09:56 | joe
其他还没看,但分页是传说中的假分页。博主把分页弄好些吧。呵呵  回复  更多评论
  
# re: 使用Annotation并对DAO层封装具有分页功能的S2SH整合实例 2011-09-06 13:23 | 李顺利
@joe
不管真分页还是假分页,这个只是一个小的Demo,只是学习过程中的一些记录。
这个Demo中需要记录总页数和总记录数,以前的设计中确实没有考虑到,肯定有很多不足,谢谢你的提醒。  回复  更多评论
  
# re: 使用Annotation并对DAO层封装具有分页功能的S2SH整合实例[未登录] 2011-09-06 16:50 | joe
@李顺利
也许你理解错我的意思了,并不是这个demo没有记录总页数和总记录数,而是你利用BaseDaoSupport.java的125行queryResult.setTotalRecord(query.list().size());// first get size来获取总记录数没什么意义,你还是把数据库的所有记录,query.list().size()跟不分页是没区别的,呵呵,我只是跟你说说而已,没什么其他意思,你能这么跟大家分享已经很大度了。我还是很顶你的。哈哈  回复  更多评论
  
# re: 使用Annotation并对DAO层封装具有分页功能的S2SH整合实例 2011-09-06 18:14 | 李顺利
@joe
谢谢提醒,应该没有错误理解你的意思。
“这个Demo中需要记录总页数和总记录数,以前的设计中确实没有考虑到”
queryResult.setTotalRecord(query.list().size()); 我的意思这个就是以前设计的不合理处,如果现在重新写的话,可能就不是这样的,大概会类似这样
queryResult.setTotalRecord("select count(1) from ..") // 多执行一个sql来获得总记录数。可能这样也不太好,不过稍微有些改善。

  回复  更多评论
  
# re: 使用Annotation并对DAO层封装具有分页功能的S2SH整合实例 2011-09-12 18:48 | 帅帅
能否把分页用到的一些辅助类的详细代码给出啊,索引我这里弄不出来  回复  更多评论
  
# re: 使用Annotation并对DAO层封装具有分页功能的S2SH整合实例 2011-09-13 19:58 | 李顺利
@帅帅
你可以通过 http://usc.googlecode.com/files/SSHWithAnnotationDemo.rar 下载源代码,里面有你说的“辅助类的详细代码”
还有,如果使用SVN的话,你可以checkout
http://usc.googlecode.com/svn/SSHWithAnnotationDemo/  回复  更多评论
  
# re: 使用Annotation并对DAO层封装具有分页功能的S2SH整合实例 2011-09-21 23:36 | 帅帅
<s:iterator begin="#request.pageView.pageIndex.startIndex" end="#request.pageView.pageIndex.endIndex" var="wp">
这段代码中,struts2.1.8中s:iterator 能这么用吗?begin,end和var属性我在书上没有看到。var="wp"是什么意思?盼解答!谢谢!
  回复  更多评论
  
# re: 使用Annotation并对DAO层封装具有分页功能的S2SH整合实例 2011-09-22 00:39 | 李顺利
@帅帅
先回答你的第一个问题,在Struts2.1.8中是可以这样用的,我已经升级Struts2.1.8,没有出现问题(没有测试最新版Struts 2.2.3.1,相信也是没有问题的)。
第二个问题,请自己阅读 http://struts.apache.org/2.1.8/docs/iterator.html

还有,尽信书不于没书,不过要相信书是个好东西。Good luck.

顺利  回复  更多评论
  
# re: 使用Annotation并对DAO层封装具有分页功能的S2SH整合实例 2011-09-22 23:14 | 帅帅
@李顺利
不错,看了你的评论我很受启发啊,不过我没有用你的分页代码,我用自己写的,但是我之前没有弄出索引,现在我弄出来了。我没有读原文档只是看我买的书了,书上的内容不全,文档上的很全,而且也有例子,我一下就搞定了。我从你这里得到的体会就是一定要读原文档,那里的知识是最全的。非常感谢你!  回复  更多评论
  
# re: 使用Annotation并对DAO层封装具有分页功能的S2SH整合实例 2011-09-22 23:17 | 帅帅
@李顺利
我的QQ是:455247221.加我好友吧,希望以后能多向你请教请教,我是求知若渴。谢谢!  回复  更多评论
  

只有注册用户登录后才能发表评论。


网站导航: