自己动手写泛型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
自己动手写泛型dao的更多相关文章
- 泛型DAO
最近正在学习泛型DAO,通过网上查阅资料,汇总并自己整理了一下.提前需要学习的知识java反射.泛型 用到的反射如下: Class<T>类 是java.lang包下,Class类的实例表示 ...
- 浅谈Java——泛型DAO
首先解释一下为什么要学习泛型DAO.平时在写DAO的时候是一个接口对应一个实现类,实现类里面要写很多的操作数据库的方法.当我们有很多的javaben的时候我们会写很多的接口和实现类,并且里面的代码都是 ...
- 泛型DAO与泛型Service
泛型Dao与Service 看了几个帖子,泛型Dao与Service的主要目的就是要减少重复代码.具体的说明如下: 1. 定义一个BaseDao接口,此接口包含了一些通用的DAO操作,例如:增加.删除 ...
- 一个好用的hibernate泛型dao
以前从springside2.0上搞下来的很好用的,基本实现dao零编码只要配置xml文件就行了. 先看图: 一共4层,com.demonstration.hibernate.basedao是我加的用 ...
- 自己动手写spring容器(3)
好久没有写博客了,今天闲下来将之前未完成的表达出来. 在之前的文章自己动手写spring容器(2)中完成了对spring的依赖注入的实现,这篇将会介绍spring基于注解的依赖注入的实现. 在一般的J ...
- 《项目架构那点儿事》——Hibernate泛型Dao,让持久层简洁起来
[前言]hibernate作为持久层ORM技术,它对JDBC进行非常轻量级对象封装,使得我们可以随心所欲的使用面向对象的思想来操作数据 库.同时,作为后台开发的支撑,的确扮演了一个举足轻重的角色,那么 ...
- 【原创】自己动手写控件----XSmartNote控件
一.前面的话 在上一篇博文自己动手写工具----XSmartNote [Beta 3.0]中,用到了若干个自定义控件,其中包含用于显示Note内容的简单的Label扩展控件,用于展示标签内容的labe ...
- 【原创】自己动手写工具----XSmartNote [Beta 3.0]
一.前面的话 在动笔之前,一直很纠结到底要不要继续完成这个工具,因为上次给它码代码还是一年多之前的事情,参考自己动手写工具----XSmartNote [Beta 2.0],这篇博文里,很多园友提出了 ...
- 【原创】自己动手写工具----XSmartNote [Beta 2.0]
一.前面的话 在上一篇自己动手写工具----XSmartNote中,我简单介绍了这个小玩意儿的大致界面和要实现的功能,看了一下园子里的评论,评价褒贬不一,有人说“现在那么多云笔记的工具”,“极简版ev ...
随机推荐
- Linux定时及mysql远程
(1)crontab crontab使用方法: (1)使用命令 crontab -e 然后直接编辑定时脚本. 这样执行以后,属于用户自定义的,会被写到 /var/spool/cron 目录下,生成一个 ...
- HDFS读写过程
HDFS的读写过程: 读过程: Client收到用户的读请求——client拿着path向namenode请求文件或者block的datanode列表——client从返回的datanode列表中选择 ...
- react 父子组件互相通信
1,父组件向子组件传递 在引用子组件的时候传递,相当于一个属性,例如: class Parent extends Component{ state = { msg: 'start' }; render ...
- 关于druid的配置说明
<bean id="stat-filter" class="com.alibaba.druid.filter.stat.StatFilter"> & ...
- HighCharts之2D圆环图
HighCharts之2D圆环图 1.实例源码 Donut.html: <!DOCTYPE html> <html> <head> <meta charset ...
- 修改MyEclipse编辑框背景色
修改MyEclipse编辑框背景色 1.未修改之前,编辑框背景色 2.依次操作,"Window--->Preferences" 3.选择"General---> ...
- Tomcat 代码方式启动
配置好参数,只需在Booter类中调用 EmbbedTomcat.main(args); 就可以启动. maven中也需要配置相应插件. import java.io.File; import org ...
- 基于 angular 规范的 commit
基于 angular 规范的 commit commit格式如下: <type>: <subject> <BLANK LINE> <body> type ...
- How to verify Certificate Pinning?
Some friends of mine they worry about the risk of Man-in-the-middle so they ask me how to verify the ...
- freemarker中的substring取子串(十四)
freemarker中的substring取子串 1.substring取子串介绍 (1)表达式?substring(from,to) (2)当to为空时,默认的是字符串的长度 (3)from是第一个 ...