SSH的Dao层封装

一、先来看代码


1.准备好所需要的Jar包

antlr-2.7.6.jar
aopalliance-1.0.jar
c3p0-0.9.1.2.jar
commons-collections-3.2.1.jar
commons-logging.jar
dom4j-1.6.1.jar
ejb3-persistence.jar
hibernate-jpa-2.0-api-1.0.0.Final.jar
hibernate3.jar
javassist-3.11.0.GA.jar
jta-1.1.jar
ojdbc6.jar
slf4j-api-1.6.1.jar
spring-aop-3.2.4.RELEASE.jar
spring-beans-3.2.4.RELEASE.jar
spring-context-3.2.4.RELEASE.jar
spring-core-3.2.4.RELEASE.jar
spring-expression-3.2.4.RELEASE.jar
spring-jdbc-3.2.4.RELEASE.jar
spring-orm-3.2.4.RELEASE.jar
spring-tx-3.2.4.RELEASE.jar

2.准备数据库

create table USER_INFO(
id number(8,0) primary key,
USERNAME varchar2(32),
PASSWORD varchar2(32)
);

3.配置Spring配置文件

version="1.0" encoding="UTF-8"?>
"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.2.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.2.xsd
http://www.springframework.org/schema/aop 
http://www.springframework.org/schema/aop/spring-aop-3.2.xsd
http://www.springframework.org/schema/tx 
http://www.springframework.org/schema/tx/spring-tx-3.2.xsd">
    "net.csdn" />
    id="datasource" class="com.mchange.v2.c3p0.ComboPooledDataSource"
        destroy-method="close">
        <property name="driverClass" value="oracle.jdbc.driver.OracleDriver" />
        <property name="jdbcUrl" value="jdbc:oracle:thin:@localhost:1521:orcl" />
        <property name="user" value="CNDS" />
        <property name="password" value="CNDS" />

        <property name="autoCommitOnClose" value="true" />
        <property name="checkoutTimeout" value="10000" />
        <property name="initialPoolSize" value="10" />
        <property name="minPoolSize" value="3" />
        <property name="maxPoolSize" value="20" />
        <property name="maxIdleTime" value="30000" />
        <property name="acquireIncrement" value="3" />
        <property name="maxIdleTimeExcessConnections" value="1800" />
    
    id="sessionFactory"
        class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
        <property name="dataSource" ref="datasource" />
        <property name="packagesToScan">
            <list>
                net.csdn.model
            list>
        property>
        <property name="hibernateProperties">
            
                hibernate.dialect=org.hibernate.dialect.OracleDialect
            
        property>
    
    id="txManager"
        class="org.springframework.orm.hibernate3.HibernateTransactionManager">
        <property name="sessionFactory" ref="sessionFactory" />
    
    transaction-manager="txManager" />

4.准备对应的实体类

package net.csdn.model;

import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
import org.springframework.stereotype.Component;
/**
 * 对应数据库中的USER_INFO表的实体类
 * @author Bowen
 *
 */
@Entity
@Table(name="USER_INFO")
@Component("userInfoEntity")
public class UserInfoEntity {
    /** ********** 成员变量 ********** **/
    //映射表中的id字段
    private int id;
    //映射表中的username字段
    private String username;
    //映射表中的password字段
    private String password;
    /** ********** Get方法 ********** **/
    @Id
    public int getId() {
        return id;
    }
    public String getUsername() {
        return username;
    }
    public String getPassword() {
        return password;
    }
    /** ********** Set方法 ********** **/
    public void setId(int id) {
        this.id = id;
    }
    public void setUsername(String username) {
        this.username = username;
    }
    public void setPassword(String password) {
        this.password = password;
    }
}

5.设计Dao层通用类的接口

package net.csdn.dao.inter;

import java.io.Serializable;
import java.util.List;
import java.util.Map;

/**
 * 封装的Dao层通用的接口 这里用到了泛型
 * 
 * @author Bowen
 * 
 * @param 
 */
public interface CommonlyDaoInter {
    /**
     * 保存
     * 
     * @param entity
     */
    public void save(T entity);

    /**
     * 根据主键删除
     * 
     * @param ids
     */
    public void deleteByIds(Serializable... ids);

    /**
     * 根据集合删除
     * 
     * @param list
     */
    public void deleteByList(List list);

    /**
     * 修改
     * 
     * @param entity
     */
    public void update(T entity);

    /**
     * 更具主键查询
     * 
     * @param id
     * @return
     */
    public T queryById(Serializable id);

    /**
     * 查询全部
     * 
     * @return
     */
    public List queryAll();

    /**
     * 根据条件查询 并且按照指定的排序方式排序
     * 
     * @param condition
     * @param params
     * @param orderby
     * @return
     */
    public List queryCondition(String condition, Object[] params,
            Map orderby);

    /**
     * 分页查询全部
     * 
     * @param offset
     * @param length
     * @return
     */
    public List queryAllPage(int offset, int length);
}

6.设计Dao层通用实现类的常用功能

package net.csdn.dao.impl;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;

import javax.annotation.Resource;

import org.hibernate.HibernateException;
import org.hibernate.Query;
import org.hibernate.SessionFactory;
import org.springframework.orm.hibernate3.HibernateCallback;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;

import net.csdn.dao.inter.CommonlyDaoInter;

/**
 * 封装Dao层的实现类
 * 
 * @author Bowen
 * 
 * @param 
 */
public class CommonlyDaoImpl<T> extends HibernateDaoSupport implements
        CommonlyDaoInter {
    /**
     * 注入SessionFactory
     * 
     * @param sessionFactory
     */
    @Resource(name = "sessionFactory")
    public final void setSessionFactoryDi(SessionFactory sessionFactory) {
        this.setSessionFactory(sessionFactory);
    }

    /**
     * 保存方法
     */
    @Override
    public void save(T entity) {
        this.getHibernateTemplate().save(entity);
    }

    /**
     * 利用可变参数的形式来达到可以根据id同时删除一个或多个对象的目的 这里参数的类型为Serializable
     */
    @Override
    public void deleteByIds(Serializable... ids) {
        if (ids != null && ids.length > 0) {
            for (Serializable key : ids) {
                Object entity = this.queryById(key);
                if (entity != null) {
                    this.getHibernateTemplate().delete(entity);
                }
            }
        }
    }

    /**
     * 通过集合来删除多个对象 这种方法是为了便于使用deleteAll()方法
     */
    @Override
    public void deleteByList(List list) {
        this.getHibernateTemplate().deleteAll(list);
    }

    /**
     * 更新方法
     */
    @Override
    public void update(T entity) {
        this.getHibernateTemplate().update(entity);
    }

    /**
     * 这是一个获取当前元素真实类的方法 原理是通过反射机制 在下面的各项查找方法中都有应用
     * 
     * @return
     */
    @SuppressWarnings({ "rawtypes" })
    public Class getEntityClass() {
        Type type = this.getClass().getGenericSuperclass();
        ParameterizedType pt = (ParameterizedType) type;
        return (Class) pt.getActualTypeArguments()[0];
    }

    /**
     * 根据Id查找对象是最为应用普遍的
     */
    @SuppressWarnings("unchecked")
    public T queryById(Serializable id) {
        return (T) this.getHibernateTemplate().get(this.getEntityClass(), id);
    }

    /**
     * 查找所有对象
     */
    @SuppressWarnings("unchecked")
    @Override
    public List queryAll() {
        // 注意这里的from后面一定要多加一个空格
        return this.getHibernateTemplate().find(
                "from " + this.getEntityClass().getName());
    }

    /**
     * 根据条件查找多个对象并按照一定规则排序 这个方法拼接了一个HQL语句,要注意HQL语句的格式 参数介绍 String condition
     * 是预设的筛选条件的属性名 Object[] params 是对应预设的筛选条件的属性值,这里设置为Object数组是为了方便传参
     * Map orderby 是存储设置的排序方式的信息的Map集合
     */
    @SuppressWarnings("unchecked")
    @Override
    public List queryCondition(String condition, Object[] params,
            Map orderby) {
        // 编写的HQL语句头部
        // 这里要注意where后面的1=1属性
        // 之所以设置这样一个属性是为了保证语HQL语句的完整性
        String hqlHead = "from " + this.getEntityClass().getName()
                + " where 1=1 ";
        // 创建一个StringBuffer用来存储遍历Map的数据
        StringBuffer buffer = new StringBuffer("");
        // 判断Map是否为空
        if (orderby != null && orderby.size() > 0) {
            // 向StringBuffer添加 order by 字符串用于设置排序
            buffer.append(" order by ");
            // 遍历Map
            for (Map.Entry map : orderby.entrySet()) {
                buffer.append(" " + map.getKey() + " " + map.getValue() + ",");
            }
            // 遍历Map之后要删除最后一个逗号
            buffer.deleteCharAt(buffer.length() - 1);
        }
        // 拼接成完整的HQL语句
        String wholeHql = hqlHead + condition + buffer.toString();
        // 执行查询
        return this.getHibernateTemplate().find(wholeHql, params);
    }

    /**
     * 分页查询 参数介绍 final int offset 起始查询的位置,从0开始 final int length 查询的步长
     */
    @SuppressWarnings({ "unchecked", "rawtypes" })
    @Override
    public List queryAllPage(final int offset, final int length) {
        // 获取类的名字
        final String className = this.getEntityClass().getName();
        return this.getHibernateTemplate().executeFind(new HibernateCallback() {
            public Object doInHibernate(org.hibernate.Session session)
                    throws HibernateException, SQLException {
                Query query = session.createQuery("from " + className);
                query.setFirstResult(offset);
                query.setMaxResults(length);
                return query.list();
            }
        });
    }
}

7.创建对应实体类的Dao层操作接口

package net.csdn.dao.inter;

import net.csdn.model.UserInfoEntity;

/**
 * 这里要注意定义Dao层接口的时候要继承通用Dao接口
 * 并且要在原有的泛型位置上传入对应的实体类
 * @author Bowen
 *
 */
public interface UserInfoDaoInter extends CommonlyDaoInter<UserInfoEntity>{

}

8.创建对应实体类的Dao层实现类

package net.csdn.dao.impl;

import org.springframework.stereotype.Component;
import net.csdn.dao.inter.UserInfoDaoInter;
import net.csdn.model.UserInfoEntity;
/**
 * 定义Dao层实现类实现了对应的接口
 * 并且继承Dao层的通用实现类,同样也要在原有的泛型上传入对应的实体类
 * @author Bowen
 *
 */
@Component("userInfoDaoImpl")
public class UserInfoDaoImpl extends CommonlyDaoImpl<UserInfoEntity> implements UserInfoDaoInter{

}

9.创建测试类

package net.csdn.test;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import net.csdn.dao.inter.UserInfoDaoInter;
import net.csdn.model.UserInfoEntity;

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

/**
 * 测试类 通过Junit单元测试功能来实现测试
 * 
 * @author Bowen
 * 
 */
public class TestClass {

    private ApplicationContext context;

    private UserInfoEntity userInfoEntity;

    private UserInfoDaoInter userInfoDaoInter;

    /**
     * 在测试前先注入
     */
    @Before
    public void init() {
        context = new ClassPathXmlApplicationContext("applicationContext.xml");
        userInfoEntity = (UserInfoEntity) context.getBean("userInfoEntity");
        userInfoDaoInter = (UserInfoDaoInter) this.context
                .getBean("userInfoDaoImpl");
    }

    /**
     * 测试保存
     */
    @Test
    public void testSave() {
        for (int i = 10000; i < 10010; i++) {
            this.userInfoEntity.setId(i);
            this.userInfoEntity.setUsername("cnds");
            this.userInfoEntity.setPassword("cnds");
            this.userInfoDaoInter.save(userInfoEntity);
        }
    }

    /**
     * 测试根据ID删除
     */
    @Test
    public void testDeleteByIds() {
        this.userInfoDaoInter.deleteByIds(10000, 10001);
    }

    /**
     * 测试根据集合删除
     */
    @Test
    public void testDeleteByList() {
        // 创建一个集合
        List list = new ArrayList();
        // 获取Id为10002的数据
        this.userInfoEntity = this.userInfoDaoInter.queryById(10002);
        // 向集合添加数据
        list.add(this.userInfoEntity);
        // 获取Id为10003的数据
        this.userInfoEntity = this.userInfoDaoInter.queryById(10003);
        // 向集合添加数据
        list.add(this.userInfoEntity);
        // 删除数据
        this.userInfoDaoInter.deleteByList(list);
    }

    /**
     * 测试更新数据
     */
    @Test
    public void testUpate() {
        // 获取原有数据
        this.userInfoEntity = this.userInfoDaoInter.queryById(10004);
        System.out.println("更新前用户名:" + this.userInfoEntity.getUsername());
        this.userInfoEntity.setUsername("cnds.net");
        // 更新数据
        this.userInfoDaoInter.update(this.userInfoEntity);
        // 查看更新后的数据
        this.userInfoEntity = this.userInfoDaoInter.queryById(10004);
        System.out.println("更新后用户名:" + this.userInfoEntity.getUsername());
    }

    /**
     * 测试根据ID查询
     */
    @Test
    public void testQueryById() {
        this.userInfoEntity = this.userInfoDaoInter.queryById(10004);
        System.out.println("更新前用户名:" + this.userInfoEntity.getUsername());
    }

    /**
     * 测试查询所有
     */
    @Test
    public void testQueryAll() {
        List list = this.userInfoDaoInter.queryAll();
        for (UserInfoEntity userInfo : list) {
            System.out.println("用户名:" + userInfo.getUsername());
        }
    }

    /**
     * 测试根据条件查询
     */
    @Test
    public void testQueryCondition() {
        // 这里注意设置条件的时候一定要加有and
        String condition = " and username=? ";
        Object[] params = { "cnds.net" };
        Map orderby = new HashMap();
        orderby.put(" id ", " DESC ");
        List list = this.userInfoDaoInter.queryCondition(
                condition, params, orderby);
        for (UserInfoEntity userInfo : list) {
            System.out.println("用户名:" + userInfo.getUsername());
        }
    }

    /**
     * 测试分页查询
     */
    @Test
    public void testQueryAllPage() {
        for (int i = 0; i < 10; i++) {
            List list = this.userInfoDaoInter.queryAllPage(
                    i * 2, 2);
            if (list.size() == 0) {
                break;
            } else {
                System.out.println("第 " + (i + 1) + " 页");
                for (UserInfoEntity userInfo : list) {
                    System.out.println(userInfo.getUsername());
                }
            }
        }
    }
}

10.最终目录结构图

SSH的Dao层封装_第1张图片

二 、原理分析与实际应用

这种封装的好处能够大大的解决了Dao层代码的重复性。因为在Dao层中基本都是增删改查的操作。所以代码重复性很高。通过继承和泛型的应用来实现一劳永逸的方法

Created with Raphaël 2.1.0 UserInfoDaoImpl UserInfoDaoImpl UserInfoDaoInter UserInfoDaoInter CommonlyDaoImpl CommonlyDaoImpl CommonlyDaoInter CommonlyDaoInter 实现(implements) 继承(extends) 实现(implements) 继承(extends)

你可能感兴趣的:(Java每日)