Java学习笔记之使用反射+泛型构建通用DAO
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的更多相关文章
- Java学习笔记54(反射详解)
反射概念: java反射机制是在运行状态中,对于任意一个类,都能知道所有属性和方法 对于任意一个对象都能调用它的任意一个方法和属性,这种动态获取和调用的功能称为java的反射机制 实际作用: 已经完成 ...
- Java学习笔记--注解和反射
注解和反射 1. 注解 注解作用: 对程序做出解释 被其他程序读取 注解格式: @注释名,还可以添加一些参数值,例如@SuppressWarnings(value="unchecked&qu ...
- Java学习笔记八(反射)
1.介绍 反射为Java程序在执行时提供了动态的能力.利用反射能够在执行时对程序进行动态的控制.本篇博客着重解说一下Java中的反射. 2.Class类的使用 在Java执行过程中,每一个类被载入后都 ...
- Java学习笔记【十、泛型】
简介 Java 泛型(generics)是 JDK 5 中引入的一个新特性, 泛型提供了编译时类型安全检测机制,该机制允许程序员在编译时检测到非法的类型. 泛型的本质是参数化类型,也就是说所操作的数据 ...
- Java学习笔记【一、环境搭建】
今天把java的学习重新拾起来,一方面是因为公司的项目需要用到大数据方面的东西,需要用java做语言 另一方面是原先使用的C#公司也在慢慢替换为java,为了以后路宽一些吧,技多不压身 此次的学习目标 ...
- 20145330第八周《Java学习笔记》
20145330第八周<Java学习笔记> 第十五章 通用API 通用API 日志:日志对信息安全意义重大,审计.取证.入侵检验等都会用到日志信息 日志API Logger:注意无法使用构 ...
- JAVA学习笔记—review基本知识[反射与异常]
JAVA学习笔记—review基本知识[反射与异常] 1.异常: 1.1异常的分类: Java会将所有的异常封装成对象,其根本父类为Throwable. Throwable有两个子类:Error 和E ...
- 《Java学习笔记(第8版)》学习指导
<Java学习笔记(第8版)>学习指导 目录 图书简况 学习指导 第一章 Java平台概论 第二章 从JDK到IDE 第三章 基础语法 第四章 认识对象 第五章 对象封装 第六章 继承与多 ...
- Java学习笔记4
Java学习笔记4 1. JDK.JRE和JVM分别是什么,区别是什么? 答: ①.JDK 是整个Java的核心,包括了Java运行环境.Java工具和Java基础类库. ②.JRE(Java Run ...
随机推荐
- shell 知识
解压 tar.bz2文件 bunzip2 linux-2.6.13.tar.bz2 | tar xvf -
- git 撤销提交的文件
一.问题 近期在使用git时遇到一个问题,就是在git上传文件时,将一个100兆的大文件添加到了git,并执行了push操作,这时在上传完毕后,会提示这个错误 Large files detected ...
- openSUSE 11 上的配置可以Xmanager远程桌面
openSUSE 11 上的配置(适用于默认图形环境为KDE的Linux): 1.配置KDM. openSUSE 11的默认图形环境为KDE,虽然可以同时安装GDM和KDM,但默认只启动了KDM.所以 ...
- Android Studio 1.0.1 + Genymotion安卓模拟器打造高效安卓开发环境
我们开发安卓大多是使用Eclipse和安卓SDK中自带的安卓模拟器.当然,Google早就推出了自己的安卓开发环境——Android studio,在不久前,Google发布了Android Stud ...
- 【转】优化Web程序的最佳实践
自动排版有点乱,看着蛋疼,建议下载中文PDF版阅读或阅读英文原文. Yahoo!的Exceptional Performance团队为改善Web性能带来最佳实践.他们为此进行了 一系列的实验.开发了各 ...
- 网络异步编程(C#)团购课
新生命开发团队大石头讲解网络异步编程(C#) 内容:网络编程基础.IOCP.APM.SAEA 时长:2~3小时 价格:20元,20人及以上成团,http://item.taobao.com/item. ...
- ssc
接了一个ssc的小项目,却因为对方的不作答而半途而废.我写了一天的代码算是废了. 主程序 <?xml version="1.0" encoding="utf-8&q ...
- 我心中的核心组件(可插拔的AOP)~第四回 异常拦截器
回到目录 之前说过有关拦截器的文章,第二回 缓存拦截器,事实上,在那讲里说的最多是AOP和缓存组件,对于拦截的概念并没有详细的说明,这一讲,不说AOP,主要说一下拦截器,拦截器Interceptio ...
- Fedora Static Configure
Background Currenlty! I am work on fedora system, but the static-ip has required, but the fedora hav ...
- iOS-----用LLDB调试,让移动开发更简单(二)
image lookup –address 当我们有一个地址,想查找这个地址具体对应的文件位置,可以使用image lookup --address,简写为image lookup -a e.g: 当 ...