07 使用DbUtils编写DAO

使用DbUtils编写DAO

标签(空格分隔): jdbc


DAO接口

里面定义好访问数据库的各种方法,接口传入一个参数,是DAO处理的实体类的类型

package day4;

/**
 * Created by japson on 12/12/2017.
 */

import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;

/**
 * 访问数据的DAO接口
 * 里面定义好访问数据库的各种方法
 * @param <T> DAO处理的实体类的类型
 */
public interface DAO<T> {

    /**
     *  INSERT,UPDATE,DELETE
     * @param connection 数据库连接
     * @param sql SQL语句
     * @param args 填充占位符的可变参数
     */
    void update(Connection connection,String sql,Object ... args);

    /**
     * 返回一个T的对象
     * @param connection
     * @param sql
     * @param args
     * @return
     */
    T get(Connection connection,String sql,Object... args) throws SQLException;

    /**
     * 返回T的一个集合
     * @param connection
     * @param sql
     * @param args
     * @return
     */
    List<T> getForList(Connection connection,String sql,Object... args);

    /**
     * 返回具体的一个值,例如总人数,平均数,某人id等
     * @param connection
     * @param sql
     * @param args
     * @param <E>
     * @return
     */
    <E> E getForValue(Connection connection,String sql,Object... args);

    /**
     * 批量处理的方法
     * @param connection
     * @param sql
     * @param args 填充占位符的Object[]类型的可变参数
     */
    void batch(Connection connection, String sql, Object[] ... args );

}

反射获取泛型T.class

目标是在具体的应用中能够确定泛型T具体是那个类型,也就是T.class是什么。

那么我们如何获取泛型T的类型呢

T.getClass()T.class都是非法的,因为T是泛型变量。 由于一个类的类型在编译期已确定,根据泛型擦拭,故不能在运行期得到T自己的实际类型。 实际上,当实例化以后,Class里面就不包括T的信息了,对于Class而言,T已经被擦拭为Object,所以无法反射到T的具体类别,也就无法得到T.class

而getGenericSuperClass()是Generic继承的特例,对于这种情况,子类会保存父类的Generic参数类型,返回一个ParameterizedType(参数化类型),这是可以获取到父类的T.class,这也是子类确定应该继承什么T的方法。

getClass().getGenericSuperclass():返回表示此Class所表示的实体的的Type

parameterizedType.getActualTypeArguments():返回表示此类型实际类型参数的Type对象的数组。也就是获得父类的泛型参数的实际类型。

    private Class<T> type;

    /**
     * 构造方法
     */
    public JdbcDaoImplements() {
        queryRunner = new QueryRunner();

        //通过反射, 获得 Class 定义中声明的父类的泛型参数类型

        //getGenericSuperclass()获得带有泛型的父类  
        //Type是Java中所有类型的公共高级接口。包括原始类型,参数化类型,数组类型、类型变量和基本类型
        Type superClass = getClass().getGenericSuperclass();

        //ParameterizedType参数化类型,即泛型
        //若带有泛型的父类为ParameterizedType参数化类型,则将带有泛型的父类强转为ParameterizedType参数化类型
        if(superClass instanceof ParameterizedType) {
            ParameterizedType parameterizedType = (ParameterizedType) superClass;
            //getActualTypeArguments获取参数化类型的数组,泛型可能有多个  
            Type[] typeArgs = parameterizedType.getActualTypeArguments();
            if (typeArgs[0] instanceof Class) {
                //确定子类需要传入泛型的类型
                type = (Class<T>) typeArgs[0];
            }
        }
    }

JdbcDaoImplements

这是一个实现类,实现了DAO接口。

每一个方法都是通过QueryRunner来实现的

package day4;

import day2.ReflectionUtils;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.BeanHandler;
import org.apache.commons.dbutils.handlers.BeanListHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;

/**
 * Created by japson on 12/12/2017.
 */

/**
 * 使用QueryRunner提供其DAO接口的具体实现
 * @param <T> 子类需要传入泛型的类型
 */

public class JdbcDaoImplements<T> implements DAO<T> {

    //使用QueryRunner类实现,因此要创建一个QueryRunner类的对象
    private QueryRunner queryRunner = null;
    //创建一个type,用来表示子类需要传入泛型的类型
    private Class<T> type;

    /**
     * 构造方法
     */
    public JdbcDaoImplements() {
        queryRunner = new QueryRunner();

        //通过反射, 获得 Class 定义中声明的父类的泛型参数类型

        //getGenericSuperclass()获得带有泛型的父类  
        //Type是Java中所有类型的公共高级接口。包括原始类型,参数化类型,数组类型、类型变量和基本类型
        Type superClass = getClass().getGenericSuperclass();

        //ParameterizedType参数化类型,即泛型
        //若带有泛型的父类为ParameterizedType参数化类型,则将带有泛型的父类强转为ParameterizedType参数化类型
        if(superClass instanceof ParameterizedType) {
            ParameterizedType parameterizedType = (ParameterizedType) superClass;
            //getActualTypeArguments获取参数化类型的数组,泛型可能有多个  
            Type[] typeArgs = parameterizedType.getActualTypeArguments();
            if (typeArgs[0] instanceof Class) {
                //确定子类需要传入泛型的类型
                type = (Class<T>) typeArgs[0];
            }
        }
    }

    /**
     * INSERT,DELETE,UPDATE操作
     * @param connection 数据库连接
     * @param sql SQL语句
     * @param args 填充占位符的可变参数
     * @throws SQLException
     */
    @Override
    public void update(Connection connection, String sql, Object... args) throws SQLException {
        queryRunner.update(connection,sql,args);
    }

    /**
     * 查询,查询结果为一个JavaBean
     * @param connection 数据库连接
     * @param sql SQL语句
     * @param args 填充占位符的可变参数
     * @return
     * @throws SQLException
     */
    @Override
    public T get(Connection connection, String sql, Object... args) throws SQLException {
        //创建BeanHandler对象时传入的Class参数对应的对象
        return queryRunner.query(connection,sql,new BeanHandler<T>(type),args);
    }


    /**
     * 获取一组对象
     * @param connection
     * @param sql
     * @param args
     * @return
     * @throws SQLException
     */
    @Override
    public List<T> getForList(Connection connection, String sql, Object... args) throws SQLException {
        //传入的Class参数对应的对象
        return queryRunner.query(connection,sql, new BeanListHandler<T>(type),args);
    }


    /**
     * 获取某一个值
     * @param connection
     * @param sql
     * @param args
     * @param <E>
     * @return
     * @throws SQLException
     */
    @Override
    public <E> E getForValue(Connection connection, String sql, Object... args) throws SQLException {
        return queryRunner.query(connection,sql, new ScalarHandler<>());
    }


    /**
     * 批量处理数据
     * @param connection
     * @param sql
     * @param args 填充占位符的Object[]类型的可变参数
     * @throws SQLException
     */
    @Override
    public void batch(Connection connection, String sql, Object[]... args) throws SQLException {
        queryRunner.batch(connection,sql,args);
    }
}

CustomerDao

继承了JdbcDaoImplements类并传递了Customer类型。

其中啥也没写

import day2.Customer;

/**
 * Created by japson on 12/12/2017.
 */
public class CustomerDao extends JdbcDaoImplements<Customer> {

}

CustomerDaoTest

对CustomerDao进行测试,测试其继承的方法

package test.day4; 

import day2.Customer;
import day4.CustomerDao;
import day4.JDBCTools;
import org.junit.Test;
import org.junit.Before; 
import org.junit.After;

import java.sql.Connection;
import java.sql.Date;
import java.util.List;

/** 
* CustomerDao Tester. 
* 
* @author <Authors name> 
* @since <pre>12/12/2017</pre> 
* @version 1.0 
*/ 
public class CustomerDaoTest { 

@Before
public void before() throws Exception { 
} 

@After
public void after() throws Exception { 
}

    /**
     * 创建一个CustomerDao的对象,用来调用其父类的方法
     */
    CustomerDao customerDao = new CustomerDao();

    /**
     * 查询id=5的customer,返回一个javaBean
     */
    @Test
public void testGet() {
    Connection connection = null;
    try {
        connection = JDBCTools.getConnection();
        String sql = "SELECT id,name,email,birth FROM customers WHERE id = ?";
        Customer customer = customerDao.get(connection,sql,5);
        System.out.println(customer);

    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        JDBCTools.releaseDB(null,null,connection);
    }
}

    /**
     * 使用update方法从插入一条记录
     */
    @Test
    public void testUpdate() {
    Connection connection = null;
    try {
        connection = JDBCTools.getConnection();
        String sql = "INSERT INTO customers(id,name,email,birth) VALUES(?,?,?,?)";
        customerDao.update(connection,sql,9,"Steven","steven@163.com","1991-05-07");
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        JDBCTools.releaseDB(null,null,connection);
    }
}


    /**
     * 查询一组数据:id为1,3,5的记录,返回javaBean的List
     */
    @Test
    public void testGetForList() {
    Connection connection = null;
    try {
        connection = JDBCTools.getConnection();
        String sql = "SELECT id,name,email,birth FROM customers WHERE id IN(?,?,?)";
        List<Customer> customers = customerDao.getForList(connection,sql,1,3,5);
        System.out.println(customers);

    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        JDBCTools.releaseDB(null,null,connection);
    }
}

    /**
     * 查询一个值,有多少个id
     */
    @Test
    public void testGetForValue() {
    Connection connection = null;
    try {
        connection = JDBCTools.getConnection();
        String sql = "SELECT COUNT(id) FROM customers";
        Object object = customerDao.getForValue(connection,sql);
        System.out.println(object);
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        JDBCTools.releaseDB(null,null,connection);
    }

}

    /**
     * 批量修改数据,第一个占位符为name,第二个占位符为id
     */
    @Test
    public void testBatch() {
    Connection connection = null;
    try {
        connection = JDBCTools.getConnection();
        String sql = "UPDATE customers SET name = ? WHERE id = ?";

        //插入的是多维数据,高维代表批量处理的次数,低维代表占位符
        Object[][] objects = {{"hahah7",7},{"hahah8",8},{"hahah9",9}};
        customerDao.batch(connection,sql,objects);

    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        JDBCTools.releaseDB(null,null,connection);
    }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值