利用JAVA反射机制设计通用的DAO
利用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的更多相关文章
- 利用java反射机制 读取配置文件 实现动态类载入以及动态类型转换
作者:54dabang 在spring的学习过程之中,我们能够看出通过配置文件来动态管理bean对象的优点(松耦合 能够让零散部分组成一个总体,而这些总体并不在意之间彼此的细节,从而达到了真正的物理上 ...
- 利用Java反射机制对实体类的常用操作工具类ObjectUtil
代码: ObjectUtil类: import java.lang.reflect.Field; import java.math.BigDecimal; import java.text.Simpl ...
- 利用Java反射机制将Bean转成Map
import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang ...
- 利用java反射机制编写solr通用的java客户端
一.前言 通过上一篇的讲解,我们知道了dynamicFiled字段,它是动态的,不需要显示的声明.而且一些常用的基本类型solr已经默认给我们创建好了. 例如:*_i,*_is,等. 如果我们要使用动 ...
- 不使用BeanUtils,利用Java反射机制:表单数据自动封装到JavaBean
在百度搜“java反射 将表单数据自动封装到javabean ”,第一页显示的都是一样的代码,都是利用导入第三方jar包<commons-beanutils>和<commons-lo ...
- 利用java反射机制实现读取excel表格中的数据
如果直接把excel表格中的数据导入数据库,首先应该将excel中的数据读取出来. 为了实现代码重用,所以使用了Object,而最终的结果是要获取一个list如List<User>.Lis ...
- 利用JAVA反射机制将JSON数据转换成JAVA对象
net.sf.json.JSONObject为我们提供了toBean方法用来转换为JAVA对象, 功能更为强大, 这里借鉴采用JDK的反射机制, 作为简单的辅助工具使用, 有些数据类型需要进行转 ...
- 利用Java反射机制优化简单工厂设计模式
之前项目有个需求,审批流程的时候要根据配置发送信息:发送短信.发送邮件.当时看到这个就想到要用工厂模式,为什么要用工厂模式呢?用工厂模式进行大型项目的开发,可以很好的进行项目并行开发.就是一个程序员和 ...
- 利用java反射机制实现List>转化为List
BEGIN; 最近在用hibernate做项目,由于后续的业务功能比较多,然后框架原设计没有使用到一对多.一对一等特性,(艹TA妹)没办法,只能用原生sql语句获得需要的结果集.但是返回过来的是一个L ...
随机推荐
- mybatis的二级缓存
在mybatis主配置文件里configuration标签里添加 <settings> <setting name="cacheEnabled" value=&q ...
- PHP序列化 反序列化
序列化是将变量转换为可保存或传输的字符串的过程:反序列化就是在适当的时候把这个字符串再转化成原来的变量使用.这两个过程结合起来,可以轻松地存储和传输数据,使程序更具维护性. 1. serialize和 ...
- 文件的上传(可以上传照片,word文档,等单个文件)
jsp: jsp页面: <LINK href="${basePath}plugins/uploadify/uploadify.css" type="text/css ...
- Android上UDP组播无法接收数据的问题
最近,想做一个跨平台的局域网的文件传输软件,思路是组播设备信息,TCP连接传输文件.于是进行了一次简单的UDP组播测试,发现Android对于UDP组播接收数据的支持即极为有限. 部分代码如下 pac ...
- 【PostgreSQL-9.6.3】函数(2)--字符型函数
在上一篇博文中我们交流了数值型函数,这篇我们将讨论PostgreSQL中的字符型函数. 1. reverse(string) reverse函数可以将string字符串的字母显示顺序颠倒. test= ...
- PS CC2018 命令大全
1.图像: 设置图像大小:图像->图像大小->设置宽高 约束比例: 解除约束比例: 2.设置大小像素图片不模糊: 双击当前图层->新建图层样式->输入名称->确定-> ...
- python tips:dict的key顺序
python3.6+版本中,dict的键值保持插入有序. t = list(range(10)) b = t[:] d = dict(zip(t, b)) print(list(d.items())) ...
- 整理Crontab 定时计划
一. 什么是crontab? crontab命令常见于Unix和类Unix的操作系统之中,用于设置周期性被执行的指令.该命令从标准输入设备读取指令,并将其存放于“crontab”文件中,以供之后读取和 ...
- es 存入失败错误
{, 'error': {'type': 'illegal_argument_exception', 'reason': 'Rejecting mapping update to [bd_date] ...
- HLPP算法 一种高效的网络最大流算法
#include <algorithm> #include <cstdio> #include <cctype> #include <queue> #d ...