在经过一系列的问题得到解决之后,泛型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. 1000多个项目中的十大JavaScript错误以及如何避免

    通过统计数据库中的1000多个项目,我们发现在 JavaScript 中最常出现的错误有10个.下面会向大家介绍这些错误发生的原因以及如何防止. 对于这些错误发生的次数,我们是通过收集的数据统计得出的 ...

  2. OJ的初步了解

    注意源文件的注释可能跟题目不一样. 注意工程文件已有主函数. 注意输出结果还是返回值. 注意带参数的方法不用手动输入. 注意提交的次数的正确率会计入编程能力.

  3. mysql字符串连接

    用SQL Server 连接字符串是用“+” 现在数据库用mysql, 写个累加两个字段值SQL语句居然不支持"+",郁闷了半天在网上查下,才知道mysql里的+是数字相加的操作, ...

  4. PCI设备内存操作函数总结

    1.  ExAllocatePool() 函数说明: ExAllocatePool allocates pool memory of the specified type and returns a ...

  5. Linux中挂载Windows共享出来的目录

    Windows中1.新建文件夹,创建共享目录 右键文件夹,共享 2.设置访问方式 Everyone,添加确认 Linux-ubuntu中1.安装cifs#sudo apt-get install ci ...

  6. JavaScript小括号、中括号、大括号的多义性

    语义1,函数声明时参数表 func(arg1,arg2){ // ... } 语义2,和一些语句联合使用以达到某些限定作用 // 和for in一起使用 for(var a in obj){ // . ...

  7. js实现内容点击复制

    <!DOCTYPE html><html> <head> <script type="text/javascript"> funct ...

  8. (luogu P3358)最长k可重区间集问题 [TPLY]

    最长k可重区间集问题 题目链接 https://www.luogu.org/problemnew/show/3358 做法 所有点向下一个点连容量为k费用为0的边 l和r连容量为1费用为区间长度的边 ...

  9. 清橙A1212:剪枝

    题面 清橙 Sol 一种新的树上\(DP\)姿势 从左往右按链\(DP\) 做法: 维护两个栈\(S1\),\(S2\) \(S1\)存当前的链 \(S2\)存分叉点以下要改的链 \(Dfs\),弄一 ...

  10. HNOI2008玩具装箱

    斜率优化 # include <stdio.h> # include <stdlib.h> # include <iostream> # include <s ...