PS:最近简单的学了学后台Servlet+JSP.也就只能学到这里了.没那么多精力去学SSH了,毕竟Android还有很多东西都没学完..

学习内容:

1.如何使用反射+泛型构建通用DAO.

1.使用泛型+反射构建通用DAO.

 DAO的概念曾经写过.其实就是数据访问对象,Date Access Object.其实就是数据库中的数据和Java对象里的一种关联关系的一系列操作.由于以前写过这个概念.就不啰嗦了..简单说一说思想.

 比如说:有两张表 User表和Shop表.

 这是User表中需要进行的操作.

public interface UserDao {
void add(User user);
void delete(User user);
void update(User user);
User select(User user);
}

这是Shop表中需要进行的操作.

public interface ShopDao {
void add(Shop shop);
void delete(Shop shop);
void update(Shop shop);
Shop select(Shop shop);
}

不 难发现,二者都有相同的操作.这样使得代码冗余度较高.那么能否将这两个DAO相同的方法封装成一个呢.这是可以的.这样就构建了一个BaseDao里面 封装了二者相同的操作.当我们需要操作表的时候,我们将T换成User或者是Shop就可以了.当我们实际项目面对的表有非常多的时候,如果都具有相同的 方法.那么就可以这样进行抽取.

public interface BaseDao<T> {
void add(T t);
void delete(T t);
void update(T t);
T select(T t);
}

 这样就构建了一个通用的DAO抽象接口.这里我拿User表来说,如果User表还有其他的业务逻辑呢(比如说查询所有信息等等).那么我们只需要这样.

public interface UserDao extends BaseDao<User> {

    //按照行查询,额外的业务逻辑.
List<User>findAll();
}

这样我们只需要定义一个新的UserDao就可以了,它继承了BaseDao中的所有方法,当有额外的业务逻辑的时候,只需要添加额外方法就可以了.这样光有接口当然是不行的.我们需要有具体的实现.

 我们先看BaseDao的实现类BaseDaoImp

 我们来看一下思路.

 先上一张原理图.

 1.首先我们如果想对User表进行操作,那么我们首先需要获取User类型.告诉BaseDaoImp,我们当前是需要对User表进行操作.因此构造函数就是用来干这个的.

 2. 当我们获取了User类型之后,如果想要对其进行操作,那么首先需要知道 sql 语句,因此我们需要对sql语句进行拼接.那么拼接过程中,我们需要知道User表内部到底声明了哪些变量.这样就需要使用反射机制.通过反射机制来获取 User实体类中声明的变量,然后对sql进行相关的拼接.那么getsql函数用来完成sql的拼接过程.

 3. 那么拼接完之后还是不行,因为拼接出来的sql语句是这样的:insert into User(id,username,password,email,grade) values(?,?,?,?,?)我们需要对占位符进行赋值操作.那么首先我们需要获取具体的值,那么setArgs就是来获取属性的具体值的.

 4.当获取了具体的值之后,我们就可以通过sql提供给我们的相关函数来执行sql语句了.

 这里函数其实都非常的简单,只要细看,还是能明白其中的道理的.

package com.example.daoimp;

import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import com.example.dao.BaseDao;
import com.example.helper.JdbcDaoHelper; //通用DAO public class BaseDaoImp<T> implements BaseDao<T> { /** 操作常量 */
public static final String SQL_INSERT = "insert";
public static final String SQL_UPDATE = "update";
public static final String SQL_DELETE = "delete";
public static final String SQL_SELECT = "select"; private Class<T> EntityClass; // 获取实体类 private PreparedStatement statement; private String sql; private Object argType[]; private ResultSet rs; @SuppressWarnings("unchecked")
public BaseDaoImp() { /**
* 传递User就是 com.example.daoimp.BaseDaoImp<com.example.bean.User>
* 传递Shop就是 com.example.daoimp.BaseDaoImp<com.example.bean.Shop>
* */
ParameterizedType type = (ParameterizedType) getClass()
.getGenericSuperclass(); /**
* 这里如果传递的是User.那么就是class com.example.bean.User
* 如果传递的是Shop. 那么就是class com.example.bean.Shop
* */
EntityClass = (Class<T>) type.getActualTypeArguments()[0];
} @Override
public void add(T t) {
// TODO Auto-generated method stub
sql = this.getSql(SQL_INSERT); //获取sql.
// 赋值.
try {
argType = setArgs(t, SQL_INSERT);
statement = JdbcDaoHelper.getPreparedStatement(sql); //实例化PreparedStatement.
//为sql语句赋值.
statement = JdbcDaoHelper.setPreparedStatementParam(statement,
argType);
statement.executeUpdate(); //执行语句.
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
JdbcDaoHelper.release(statement, null); //释放资源.
}
} @Override
public void delete(T t) {
// TODO Auto-generated method stub
sql = this.getSql(SQL_DELETE);
try {
argType = this.setArgs(t, SQL_DELETE);
statement = JdbcDaoHelper.getPreparedStatement(sql);
statement = JdbcDaoHelper.setPreparedStatementParam(statement,
argType);
statement.executeUpdate();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
JdbcDaoHelper.release(statement, null);
}
} @Override
public void update(T t) {
// TODO Auto-generated method stub
sql = this.getSql(SQL_UPDATE);
try {
argType = setArgs(t, SQL_UPDATE);
statement = JdbcDaoHelper.getPreparedStatement(sql);
statement = JdbcDaoHelper.setPreparedStatementParam(statement,
argType);
statement.executeUpdate();
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
} finally {
JdbcDaoHelper.release(statement, null);
}
} @Override
public T select(T t) {
// TODO Auto-generated method stub
sql = this.getSql(SQL_SELECT);
T obj = null;
try {
argType = setArgs(t, SQL_SELECT);
statement = JdbcDaoHelper.getPreparedStatement(sql);
statement = JdbcDaoHelper.setPreparedStatementParam(statement,
argType);
rs = statement.executeQuery();
Field fields[] = EntityClass.getDeclaredFields();
while (rs.next()) {
obj = EntityClass.newInstance();
for (int i = 0; i < fields.length; i++) {
fields[i].setAccessible(true);
fields[i].set(obj, rs.getObject(fields[i].getName()));
}
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return obj; } // sql拼接函数 形如 : insert into User(id,username,password,email,grade) values(?,?,?,?,?)
private String getSql(String operator) { StringBuffer sql = new StringBuffer();
// 通过反射获取实体类中的所有变量
Field fields[] = EntityClass.getDeclaredFields(); // 插入操作
if (operator.equals(SQL_INSERT)) {
sql.append("insert into " + EntityClass.getSimpleName());
sql.append("(");
for (int i = 0; fields != null && i < fields.length; i++) {
fields[i].setAccessible(true); //这句话必须要有,否则会抛出异常.
String column = fields[i].getName();
sql.append(column).append(",");
}
sql = sql.deleteCharAt(sql.length() - 1);
sql.append(") values (");
for (int i = 0; fields != null && i < fields.length; i++) {
sql.append("?,");
}
sql.deleteCharAt(sql.length() - 1);
// 是否需要添加分号
sql.append(")");
} else if (operator.equals(SQL_UPDATE)) {
sql.append("update " + EntityClass.getSimpleName() + " set ");
for (int i = 0; fields != null && i < fields.length; i++) {
fields[i].setAccessible(true);
String column = fields[i].getName();
if (column.equals("id")) {
continue;
}
sql.append(column).append("=").append("?,");
}
sql.deleteCharAt(sql.length() - 1);
sql.append(" where id=?");
} else if (operator.equals(SQL_DELETE)) {
sql.append("delete from " + EntityClass.getSimpleName()
+ " where id=?");
} else if (operator.equals(SQL_SELECT)) {
sql.append("select * from " + EntityClass.getSimpleName()
+ " where id=?");
}
return sql.toString();
} // 获取参数.
private Object[] setArgs(T entity, String operator)
throws IllegalArgumentException, IllegalAccessException { Field fields[] = EntityClass.getDeclaredFields();
if (operator.equals(SQL_INSERT)) { Object obj[] = new Object[fields.length];
for (int i = 0; obj != null && i < fields.length; i++) {
fields[i].setAccessible(true);
obj[i] = fields[i].get(entity);
}
return obj; } else if (operator.equals(SQL_UPDATE)) { Object Tempobj[] = new Object[fields.length];
for (int i = 0; Tempobj != null && i < fields.length; i++) {
fields[i].setAccessible(true);
Tempobj[i] = fields[i].get(entity);
} Object obj[] = new Object[fields.length];
System.arraycopy(Tempobj, 1, obj, 0, Tempobj.length - 1);
obj[obj.length - 1] = Tempobj[0];
return obj; } else if (operator.equals(SQL_DELETE)) { Object obj[] = new Object[1];
fields[0].setAccessible(true);
obj[0] = fields[0].get(entity);
return obj;
} else if (operator.equals(SQL_SELECT)) { Object obj[] = new Object[1];
fields[0].setAccessible(true);
obj[0] = fields[0].get(entity);
return obj;
}
return null;
} }

这样就对BaseDao进行了具体的实现.因为我们的User表还有其他额外的操作,那么我们只需要这样.它通过继承BaseDaoImp,然后实现UserDao接口,那么UserDaoImp就即具有了BaseDaoImp的通用方法,还具有了自己其他的额外方法.

package com.example.daoimp;

import java.lang.reflect.ParameterizedType;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.util.ArrayList;
import java.util.List; import com.example.bean.User;
import com.example.dao.UserDao;
import com.example.helper.JdbcDaoHelper; public class UserDaoImp extends BaseDaoImp<User> implements UserDao { private Class<?> EntityClass; private String sql; private PreparedStatement statement; private ResultSet rs; private List<User> list; public UserDaoImp() { ParameterizedType type = (ParameterizedType) getClass()
.getGenericSuperclass();
EntityClass = (Class<?>) type.getActualTypeArguments()[0];
} @Override
public List<User> findAll() {
// TODO Auto-generated method stub
StringBuffer b = new StringBuffer();
list = new ArrayList<User>();
sql = b.append("select * from " + EntityClass.getSimpleName())
.toString();
try {
statement = JdbcDaoHelper.getPreparedStatement(sql);
rs = statement.executeQuery();
while (rs.next()) {
User user = new User();
user.setId(rs.getInt("id"));
user.setPassword(rs.getString("password"));
user.setEmail(rs.getString("email"));
user.setUsername(rs.getString("username"));
user.setGrade(rs.getInt("grade"));
list.add(user);
}
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return list;
} }

有 了他们,我们就可以进行具体的操作了,如果还有Shop表,那么同理我们可以去创建一个ShopDao去继承BaseDao,然后在自己的ShopDao 定义其他的额外方法就可以了.当表非常多的时候,我们就可以采用这种思想进行封装.这样写出的代码质量就显得非常的高,耦合度也非常的松散.

 在添加上工具类.

package com.example.helper;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException; public class JdbcDaoHelper { private static final String USER = "root"; private static final String PASSWORD = ""; private static final String URL = "jdbc:mysql://localhost:3306/usermanager"; private static Connection con; // 获取数据库连接对象
public static Connection getConnection() { if (con == null) {
try {
Class.forName("com.mysql.jdbc.Driver");
con = DriverManager.getConnection(URL, USER, PASSWORD);
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
} else {
return con;
}
return con;
} public static PreparedStatement getPreparedStatement(String sql)
throws SQLException { return getConnection().prepareStatement(sql);
} public static PreparedStatement setPreparedStatementParam(
PreparedStatement statement, Object obj[]) throws SQLException { for (int i = 0; i < obj.length; i++) {
statement.setObject(i + 1, obj[i]);
}
return statement;
} // 释放资源
public static void release(PreparedStatement ps, ResultSet rs) {
try {
if (con != null) {
con.close();
con = null;
}
if (ps != null) {
ps.close();
ps = null;
}
if (rs != null) {
rs.close();
rs = null;
}
} catch (Exception e) {
// TODO: handle exception
}
} }

最后加上UserBean.

package com.example.bean;

public class User {

    private int id;
private String username;
private String password;
private String email;
private int grade; public User(){ } public User(int id,String username,String password,String email,int grade){
this.id = id;
this.username = username;
this.password = password;
this.email = email;
this.grade = grade;
} public int getId() {
return id;
} public void setId(int id) {
this.id = id;
} public String getUsername() {
return username;
} public void setUsername(String username) {
this.username = username;
} public String getPassword() {
return password;
} public void setPassword(String password) {
this.password = password;
} public String getEmail() {
return email;
} public void setEmail(String email) {
this.email = email;
} public int getGrade() {
return grade;
} public void setGrade(int grade) {
this.grade = grade;
} }

测试类.

package com.example.jdbc;

import java.util.List;

import com.example.bean.User;
import com.example.daoimp.UserDaoImp; public class Main { /**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub List<User>list = null;
UserDaoImp imp = new UserDaoImp();
list = imp.findAll();
for(User user:list){
System.out.println(user.getId()+" "+user.getUsername()+" "+user.getPassword()+" "+user.getEmail()+" "+user.getGrade());
}
//insert操作.
User user = new User();
user.setId(1);
user.setUsername("代码如风");
user.setPassword("123456");
user.setEmail("123");
user.setGrade(5);
imp.add(user);
//update操作.
User user_1 = new User();
user.setId(1);
user.setUsername("心静如水");
user.setPassword("123456");
user.setEmail("123");
user.setGrade(5);
imp.update(user_1);
} }

 注意(别忘了引入mysql.jar包.)

 最后放上一个源代码:files.cnblogs.com/files/RGogoing/JDBCDao.rar

Java学习笔记之使用反射+泛型构建通用DAO的更多相关文章

  1. Java学习笔记54(反射详解)

    反射概念: java反射机制是在运行状态中,对于任意一个类,都能知道所有属性和方法 对于任意一个对象都能调用它的任意一个方法和属性,这种动态获取和调用的功能称为java的反射机制 实际作用: 已经完成 ...

  2. Java学习笔记--注解和反射

    注解和反射 1. 注解 注解作用: 对程序做出解释 被其他程序读取 注解格式: @注释名,还可以添加一些参数值,例如@SuppressWarnings(value="unchecked&qu ...

  3. Java学习笔记八(反射)

    1.介绍 反射为Java程序在执行时提供了动态的能力.利用反射能够在执行时对程序进行动态的控制.本篇博客着重解说一下Java中的反射. 2.Class类的使用 在Java执行过程中,每一个类被载入后都 ...

  4. Java学习笔记【十、泛型】

    简介 Java 泛型(generics)是 JDK 5 中引入的一个新特性, 泛型提供了编译时类型安全检测机制,该机制允许程序员在编译时检测到非法的类型. 泛型的本质是参数化类型,也就是说所操作的数据 ...

  5. Java学习笔记【一、环境搭建】

    今天把java的学习重新拾起来,一方面是因为公司的项目需要用到大数据方面的东西,需要用java做语言 另一方面是原先使用的C#公司也在慢慢替换为java,为了以后路宽一些吧,技多不压身 此次的学习目标 ...

  6. 20145330第八周《Java学习笔记》

    20145330第八周<Java学习笔记> 第十五章 通用API 通用API 日志:日志对信息安全意义重大,审计.取证.入侵检验等都会用到日志信息 日志API Logger:注意无法使用构 ...

  7. JAVA学习笔记—review基本知识[反射与异常]

    JAVA学习笔记—review基本知识[反射与异常] 1.异常: 1.1异常的分类: Java会将所有的异常封装成对象,其根本父类为Throwable. Throwable有两个子类:Error 和E ...

  8. 《Java学习笔记(第8版)》学习指导

    <Java学习笔记(第8版)>学习指导 目录 图书简况 学习指导 第一章 Java平台概论 第二章 从JDK到IDE 第三章 基础语法 第四章 认识对象 第五章 对象封装 第六章 继承与多 ...

  9. Java学习笔记4

    Java学习笔记4 1. JDK.JRE和JVM分别是什么,区别是什么? 答: ①.JDK 是整个Java的核心,包括了Java运行环境.Java工具和Java基础类库. ②.JRE(Java Run ...

随机推荐

  1. 管理我的数据之GDBM

    管理我的数据之GDBM 作者 He YiJun – storysnail<at>gmail.com 团队 ls 版权 转载请保留本声明! 本文档包含的原创代码根据General Publi ...

  2. 记AbpSession扩展实现过程

    AbpSession只给了userId和TenantId,这次实际项目中并不够用,网上找了很久也没找到好的实现方法.项目初期没有时间进行研究,最近空了试了一下,大致实现添加额外字段并读取相应值的功能. ...

  3. guzzle调用失败-缺少guzzle

    用composer安装了,但是目前为止还有问题.开发环境是 WAMP PHP5.4.12. 已经打开PHP.ini 的SSL扩展,现在还是提示缺少 curl-ca-bundle.cr 报错 No sy ...

  4. 曲演杂坛--特殊字符/生僻字与varchar

    对于中文版的SQL SERVER,默认安装后使用的默认排序规则为Chinese_PRC_CI_AS,在此排序规则下,使用varchar类型来可以“正常存取”存放中文字符以及一些东南亚国家的字符,同时v ...

  5. 虚拟化平台cloudstack(4)——几个异常

    cloudstack主机添加不成功 CloudStack正常启动,添加区域.提供点和群集都正常,但是添加主机时提示添加不成功. 先添加主机: 然后出现提示: 在网上找了一圈,基本上没什么回复,没办法, ...

  6. LuaAlchemy API 介绍

    The AS3 Sugar provides a Lua-like way to access AS3 class and instance creation, property getter/set ...

  7. js笔记——js异常处理

    异常捕获 try...catch结构: try { //需要捕获的代码块 } catch (e) { console.log(e.name + ": " + e.message); ...

  8. Atitit 马尔可夫过程(Markov process) hmm隐马尔科夫。 马尔可夫链,的原理attilax总结

    Atitit 马尔可夫过程(Markov process) hmm隐马尔科夫. 马尔可夫链,的原理attilax总结 1. 马尔可夫过程1 1.1. 马尔科夫的应用 生成一篇"看起来像文章的 ...

  9. Atitit  循环(loop), 递归(recursion), 遍历(traversal), 迭代(iterate).

    Atitit  循环(loop), 递归(recursion), 遍历(traversal), 迭代(iterate). 1.1. 循环算是最基础的概念, 凡是重复执行一段代码, 都可以称之为循环. ...

  10. salesforce 零基础开发入门学习(七)PickList的value值获取

    之前介绍过PickList类型的声明以及赋值,但是如何取出呢?一个sObject对象可以理解为一条数据.通过sObject直接取恐怕很难做到,因为他只会显示一个值.这时候就要用到Schema命名空间中 ...