在经过一系列的问题得到解决之后,泛型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

自己动手写泛型dao的更多相关文章

  1. 泛型DAO

    最近正在学习泛型DAO,通过网上查阅资料,汇总并自己整理了一下.提前需要学习的知识java反射.泛型 用到的反射如下: Class<T>类 是java.lang包下,Class类的实例表示 ...

  2. 浅谈Java——泛型DAO

    首先解释一下为什么要学习泛型DAO.平时在写DAO的时候是一个接口对应一个实现类,实现类里面要写很多的操作数据库的方法.当我们有很多的javaben的时候我们会写很多的接口和实现类,并且里面的代码都是 ...

  3. 泛型DAO与泛型Service

    泛型Dao与Service 看了几个帖子,泛型Dao与Service的主要目的就是要减少重复代码.具体的说明如下: 1. 定义一个BaseDao接口,此接口包含了一些通用的DAO操作,例如:增加.删除 ...

  4. 一个好用的hibernate泛型dao

    以前从springside2.0上搞下来的很好用的,基本实现dao零编码只要配置xml文件就行了. 先看图: 一共4层,com.demonstration.hibernate.basedao是我加的用 ...

  5. 自己动手写spring容器(3)

    好久没有写博客了,今天闲下来将之前未完成的表达出来. 在之前的文章自己动手写spring容器(2)中完成了对spring的依赖注入的实现,这篇将会介绍spring基于注解的依赖注入的实现. 在一般的J ...

  6. 《项目架构那点儿事》——Hibernate泛型Dao,让持久层简洁起来

    [前言]hibernate作为持久层ORM技术,它对JDBC进行非常轻量级对象封装,使得我们可以随心所欲的使用面向对象的思想来操作数据 库.同时,作为后台开发的支撑,的确扮演了一个举足轻重的角色,那么 ...

  7. 【原创】自己动手写控件----XSmartNote控件

    一.前面的话 在上一篇博文自己动手写工具----XSmartNote [Beta 3.0]中,用到了若干个自定义控件,其中包含用于显示Note内容的简单的Label扩展控件,用于展示标签内容的labe ...

  8. 【原创】自己动手写工具----XSmartNote [Beta 3.0]

    一.前面的话 在动笔之前,一直很纠结到底要不要继续完成这个工具,因为上次给它码代码还是一年多之前的事情,参考自己动手写工具----XSmartNote [Beta 2.0],这篇博文里,很多园友提出了 ...

  9. 【原创】自己动手写工具----XSmartNote [Beta 2.0]

    一.前面的话 在上一篇自己动手写工具----XSmartNote中,我简单介绍了这个小玩意儿的大致界面和要实现的功能,看了一下园子里的评论,评价褒贬不一,有人说“现在那么多云笔记的工具”,“极简版ev ...

随机推荐

  1. Java 多线程入门

    进程与线程 在学习Java多线程之前,先简单复习一下进程与线程的知识. 进程:进程是系统进行资源分配和调度的基本单位,可以将进程理解为一个正在执行的程序,比如一款游戏. 线程:线程是程序执行的最小单位 ...

  2. web前端开发工程师工资多少

      做web前端开发工程师工资高不高?下面千锋小编为大家分析一下:作为目前互联网行业中的主流技术,Web前端一直是占有重要的地位.尤其是近年来HTML5技术的突飞猛进,使Web前端技术有了更好的发展. ...

  3. R+先知︱Facebook大规模时序预测『真』神器——Prophet(遍地代码图)

    经统专业看到预测的packages都是很眼馋的.除了之前的forecast包,现在这个prophet功能也很强大.本packages是由机器之心报道之后,抽空在周末试玩几小时.一些基本介绍可见机器之心 ...

  4. GJB150-2009军用装备实验室环境试验方法新版标准

    http://www.kekaoxing.com/m/view.php?aid=22604 GJB150.1A-2009 军用装备实验室环境试验方法第1部分:通用要求(代替GJB150.1-86)GJ ...

  5. Meet Python

    关于python 入门书<Head First Python>的一些读书笔记,用以备忘. 下载安装Python 下载地址: https://www.python.org/downloads ...

  6. Django学习-8-模板渲染的一些特性

       对于{%for i in list%}来说里面都有一个{{forloop.counter}}每次循环一次记一次数    对于{%for i in list%}来说里面都有一个{{forloop. ...

  7. 三十天学不会TCP,UDP/IP网络编程 - 绅士的开始

    经过了过年的忙碌和年初的懈怠一切的日子,我又开始重新更新了~这是最新的一篇~完整版可以去gitbook(https://www.gitbook.com/@rogerzhu/)看到. 如果对和程序员有关 ...

  8. 【HDU4622】Reincarnation(后缀自动机)

    [HDU4622]Reincarnation(后缀自动机) 题面 Vjudge 题意:给定一个串,每次询问l~r组成的子串的不同子串个数 题解 看到字符串的大小很小 而询问数太多 所以我们预处理任意的 ...

  9. 【BZOJ5020】【THUWC2017】在美妙的数学王国中畅游(Link-Cut Tree,组合数学)

    [BZOJ5020][THUWC2017]在美妙的数学王国中畅游(Link-Cut Tree,组合数学) 题解 Description 数字和数学规律主宰着这个世界. 机器的运转, 生命的消长, 宇宙 ...

  10. 【POJ2387】Til the Cows Come Home (最短路)

    题面 Bessie is out in the field and wants to get back to the barn to get as much sleep as possible bef ...