利用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 ...
随机推荐
- mysql 年龄计算(根据生日字段)
mysql 年龄计算(根据生日字段) year( from_days( datediff( now( ), birthdate))) //获取年龄 now() 当前时间,精确到秒 datediff(b ...
- python利用有道翻译实现“语言翻译器”的功能
import urllib.request import urllib.parse import json while True: content = input('请输入需要翻译的内容(退出输入Q) ...
- [转载]Android平台第三方应用分享到微信开发
一.申请APPID 微信公共平台和微博分享一样,也需要申请一个ID,来作为调起微信.分享到微信的唯一标识. 申请微信APPID可以到微信平台http://open.weixin.qq.com/app/ ...
- KindEditor文本编辑框的实现
效果图: kindeditor 是一个插件 下载地址: https://files-cdn.cnblogs.com/files/lxnlxn/kindeditor.zip 解压后将其放在项目的js文件 ...
- JQuery 数据加载中禁止操作页面
比较常见的做法,但对我而言是第一次做,记录一下. 为了把找来的loading.gif 的背景色设置为透明,还特意装了quicktime. 有学到一些额外的东西. 先将div及img定义好 <bo ...
- 复习HTML+CSS(9)
n CSS简介 CSS:Cascading Style Sheets 层叠样式表 CSS的主要目的:是给HTML标记添加各种各样的表现(格式.样式).比如:文字样式.背景.文本样式.链接样式. 提示 ...
- Activity生命周期(待整理)
1. 定义 有一些方法共同定义生命周期,如下图示:(图片来自于官网文档) 2. onStart()——在Activity即将对用户可见之前调用 (1)Activity启动动画.二维动画在onStart ...
- python--3、函数
定义: 定义函数时,也相当于定义变量.会把函数体内的代码存入开辟的内存空间中.使用函数时,通过func() 声明是函数,其对应的值为代码.函数是指将一组语句的集合通过一个名字(函数名)封装起来,要想执 ...
- MFC 添加文件路径 遍历文件
.添加MFC选择文件路径,使用MessageBox显示信息. void CMyCalLawsDlg::OnBnClickedAddfolder() { wchar_t* p; wchar_t szPa ...
- mysql手册操作
1.show table status 显示表状态 2.VERSION() 版本:CURRENT_DATE 当前日期: NOW() 当前时间:USER 当前用户 3.GRANT A ...