利用JAVA反射机制设计一个通用的DAO

反射机制

反射机制指的是程序在运行时能够获取自身的信息。在java中,只要给定类的名字,    
那么就可以通过反射机制来获得类的所有信息。

反射机制创建类对象

Class c=Class.forName("className");注明:className必须为全名,也就是得包含包名,比如,com.cnblog.Bean;   
    Object obj=c.newInstance();//创建对象的实例

有了类对象就可以对该类的方法及属性进行操作

通用DAO

可以对所有单表的增删查改,无需新建对应的DAO文件,即新增表操作的的时候,只需要建立表的对应的javabean即可,无需新建表的DAO文件

代码结构也比较简单

连接数据库的类 DBConnection.java

DAO的实现类 DAOImpl.java

DAO的代理类 DAOProxy.java

各个表的bean

DBConnection.java 连接数据库的类

package Utils;

import java.sql.Connection;
import java.sql.DriverManager; public class DBConnection {
private Connection conn;
private String url;
private String user;
private String password;
private String driver; public String getUrl() {
return url;
} public void setUrl(String url) {
this.url = url;
} public String getUser() {
return user;
} public void setUser(String user) {
this.user = user;
} public String getPassword() {
return password;
} public void setPassword(String password) {
this.password = password;
} public String getDriver() {
return driver;
} public void setDriver(String driver) {
this.driver = driver;
} public Connection connection()throws Exception{
try{
Class.forName(driver);
}catch(Exception e){
System.out.println("Load error!");
e.printStackTrace();
} try{
conn=DriverManager.getConnection(url, user, password);
}catch(Exception e){
System.out.println("Login error ,please check your login information");
e.printStackTrace();
} return conn; } public void close() throws Exception{ this.conn.close(); } }

DAOImpl.java  增删查改的实现类,所有的bean都作为Object进来,然后通过反射机制拼装数据库操作的sql

query() 传入的bean不需要每个属性都赋值,筛选已赋值的属性拼装sql,筛选的时候利用反射机制中的反射属性Field[] fields =object.getClass().getFields()

insert() 拼装sql时无需筛选未赋值的属性,未赋值的直接插入null

update() 传入两个bean,第一个是更新前的记录,第二个是更新后的记录

delete() 传入的bean不需要每个属性都赋值,筛选已赋值的属性拼装sql,筛选的时候利用反射机制中的反射属性Field[] fields =object.getClass().getFields()

package DAO;

import java.lang.reflect.Field;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList; import Bean.*;
import Utils.DBConnection; public class DAOImpl { private DBConnection dataSource;
DAOImpl(DBConnection dataSource) throws Exception{
this.dataSource=dataSource;
} public ArrayList<Object> query(Object object) throws Exception{
Connection conn=null;
PreparedStatement ps=null;
ResultSet rs=null;
ArrayList result=new ArrayList();
//记录非空的属性值,用于SQL的变量绑定
ArrayList args=new ArrayList(); StringBuilder condition=new StringBuilder();
String sql="select * from "+object.getClass().getSimpleName()+" where 1=1 "; //取出对象中的值作为条件,如果值为null则不加入查询条件中
Field[] fields=object.getClass().getFields();
for(Field field:fields){
field.setAccessible(true);
if(this.isBlank(field.get(object))==false){
condition.append(" and ").append(field.getName()).append("=").append("?");
args.add(field.get(object));
} }
sql=sql+condition.toString(); //访问数据库返回查询结果
try{
conn=dataSource.connection();
ps=conn.prepareStatement(sql);
for(int i=0;i<args.size();i++){
//绑定变量下标从1开始
ps.setObject(i+1, args.get(i));
}
rs=ps.executeQuery(); //将查询结果放到bean中
while(rs.next()){
//利用反射机制新建bean实例
String className=object.getClass().getName();
Class<?> obj=Class.forName(className);
Object resultBean=obj.newInstance();
Field[] resultFields=resultBean.getClass().getFields();
for(Field resultField:resultFields){
resultField.setAccessible(true);
resultField.set(resultBean, rs.getObject(resultField.getName()));
} result.add(resultBean);
} }catch(Exception e){
System.out.println("Operation in database fail");
e.printStackTrace();
}finally{
if(rs != null){ // 关闭记录集
try{
rs.close() ;
}catch(SQLException e){
e.printStackTrace() ;
}
}
if(ps != null){ // 关闭声明
try{
ps.close() ;
}catch(SQLException e){
e.printStackTrace() ;
}
}
if(conn != null){ // 关闭连接对象
try{
conn.close() ;
}catch(SQLException e){
e.printStackTrace() ;
}
} }
return result;
} public boolean insert(Object object) throws Exception{
boolean flag=false;
Connection conn=null;
PreparedStatement ps=null; StringBuilder area=new StringBuilder("(");
StringBuilder value=new StringBuilder("(");
//获取Bean下所有的fields
Field[] fields=object.getClass().getFields();
//组装Sql
String sql="insert into "+object.getClass().getSimpleName(); for(int i=0 ;i<fields.length;i++){
area.append(fields[i].getName());
value.append("?");
if(i<fields.length-1){
area.append(",");
value.append(",");
}
} area.append(")");
value.append(")"); sql=sql+area.toString()+" values "+value.toString();
System.out.println(sql); try{
conn=dataSource.connection();
ps = conn.prepareStatement(sql);
for(int i=0;i<fields.length;i++){
fields[i].setAccessible(true);
//setObject 下标 从1开始
ps.setObject(i+1,fields[i].get(object));
System.out.println(fields[i]);
}
if(ps.executeUpdate()>0){
flag=true;
} }catch(Exception e){
System.out.println("Operation in database fail");
e.printStackTrace();
}finally{
if(ps != null){ // 关闭声明
try{
ps.close() ;
}catch(SQLException e){
e.printStackTrace() ;
}
}
if(conn != null){ // 关闭连接对象
try{
conn.close() ;
}catch(SQLException e){
e.printStackTrace() ;
}
}
} return flag;
} public boolean update(Object previous,Object follow) throws Exception{
boolean flag=false;
Connection conn=null;
PreparedStatement ps=null;
ArrayList preArgs=new ArrayList();
ArrayList folArgs=new ArrayList(); //获取where条件的字段值
Field[] preFields=previous.getClass().getFields(); //获取set的字段值
Field[] folFields=follow.getClass().getFields(); StringBuilder set=new StringBuilder("");
StringBuilder where=new StringBuilder(""); String sql="update "+previous.getClass().getSimpleName()+" set 1=1"; //组装sql语句
for(Field folField:folFields){
//如果bean中的属性值没有被set方法赋值过则不添加到sql语句的条件中
if(this.isBlank(folField.get(follow))==false){
set.append(",").append(folField.getName()).append(" = ").append("?");
folArgs.add(folField.get(follow)); }
} sql=sql+set.toString()+" where 1=1 "; for(Field preField:preFields){
if(this.isBlank(preField.get(previous))==false){ where.append(" and ").append(preField.getName()).append(" = ").append("?");
preArgs.add(preField.get(previous));
}
} sql=sql+where.toString();
System.out.println(sql); try{ conn=dataSource.connection();
ps=conn.prepareStatement(sql);
//先绑定set部分的变量,然后再绑定where部分的变量
for(int i=0;i<(folArgs.size()+preArgs.size());i++){
if(i<folArgs.size()){
ps.setObject(i+1, folArgs.get(i));
}else{
ps.setObject(i+1, preArgs.get(i-folArgs.size()));
} }
if(ps.executeUpdate()>0){
flag=true;
}
}catch(Exception e){
System.out.println("Operation in database fail");
e.printStackTrace();
}finally{
if(ps != null){ // 关闭声明
try{
ps.close() ;
}catch(SQLException e){
e.printStackTrace() ;
}
}
if(conn != null){ // 关闭连接对象
try{
conn.close() ;
}catch(SQLException e){
e.printStackTrace() ;
}
}
} return flag;
} public boolean delete(Object object) throws Exception{
boolean flag=false;
Connection conn=null;
PreparedStatement ps=null;
ArrayList args=new ArrayList(); //获取where条件的字段值
Field[] fields=object.getClass().getFields();
StringBuilder where=new StringBuilder(""); //拼装sql
String sql="delect from "+object.getClass().getSimpleName()+" where 1=1"; for(Field field:fields){
//如果属性值没有被set方法设置过,则不添加到条件进去
if(this.isBlank(field.get(object))==false){ where.append(" and ").append(field.getName()).append("=").append("?");
args.add(field.get(object));
}
} sql=sql+where.toString();
System.out.println(sql); try{
conn=dataSource.connection();
ps=conn.prepareStatement(sql);
for(int i=0;i>args.size();i++){
//绑定变量下标从1开始
ps.setObject(i+1, args.get(i));
}
if(ps.executeUpdate()>0){
flag=true;
}
}catch(Exception e){
System.out.println("Operation in database fail");
e.printStackTrace();
}finally{
if(ps != null){ // 关闭声明
try{
ps.close() ;
}catch(SQLException e){
e.printStackTrace() ;
}
}
if(conn != null){ // 关闭连接对象
try{
conn.close() ;
}catch(SQLException e){
e.printStackTrace() ;
}
}
}
return flag;
} /*
* @description 判断bean属性值是否为空
*/
public boolean isBlank(Object object){ boolean flag;
if(null==object||"".equals(object)){
flag=true;
}else{
flag=false;
} return flag;
} }

DAOProxy.java DAO的代理,DBConnection和DAOImpl的连接桥梁

package DAO;

import java.util.ArrayList;

import Utils.DBConnection;

public class DAOProxy {
private DBConnection dataSource;
DAOProxy(DBConnection dataSource){
this.dataSource=dataSource; } public ArrayList doQuery(Object object)throws Exception{
ArrayList result=new ArrayList();
DAOImpl dao=new DAOImpl(dataSource);
result=dao.query(object);
return result;
} public boolean doInsert(Object object)throws Exception{
boolean result;
DAOImpl dao=new DAOImpl(dataSource);
result=dao.insert(object);
return result;
} public boolean doUpdate(Object previous,Object follow)throws Exception{
boolean result;
DAOImpl dao=new DAOImpl(dataSource);
result=dao.update(previous,follow);
return result; } public boolean doDelete(Object object)throws Exception{
boolean result;
DAOImpl dao=new DAOImpl(dataSource);
result=dao.delete(object);
return result;
} }

Bean.java 数据库表对应的javabean

建立对应的javabean时需要注意,属性类型最好不要用基本数据类型,因为这些数据类型会自动初始化,即int类型的属性默认是0,如果没有给该属性赋值,即插入到数据库的时候是0而不是空

其中一个bean的例子

package Bean;

import java.math.BigDecimal;
import java.util.Date; public class Employee {
public BigDecimal emp_id;
public String emp_name;
public String emp_dep;
public Date entry_time;
public BigDecimal getEmp_id() {
return emp_id;
}
public void setEmp_id(BigDecimal emp_id) {
this.emp_id = emp_id;
}
public String getEmp_name() {
return emp_name;
}
public void setEmp_name(String emp_name) {
this.emp_name = emp_name;
}
public String getEmp_dep() {
return emp_dep;
}
public void setEmp_dep(String emp_dep) {
this.emp_dep = emp_dep;
}
public Date getEntry_time() {
return entry_time;
}
public void setEntry_time(Date entry_time) {
this.entry_time = entry_time;
} }

测试代码

public static void main(String[] args){

//设置数据库连接
     DBConnection dbSource=new DBConnection();
    dbSource.setDriver(driver);
    dbSource.setUser(user);
    dbSource.setPassword(password);
    dbSource.setUrl(url);

DAOProxy testDAO=new DAOProxy(dbSource)
    Employee jack=new Employee();
    jack.setEmp_id(123);
    jack.setEmp_name("jack");
    jack.setEmp_dep("dev");
    testDAO.doInsert(jack);
  
    Employee jack2=new Employee();
    jack2.setEmp_id(123);
    jack2.setEmp_name("jack");
    jack2.setEmp_dep("test");
    testDAO.doUpdate(jack, jack2);

}

利用JAVA反射机制设计通用的DAO的更多相关文章

  1. 利用java反射机制 读取配置文件 实现动态类载入以及动态类型转换

    作者:54dabang 在spring的学习过程之中,我们能够看出通过配置文件来动态管理bean对象的优点(松耦合 能够让零散部分组成一个总体,而这些总体并不在意之间彼此的细节,从而达到了真正的物理上 ...

  2. 利用Java反射机制对实体类的常用操作工具类ObjectUtil

    代码: ObjectUtil类: import java.lang.reflect.Field; import java.math.BigDecimal; import java.text.Simpl ...

  3. 利用Java反射机制将Bean转成Map

    import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang ...

  4. 利用java反射机制编写solr通用的java客户端

    一.前言 通过上一篇的讲解,我们知道了dynamicFiled字段,它是动态的,不需要显示的声明.而且一些常用的基本类型solr已经默认给我们创建好了. 例如:*_i,*_is,等. 如果我们要使用动 ...

  5. 不使用BeanUtils,利用Java反射机制:表单数据自动封装到JavaBean

    在百度搜“java反射 将表单数据自动封装到javabean ”,第一页显示的都是一样的代码,都是利用导入第三方jar包<commons-beanutils>和<commons-lo ...

  6. 利用java反射机制实现读取excel表格中的数据

    如果直接把excel表格中的数据导入数据库,首先应该将excel中的数据读取出来. 为了实现代码重用,所以使用了Object,而最终的结果是要获取一个list如List<User>.Lis ...

  7. 利用JAVA反射机制将JSON数据转换成JAVA对象

    net.sf.json.JSONObject为我们提供了toBean方法用来转换为JAVA对象, 功能更为强大,  这里借鉴采用JDK的反射机制, 作为简单的辅助工具使用,   有些数据类型需要进行转 ...

  8. 利用Java反射机制优化简单工厂设计模式

    之前项目有个需求,审批流程的时候要根据配置发送信息:发送短信.发送邮件.当时看到这个就想到要用工厂模式,为什么要用工厂模式呢?用工厂模式进行大型项目的开发,可以很好的进行项目并行开发.就是一个程序员和 ...

  9. 利用java反射机制实现List>转化为List

    BEGIN; 最近在用hibernate做项目,由于后续的业务功能比较多,然后框架原设计没有使用到一对多.一对一等特性,(艹TA妹)没办法,只能用原生sql语句获得需要的结果集.但是返回过来的是一个L ...

随机推荐

  1. Spring Boot (14) 数据源配置原理

    数据源配置源码 这里截取org.springframework.boot.autoconfigure.jdbc.DataSourceConfiguration的部分源码,主要介绍Tomcat和Hika ...

  2. PHP操作多进程

    在以往的开发项目中,要操作进程就会使用PHP自带的pcntl拓展.但是pcntl存在着许多的不足: pcntl没有提供进程间通信的功能 pcntl不支持重定向标准输入和输出 pcntl只提供了fork ...

  3. HTTPS 为什么更安全,先看这些

    HTTPS 是建立在密码学基础之上的一种安全通信协议,严格来说是基于 HTTP 协议和 SSL/TLS 的组合.理解 HTTPS 之前有必要弄清楚一些密码学的相关基础概念,比如:明文.密文.密码.密钥 ...

  4. SQL Server 检测到基于一致性的逻辑 I/O 错误 pageid 不正确(应为 1:1772,但实际为 0:0)。在文件 'D:\Program Files\Microsoft SQL Ser

    SQL Server 检测到基于一致性的逻辑 I/O 错误 pageid 不正确(应为 1:1772,但实际为 0:0).在文件 'D:\Program Files\Microsoft SQL Ser ...

  5. Eclipse Rap开发 异步刷新UI处理

    1.Display.getCurrent()获取的是当前线程的display对象,如果当前在非UI线程中那么获取到的display对象为空:      一般Display.getCurrent() 用 ...

  6. ICCV2015上的GazeTracker论文总结

    SLAM问题先慢慢编译一段时间,赶紧拾起来GazeTrack的事情...... ICCV2015的大部分paper已经可以下载,文章列表在这个位置. http://www.cvpapers.com/i ...

  7. linux环境jdk安装及配置

    linux环境jdk安装及配置 linux环境jdk安装及配置 1.下载jkd( http://www.oracle.com/technetwork/java/javase/downloads/ind ...

  8. html 图片翻转

    var Lb = false; var Ub = false; function rotate(obj) { if (obj == "L") { if (Lb == false) ...

  9. Git及Github环境搭建(Windows系统)

    一.github账号注册 1.打开网址https://github.com  注册账号: 二.本地安装Git 1.安装包下载地址:链接:https://pan.baidu.com/s/1smpnJL7 ...

  10. Lua的热更新学习笔记_01

    热更新的的实现方式 1.使用lua脚本编写游戏的UI或者其他的逻辑 2.使用C#的反射技术 3.使用C#Light AssetBundle是什么? 1.unity提供一个资源更新技术,就是通过Asse ...