自己动手写泛型dao

时间:2024-10-29 21:05:44

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

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

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

下面开始正题:

代码结构:

自己动手写泛型dao

在例子中用到了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