自己动手写泛型dao

在经过一系列的问题得到解决之后,泛型dao终于写出来了。泛型dao相比于以前写的dao最大的好处就是,大大提高了代码的复用性,以往我们要对数据库中表中的数据进行操作的时候,每张表都需要写一个dao来操作,当表非常多的时候,代码量就会很大,还有就是这些代码大部分都是重复的,获取数据库连接、sql预处理,返回结果集,最后关闭数据库连接,获取数据库连接和关闭资源可以放在一个数据库工具类中很简单,剩下的对数据进行操作的方法,由于我们事先不知道要对那张表进行操作,所以就需要利用一些特殊的手段来获取,动态的获取,利用反射这个特性,我们可以很容易的获得我们想要得到的信息。

在前面有一篇文章讲了反射获取类中信息的例子: 通过反射获取属性名和属性类型 这篇文章就是在这里遇到的问题

还有就是在存储获得到的数据时候,需要用到有序的键值对在:有序的Map集合--LinkedHashMap 中说明了

下面开始正题:
代码结构:


在例子中用到了c3p0和读取properties配置文件连接数据库,构建数据库连接池,在第一个方法中写了注释,剩下的方法都是类似的

注意:代码中有get和getset方法分别是拼接get方法和set方法的方法……还有获得属性信息的getField方法都在代码的最后面

package com_basedao;


import java.util.List;

/**
 * Created with IDEA
 * author:DuzhenTong
 * Date:2017/11/8
 * Time:19:40
 */
public interface BaseDao<T> {

    void update(T t, String password, int id);

    void insert(T t);

    void delete(T t, int id);

    List selectAll(T t);

    List selectOne(T t,int id);
}


package com_daoImp;

import com_basedao.BaseDao;
import com_util.JdbcUtil;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.*;

/**
 * Created with IDEA
 * author:DuzhenTong
 * Date:2017/11/8
 * Time:19:46
 */

public class BaseDaoImp<T> implements BaseDao<T>{

    private Connection connection;
    private PreparedStatement preparedStatement;
    private ResultSet resultSet;
    private String sql;
    private List<Object> list = null;
    //LinkedHashMap是一个有顺序的map集合
    private static Map<String, String> map = new LinkedHashMap<String, String>();

    /**
     * 查询表中所有数据
     * @param t
     * @return
     */
    @Override
    public List<Object> selectAll(T t) {
        //初始化字符串
        StringBuffer stringBuffer = new StringBuffer("select * from ");
        //创建对象的容器list集合
        list = new ArrayList<Object>();
        //获取类的类
        Class clazz =t.getClass();
        //获取到类的名字处理拼接sql语句
        sql = stringBuffer.append(clazz.getSimpleName()).toString().toLowerCase();
        try {
            connection = JdbcUtil.getInstance().getConnection();
            preparedStatement = connection.prepareStatement(sql);
            resultSet = preparedStatement.executeQuery();
            while (resultSet.next()) {
                //利用反射获得对象
                Object object = clazz.newInstance();
                getField(object);
                int i = 1;
                //遍历map集合
                for (Map.Entry<String, String> entry : map.entrySet()) {
                    if ("int".equals(entry.getValue())) {
                        //利用发射获取实体类中的set方法
                        Method method = clazz.getMethod(getSet(entry.getKey()), int.class);
                        //执行方法
                        method.invoke(object, resultSet.getInt(i));
                        //从结果集中想要获取列值需要一个计数器如果查到的是本列加一
                        i++;
                    }
                    if ("String".equals(entry.getValue())) {
                        Method method = clazz.getMethod(getSet(entry.getKey()), String.class);
                        method.invoke(object, resultSet.getString(i));
                        i++;
                    }
                }
                list.add(object);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }finally {
            JdbcUtil.releaseResources(connection,preparedStatement,resultSet);
        }
        return list;
    }

    /**
     * 根据id查询
     * @param t
     * @param id
     * @return
     */
    @Override
    public List<Object> selectOne(T t,int id) {
        StringBuffer stringBuffer = new StringBuffer("select * from ");
        list = new ArrayList<Object>();
        Class clazz = t.getClass();
        sql = stringBuffer.append(clazz.getSimpleName()+" where id=?").toString().toLowerCase();
        try {
            connection = JdbcUtil.getInstance().getConnection();
            preparedStatement = connection.prepareStatement(sql);
            preparedStatement.setInt(1,id);
            resultSet = preparedStatement.executeQuery();
            while (resultSet.next()) {
                Object object = clazz.newInstance();
                getField(t);
                int i = 1;
                for (Map.Entry<String, String> entry : map.entrySet()) {
                    if ("int".equals(entry.getValue())) {
                        Method method = clazz.getMethod(getSet(entry.getKey()), int.class);
                        method.invoke(object, resultSet.getInt(i));
                        i++;
                    }
                    if ("String".equals(entry.getValue())) {
                        Method method = clazz.getMethod(getSet(entry.getKey()), String.class);
                        method.invoke(object, resultSet.getString(i));
                        i++;
                    }
                }
                list.add(object);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }finally {
            JdbcUtil.releaseResources(connection,preparedStatement,resultSet);
        }
        return list;
    }

    /**
     * 根据id删除记录
     * @param t
     * @param id
     */
    @Override
    public void delete(T t, int id){
        StringBuffer stringBuffer = new StringBuffer("delete from ");
        Class clazz = t.getClass();
        String tableName = clazz.getSimpleName().toLowerCase();
        sql = stringBuffer.append(tableName + " where id=?").toString();
        try {
            connection = JdbcUtil.getInstance().getConnection();
            preparedStatement = connection.prepareStatement(sql);
            preparedStatement.setInt(1, id);
            preparedStatement.execute();
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            JdbcUtil.releaseResources(connection, preparedStatement, null);
        }
    }

    /**
     * 修改密码
     * @param t
     * @param password
     * @param id
     */
    @Override
    public void update(T t, String password, int id) {
        Class clazz = t.getClass();
        String tableName = clazz.getSimpleName().toLowerCase();
        StringBuffer stringBuffer = new StringBuffer("update " + tableName + " set password=? where id=?");
        sql = stringBuffer.toString();
        try {
            connection = JdbcUtil.getInstance().getConnection();
            preparedStatement = connection.prepareStatement(sql);
            preparedStatement.setString(1, password);
            preparedStatement.setInt(2, id);
            preparedStatement.execute();
        } catch (SQLException e) {
            e.printStackTrace();
        } finally {
            JdbcUtil.releaseResources(connection, preparedStatement, null);
        }
    }

    /**
     * 增加记录
     * @param t
     */
    @Override
    public void insert(T t) {
        StringBuffer stringBuffer = new StringBuffer("insert into ");
        Class clazz = t.getClass();
        String table = clazz.getSimpleName().toLowerCase();
        try {
            Object object = t;
            getField(object);
            stringBuffer.append(table + " values(");
            for (int i = 0; i < map.size(); i++) {
                if (i == map.size() - 1) {
                    stringBuffer.append("?)");
                }else {
                    stringBuffer.append("?,");
                }
            }
            sql = stringBuffer.toString();
            connection = JdbcUtil.getInstance().getConnection();
            preparedStatement = connection.prepareStatement(sql);
            System.out.println(sql);
            int i=1;
            for (Map.Entry<String, String> entry : map.entrySet()) {
                if ("int".equals(entry.getValue())) {
                    Method method = clazz.getMethod(get(entry.getKey()));
                    System.out.println(method.invoke(object,null));
                    preparedStatement.setInt(i,(int)method.invoke(object,null));
                    i++;
                }
                if ("String".equals(entry.getValue())) {
                    Method method = clazz.getMethod(get(entry.getKey()));
                    preparedStatement.setString(i,(String)method.invoke(object,null));
                    i++;
                }
            }
            preparedStatement.execute();

        }  catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }finally {
            JdbcUtil.releaseResources(connection,preparedStatement,null);
        }
    }



    /**
     * 根据属性名拼接set方法字符串
     * @param str
     * @return
     */
    public static String getSet(String str) {

        return "set" + str.substring(0, 1).toUpperCase() + str.substring(1);
    }

    /**
     * 拼接get方法
     * @param str
     * @return
     */
    public static String get(String str) {
        return "get" + str.substring(0, 1).toUpperCase() + str.substring(1);
    }

    public static void getField(Object object) {
        Class clazz = object.getClass();
        // 获取实体类的所有属性,返回Field数组
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            String type = field.getGenericType().toString();
            /*如果是String听会带有class java.lang.String截取再放入map中,其他直接放入
            * 把属性名作为键,属性类型作为值*/
            if ("class java.lang.String".equals(type)) {
                int index = type.lastIndexOf(".");
                map.put(field.getName(), type.substring(index + 1));
            } else {
                map.put(field.getName(), field.getGenericType().toString());
            }
        }
    }

}

数据库工具类:JdbcUtil  用到了单例模式

package com_util;

import com.mchange.v2.c3p0.ComboPooledDataSource;

import java.beans.PropertyVetoException;
import java.io.IOException;
import java.io.InputStream;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Properties;

public class JdbcUtil {
    private Properties properties = new Properties();
    private static String dirverName;
    private static String url;
    private static String username;
    private static String password;

    private static ComboPooledDataSource dataSource;
    private static JdbcUtil jdbcUtil = new JdbcUtil();

    private JdbcUtil() {
        try {
            InputStream inputStream = JdbcUtil.class.getClassLoader()
                    .getResourceAsStream("datebase.properties");
//            从输入字节流读取属性列表(键和元素对)
            properties.load(inputStream);
//            用此属性列表中指定的键搜索属性,获取驱动,url,username,password
            dirverName = properties.getProperty("driverName").trim();
            url = properties.getProperty("url").trim();
            username = properties.getProperty("username").trim();
            password = properties.getProperty("password").trim();

            dataSource = new ComboPooledDataSource();
            dataSource.setUser(username);
            dataSource.setPassword(password);
            dataSource.setJdbcUrl(url);
            dataSource.setDriverClass(dirverName);
            dataSource.setInitialPoolSize(5); //初始化连接数
            dataSource.setMinPoolSize(1);//最小连接数
            dataSource.setMaxPoolSize(20);//最大连接数
            dataSource.setMaxStatements(50);//最长等待时间
            dataSource.setMaxIdleTime(60);//最大空闲时间,单位毫秒
        } catch (PropertyVetoException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static JdbcUtil getInstance(){
        return jdbcUtil;
    }

    public synchronized Connection getConnection() {
        Connection conn = null;
        try {
            conn=dataSource.getConnection();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return conn;
    }

//关闭连接工具方法
    public static void releaseResources(Connection connection, PreparedStatement preparedStatement, ResultSet resultSet) {
        if (resultSet != null) {
            try {
                resultSet.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if (connection != null) {
            try {
                connection.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        if (preparedStatement != null) {
            try {
                preparedStatement.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
    }
}

实体类:用于测试

package com_domain;

public class Users {
  private int id;
  private String name;
  private String password;
  private int aid;

  @Override
  public String toString() {
    return "Users{" +
            "id=" + id +
            ", name='" + name + '\'' +
            ", password='" + password + '\'' +
            ", aid=" + aid +
            '}';
  }

  public int getId() {
    return id;
  }

  public void setId(int id) {
    this.id = id;
  }

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }

  public String getPassword() {
    return password;
  }

  public void setPassword(String password) {
    this.password = password;
  }

  public int getAid() {
    return aid;
  }

  public void setAid(int aid) {
    this.aid = aid;
  }
}

datebase.properties数据库连接配置文件

driverName=com.mysql.jdbc.Driver
url=jdbc:mysql://localhost:3306/test
username=root
password=root

代码放在了github上,可以下载完整代码(Code_story仓库fanxing文件夹):https://github.com/Ai-yoo/Code_story.git

posted @ 2017-11-11 19:40  In_new  阅读(386)  评论(0编辑  收藏  举报