利用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. Hadoop一主一从部署(2)

    Hadoop部署一主一从(2) 1.关闭防火墙和Linux守护进程 执行命令: iptables -F setenforce 0 2.对Hadoop集群进行初始化,在namenode(主机)上执行命令 ...

  2. [BZOJ2017][Usaco2009 Nov]硬币游戏(要复习系列)

    又是DP? 好吧,或者说是博弈论,但是我不会啊. 先搞个O(n^3)的记忆化搜索,然后瞎搞好像发现两个状态几乎一样? 竟然过了样例,然后竟然A了... #include<iostream> ...

  3. Unity中内嵌网页插件UniWebView

    一.常见Unity中内嵌网页实现方式: 1.UnityWebCore只支持windows 2.Unity-Webview支持Android,IOS 3.UniWebView支持mac os,Andro ...

  4. sql 改字段名

    sp_rename '[zErpMini].[dbo].[STK_Stock].Isextension','IsExtened'

  5. 消除svn选定(checkout)桌面上文件显示一大堆问号。

    图片: 解决方法一: 桌面右键选择TortoiseSVN——>点击Settings,如下图,选中Icon Overlays(图标覆盖),去勾选Fixed drives(本地磁盘),点击确定,按F ...

  6. 测试 Zoundry Raven

    安装很方便,看看发布的内容是否好用 但发现从博客上取下来的内容是有问题的,不能正常打开

  7. Redis 通用key操作命令

    1.在redis里面允许模糊查询key,有3个通配符:*,?,[]. *:通配任意字符 ?:通配单个字符 []:通配中括号内的某个字符 例如: 2.randomKey 随机返回所有key中的某个 3. ...

  8. BZOJ 4195: [Noi2015]程序自动分析 并查集 + 离散化 + 水题

    TM 读错题了...... 我还以为是要动态询问呢,结果是统一处理完了再询问...... 幼儿园题,不解释. Code: #include<bits/stdc++.h> #define m ...

  9. Html 页面刷新后出现闪动

    Html 页面刷新后,或跳转后,出现闪动,抖动问题 1.查看有没有用到新字体,新字体链接位置是否存在 如: @font-face { font-family: "AvantGarde-Dem ...

  10. 使用css设置border从中间向两边的颜色渐进效果

    1.效果图,设置目录的右框线渐进效果 2.代码 .rightCont>div:nth-child(1){ width: 370px; height: 100%; border-right: 2p ...