Day4_JDBC——BaseDao类的优化

一. 分析

由上一篇Day3_JDBC——使用DBUtils第三方工具完成增删改查的封装(BaseDao类)可知,BaseDao类中的每一个方法,都需要传入一个实体类的类型(即JavaBean类型)。假如我们在继承BaseDao类的时候,直接告诉BaseDao的构造器我的实体类的类型,这样就再也不用在方法里面传入一个实体类的类型。

二. 例子

本项目的目录结构如下:
Day4_JDBC——BaseDao类的优化

BaseDao2.java

package com.atguigu.dao;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;

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 com.atguigu.utils.JDBCUtils;

public class BaseDao2<T> {
          private QueryRunner runner = new QueryRunner();
          private Class<T> type;//目的是将T赋给type,即要把BaseDao2的泛型拿到,交给type
          
          /*
           * 在无参构造器中获取类泛型的类型,BaseDao2不会直接创建对象
           * BaseDao2构造器中this代表子类对象
           */
           public BaseDao2() {
        	   //1.获取子类对象的类模板, UserDao2 extends BaseDao2<User>
        	   Class<? extends BaseDao2> cla = this.getClass();
        	   //2.获取父类的带泛型的类型
        	   //cla.getSuperclass();获取父类类型 BaseDao2
        	   ParameterizedType pt = (ParameterizedType) cla.getGenericSuperclass();//获取真实的父类类型BaseDao2<User>
        	   //3.获取泛型列表,一个类可以声明多个泛型参数Map<K,V>
        	   Type[] types = pt.getActualTypeArguments();
        	   //4.取出第一位的泛型就是BaseDao2的泛型类型
        	  type = (Class<T>) types[0];
           }
          
          //增删改
          public int update(String sql, Object...params) {
        	  Connection conn = JDBCUtils.getConn();
        	  int count = 0;
              try {
				count = runner.update(conn, sql, params);
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}finally {
				JDBCUtils.closeConn(conn);
			}
        	 return count; 
          }
          
          //查询一条记录封装为对象的方法
          public T getBean( String sql, Object...params){
        	  Connection conn = JDBCUtils.getConn();
        	  T t = null;
        	  try {
        		  //BeanHandler将查询到的记录封装为一个对象
        		  //type类中必须由无参构造器,type类的属性名必须和sql查询的列名一致
				t = runner.query(conn, sql, new BeanHandler<>(type), params);
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
				System.out.println("t为:" + t);
			}finally {
				JDBCUtils.closeConn(conn);
			}
        	  return t;
          }
          
          //查询多条记录并封装为对象的集合
          public List<T> getBeanList( String sql, Object...params){
        	  Connection conn = JDBCUtils.getConn();
        	  List<T> list = null;
        	  try {
				list = runner.query(conn, sql, new BeanListHandler<>(type), params);
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}finally {
				JDBCUtils.closeConn(conn);
			}
        	  return list;
          }
          
          //查询数据库表的总记录条数,可变参数列表是0个~n个参数,
          //如果没有参数,则不需要传入可变参数列表,连null也不用传
          public long getCount(String sql, Object...params) {
        	  Connection conn = JDBCUtils.getConn();
        	  //ScalarHandler:无参构造器默认将查询到的第一行第一列数据封装为对象返回
        	  //              如果是整数类型返回真实类型Long
        	  //              如果真实返回类型是String,并提升为Object返回
        	  long count = 0;
        	  try {
				count = (long) runner.query(conn, sql, new ScalarHandler(), params);
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}finally {
				JDBCUtils.closeConn(conn);
			}
        	  return count;
          }
          
          //批量增删改,它需要知道执行多少次,每次的参数是什么
          //所以方法中的二维数据参数,第一维代表批处理执行的次数
          //第二维代表每次批处理需要的参数列表
          public void batchUpdate(String sql, Object[][] params) {
        	  Connection conn = JDBCUtils.getConn();
        	  try {
				runner.batch(conn, sql, params);
			} catch (SQLException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}finally {
				JDBCUtils.closeConn(conn);
			}
          }
          
}

上一篇:azkaban参数详解


下一篇:【java】事务的回滚