自己写的Dao框架

在使用数据库连接池的时候,每次写Dao都很烦,要写很多重复的Sql语句,还有各种针对查询好的Rs后fetch出Bean,真的让我很不能忍。

于是在经过了一下午的研究,终于针对Dao进行的封装。

废话不多说 先看Dao父类:

import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;

import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;

public class DAO {

    public String tablename = "";
    public Class<?> clazz = null;

    Logger log = Logger.getLogger(DAO.class);

    protected Connection conn;

    public DAO(Connection conn) {
        this.conn = conn;
    }

    protected static final int timeStampLen = "2011-01-18 16:18:18".length();
    protected static final String timeStampPattern = "yyyy-MM-dd HH:mm:ss";
    protected static final String datePattern = "yyyy-MM-dd";

    public synchronized long add(Object oaBean)
            throws SQLException {
        HashMap<String, String> valueMap = this.getBeanHash(oaBean);
        String sqlsString = this.getInsertSqlString(tablename, valueMap);
        Statement statement = conn.createStatement();
        long count = statement.executeUpdate(sqlsString,Statement.RETURN_GENERATED_KEYS);
        if(count > 0){
            ResultSet rs = statement.getGeneratedKeys();
            if(rs.next()){
                count = rs.getInt(1);
            }
        }
        return count;
    }

    public synchronized long update(Object oaBean) throws SQLException{
        HashMap<String, String> valueMap = this.getBeanHash(oaBean);
        String sqlString = this.getUpdateSqlString(tablename, valueMap);
        System.out.println(sqlString);
        Statement statement = conn.createStatement();
        long count = statement.executeUpdate(sqlString);
        return count;
    }

    public ArrayList<Object> getAllObj() throws SQLException{
        String sqlStr = "SELECT * FROM "+tablename+";";
        PreparedStatement ps = conn.prepareStatement(sqlStr);
        ResultSet rs = ps.executeQuery();
        return this.fetchList(rs);
    }

    public Object getById(String id) throws SQLException{
        String sqlStr = "SELECT * FROM "+tablename+" where id = ?;";
        PreparedStatement ps = conn.prepareStatement(sqlStr);
        ps.setString(1, id);
        ResultSet rs = ps.executeQuery();
        return this.fetch(rs);

    }

//    public int deleteObj(Object obj) throws SQLException{
//
//    }

    public int deleteById(String id) throws SQLException{
        String sqlStr = "DELETE FROM "+tablename+" where id = ?;";
        PreparedStatement ps = conn.prepareStatement(sqlStr);
        ps.setString(1, id);
        return ps.executeUpdate();
    }

    private Object fetch(ResultSet rs) {
        Object returnObj = null;

        try {
            if (rs.next()) {
                returnObj = clazz.newInstance();
                BeanInfo beanInfo = Introspector.getBeanInfo(returnObj.getClass());
                PropertyDescriptor[] propertyDesc = beanInfo
                        .getPropertyDescriptors();
                for (int i = 0; i < propertyDesc.length; i++) {
                    if (propertyDesc[i].getName().compareToIgnoreCase("class") == 0)
                        continue;
                    String key = propertyDesc[i].getName();
                    String value =  rs.getString(key);
                    if (value != null) {
                        try {
                            Method mr = propertyDesc[i].getWriteMethod();
                            Class<?> class1 = mr.getParameterTypes()[0];
                            mr.invoke(returnObj, this.convert(class1, value));
                        } catch (Exception e) {
                            e.printStackTrace();
                        }

                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error(e, e);
        }
        return returnObj;
    }

    private ArrayList<Object> fetchList(ResultSet rs) {
        ArrayList<Object> returnList = new ArrayList<Object>();

        try {
            if (rs.next()) {
                Object tempObj = clazz.newInstance();
                BeanInfo beanInfo = Introspector.getBeanInfo(tempObj.getClass());
                PropertyDescriptor[] propertyDesc = beanInfo
                        .getPropertyDescriptors();
                for (int i = 0; i < propertyDesc.length; i++) {
                    if (propertyDesc[i].getName().compareToIgnoreCase("class") == 0)
                        continue;
                    String key = propertyDesc[i].getName();
                    String value =  rs.getString(key);
                    if (value != null) {
                        try {
                            Method mr = propertyDesc[i].getWriteMethod();
                            Class<?> class1 = mr.getParameterTypes()[0];
                            mr.invoke(tempObj, this.convert(class1, value));
                        } catch (Exception e) {
                            e.printStackTrace();
                        }

                    }
                }
                returnList.add(tempObj);
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.error(e, e);
        }
        return returnList;
    }

    /***
     * 根据startString 和valueMap 拼接出插入的sqlStr
     * @param startString
     * @param valueMap
     * @return
     */
    public String getInsertSqlString(String tableName, HashMap<String, String> valueMap ){

        StringBuffer sqlBuffer = new StringBuffer();
        StringBuffer valueBuffer = new StringBuffer(" values (");
        sqlBuffer.append("INSERT INTO " + tableName + " (");

        //是否是第一次循环 如果不是 则先append字符 ,
        boolean isFirstValue = true;
        for (String key : valueMap.keySet()) {
            if(key.equals("id")){
                continue;
            }
            if(!isFirstValue){
                sqlBuffer.append(",");
                valueBuffer.append(",");
            }
            isFirstValue = false;
            sqlBuffer.append("`");
            sqlBuffer.append(key);
            sqlBuffer.append("`");

            valueBuffer.append("‘");
            valueBuffer.append(valueMap.get(key));
            valueBuffer.append("‘");

        }

        sqlBuffer.append(") ");
        valueBuffer.append(");");
        sqlBuffer.append(valueBuffer);

        return sqlBuffer.toString();
    }

    public String getUpdateSqlString(String tableName, HashMap<String, String> valueMap ){

        StringBuffer sqlBuffer = new StringBuffer();
        sqlBuffer.append("Update" + tableName + " set ");
        StringBuffer whereBuffer = new StringBuffer();
        whereBuffer.append("where `id` = ‘");
        //是否是第一次循环 如果不是 则先append字符 ,
        boolean isFirstValue = true;
        for (String key : valueMap.keySet()) {
            if(key.equals("id")){
                whereBuffer.append(valueMap.get(key));
                whereBuffer.append("‘;");
            }else {
                if(!isFirstValue){
                    sqlBuffer.append(",");
                }
                isFirstValue = false;
                sqlBuffer.append(" `");
                sqlBuffer.append(key);
                sqlBuffer.append("`");
                sqlBuffer.append(" = ");
                sqlBuffer.append("‘");
                sqlBuffer.append(valueMap.get(key));
                sqlBuffer.append("‘ ");
            }
        }

        sqlBuffer.append(whereBuffer);
        return sqlBuffer.toString();
    }

    //根据bean现有的属性 获取对应的key  put到map中并返回
    public HashMap<String, String> getBeanHash(Object oaBean) {
        HashMap<String, String> returnHash = new HashMap<String, String>();
        try {
            BeanInfo beanInfo = Introspector.getBeanInfo(oaBean.getClass());
            PropertyDescriptor[] propertyDesc = beanInfo
                    .getPropertyDescriptors();

            for (int i = 0; i < propertyDesc.length; i++) {
                try {
                    if (propertyDesc[i].getName().compareToIgnoreCase("class") == 0)
                        continue;
                    String key = propertyDesc[i].getName();
                    Method m = propertyDesc[i].getReadMethod();
                    if (m != null) {
                        Object[] oParam = new Object[] {};
                        String value = "" + m.invoke(oaBean, oParam);
                        // System.out.println(propertyDesc[i].getName() + ":"
                        // + value);
                        if (!StringUtils.isBlank(value) && !value.equalsIgnoreCase("null")) {
                            returnHash.put(key, value);
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }

            }

        } catch (Exception e) {
            // TODO: handle exception
        }
        return returnHash;
    }

    protected   Object convert(Class<?> clazz, String s)
            throws ParseException {

        // mysql type: varchar, char, enum, set, text, tinytext, mediumtext,
        // longtext
        if (clazz == String.class) {
            return ("".equals(s) ? null : s); // 用户在表单域中没有输入内容时将提交过来 "",
                                                // 因为没有输入,所以要转成 null.
        }
        s = s.trim();
        if ("".equals(s)) { // 前面的 String跳过以后,所有的空字符串全都转成 null, 这是合理的
            return null;
        }
        // 以上两种情况无需转换,直接返回, 注意, 本方法不接受null为 s 参数(经测试永远不可能传来null, 因为无输入传来的也是"")

        Object result = null;
        // mysql type: int, integer, tinyint(n) n > 1, smallint, mediumint
        if (clazz == Integer.class || clazz == int.class) {
            result = Integer.parseInt(s);
        }
        // mysql type: bigint
        else if (clazz == Long.class || clazz == long.class) {
            result = Long.parseLong(s);
        }
        // 经测试java.util.Data类型不会返回, java.sql.Date,
        // java.sql.Time,java.sql.Timestamp 全部直接继承自 java.util.Data, 所以
        // getDate可以返回这三类数据
        else if (clazz == java.util.Date.class) {
            if (s.length() >= timeStampLen) {
                // Timestamp format must be yyyy-mm-dd hh:mm:ss[.fffffffff]
                // result = new
                // java.util.Date(java.sql.Timestamp.valueOf(s).getTime()); //
                // error under jdk 64bit(maybe)
                result = new SimpleDateFormat(timeStampPattern).parse(s);
            } else {
                // result = new
                // java.util.Date(java.sql.Date.valueOf(s).getTime()); // error
                // under jdk 64bit
                result = new SimpleDateFormat(datePattern).parse(s);
            }
        }
        // mysql type: date, year
        else if (clazz == java.sql.Date.class) {
            if (s.length() >= timeStampLen) {
                // result = new
                // java.sql.Date(java.sql.Timestamp.valueOf(s).getTime()); //
                // error under jdk 64bit(maybe)
                result = new java.sql.Date(new SimpleDateFormat(
                        timeStampPattern).parse(s).getTime());
            } else {
                // result = new
                // java.sql.Date(java.sql.Date.valueOf(s).getTime()); // error
                // under jdk 64bit
                result = new java.sql.Date(new SimpleDateFormat(datePattern)
                        .parse(s).getTime());
            }
        }
        // mysql type: time
        else if (clazz == java.sql.Time.class) {
            result = java.sql.Time.valueOf(s);
        }
        // mysql type: timestamp, datetime
        else if (clazz == java.sql.Timestamp.class) {
            result = java.sql.Timestamp.valueOf(s);
        }
        // mysql type: real, double
        else if (clazz == Double.class) {
            result = Double.parseDouble(s);
        }
        // mysql type: float
        else if (clazz == Float.class) {
            result = Float.parseFloat(s);
        }
        // mysql type: bit, tinyint(1)
        else if (clazz == Boolean.class) {
            result = Boolean.parseBoolean(s);
        }
        // mysql type: decimal, numeric
        else if (clazz == java.math.BigDecimal.class) {
            result = new java.math.BigDecimal(s);
        }
        // mysql type: binary, varbinary, tinyblob, blob, mediumblob, longblob.
        // I have not finished the test.
        else if (clazz == byte[].class) {
            result = s.getBytes();
        }

        return result;
    }

}

这里最重要的两个属性是 tablename 和 clazz。在子类Dao中必须要设置这两个属性:tablename为Dao要操作的表的表明;clazz为对应JavaBean的反射类对象。

同时最后一个方法convert拷贝自詹波的JFinal中,感谢詹波的慷慨开源。

下面简单写了个JavaBean,注意,javabean中的各属性名必须和表中的各属性名保持一直,不能有丝毫差错。因为父类Dao中采用反射获取属性名,并把属性名当作字段名。

package testPackage;

import java.sql.Connection;

import org.sojex.finance.bean.GroupMessageBean;
import org.sojex.finance.dao.DAO;
import org.sojex.finance.dao.DBIns;

public class TestDao extends DAO {

public TestDao(Connection conn) {
super(conn);
tablename = "`tb_group_message`";
clazz = TestBean.class;
}

// public static void main(String args[]){
// Connection conn = null;
// try {
//
// conn = DBIns.getInstance().getConnection();
// TestDao tDao = new TestDao(conn);
// TestBean gm = (TestBean)tDao.getById("238");
//
// if(gm == null){
// System.out.println("return null");
// }else {
// System.out.println(gm.getMessage_content());
// }
//
// long key = tDao.add(gm);
// if(key > 0){
// gm.setId(key + "");
// gm.setMessage_content("test my strong dao");
// tDao.update(gm);
// }
//
// } catch (Exception e) {
// e.printStackTrace();
// }finally{
// DBIns.getInstance().release(conn);
// }
//
// }

}

注:本文默认使用的MySql数据库,若使用其他数据库可能会存在Sql语句错误的现象。

自己写的Dao框架,布布扣,bubuko.com

时间: 2024-10-08 15:41:00

自己写的Dao框架的相关文章

写个PHP框架吧

肯定会问:现在的PHP框架那么多了,为什么还要写一个PHP框架呢? 1.时代:PHP7来了,现在的所有框架都是基于PHP5.x的.到时候PHP7正式推广出来,现有的框架都不能发挥PHP7的最大性能优势,比如强类型和JIT.到时候很多框架就会有一个版本分裂的问题出现了,很多框架需要同时维护两套代码,部分框架可能会力不从心而挂掉了.所以现在要写一个PHP框架就要以PHP7为最低版本要求,虽然现在PHP7还是测试版本,框架开发难度有点大. 2.时长:一个框架开发要多少呢?个人观点:从开发到测试.到实验

自己手写WEB程序框架并运行

1.新建文件夹,起名MyWeb 2.文件夹下,新建两个文件夹 WEB-INF, META-INF,,还可以新建一些jsp,html文件 ,如 index.html 3在WEB-INF中必须存在一个文件WEB.xml, 还包含两个文件夹 lib, classes 4 在WEB.xml中写入最简单的<web-app> ....  </web-app>,,,,,编辑一下index.html 下面是要运行了 1,cmd 2,切换到MyWeb的文件夹,jar 命令查看一下各个参数的含义 3,

自己动手写Android数据库框架

前言 相信不少开发人员跟我一样,每次都非常烦恼自己写数据库,并且那些数据库语句也经常记不住.当然网上也有非常多非常好的数据库框架,你能够直接拿来用,可是 非常多时候我们的项目.特别是一个小型的Andrond应用原本用到的数据库结构比較简单,不是必需去用那些有点臃肿的框架.当然,即使你用那些框架.当你遇到问题时,你是否也得去改动它?你要改动别人的框架必须的读懂他人的设计代码.所以无论从那个角度出发,你都得掌握简单的数据库操作.那么这篇博客就从简单的数据库操作来学习Android数据库相关知识点.然

自己动手写PHP MVC框架

来自:yuansir-web.com / [email protected] 代码下载: https://github.com/yuansir/tiny-php-framework PHP的框架众多,对于哪个框架最好,哪个框架最烂,是否应该用框架,对于这些争论在论坛里面都有人争论,这里不做评价, 个人觉得根据自己需求,选中最佳最适合自己MVC框架,并在开发中能够体现出敏捷开发的效果就OK了,作为一个PHPer要提高自己的对PHP和MVC的框架的认识,所以自己写一个MVC框架是很有必要的, 即使不

教你写Android ImageLoader框架之初始配置与请求调度

## 前言 在教你写Android ImageLoader框架之基本架构中我们对SimpleImageLoader框架进行了基本的介绍,今天我们就从源码的角度来剖析ImageLoader的设计与实现.   在我们使用ImageLoader前都会通过一个配置类来设置一些基本的东西,比如加载中的图片.加载失败的图片.缓存策略等等,SimpleImageLoader的设计也是如此.配置类这个比较简单,我们直接看源码吧. ImageLoaderConfig配置 /** * ImageLoader配置类,

自己写的struts1框架

前言 正文 自定义Struts1 commons-digester.jar解析XML 实现XML标签到对象的转换 1.根据目标XML的结构定义解析规则文件 参照rule.xml 2.创建集合对象接收封装解析的XML ModelConfig config = new ModelConfig(); Digester digester = DigesterLoader. createDigester(ActionServlet.class.getClassLoader().getResource("c

【EatBook】-NO.3.EatBook.3.JavaArchitecture.2.001-《架构探险:从零开始写Java Web框架》-

1.0.0 Summary Tittle:[EatBook]-NO.3.EatBook.3.JavaArchitecture.2.001-<架构探险:从零开始写Java Web框架>- Style:JavaArchitecture Series:Architecture Publishing House:电子工业 Author: 黄勇 Page Number:349 Since:2017-04-06 End:ing... Total Hours:ing... Degree Of Diffcul

教你写Android ImageLoader框架之图片缓存 (完结篇)

在教你写Android ImageLoader框架系列博文中,我们从基本架构到具体实现已经更新了大部分的内容.今天,我们来讲最后一个关键点,即图片的缓存.为了用户体验,通常情况下我们都会将已经下载的图片缓存起来,一般来说内存和本地都会有图片缓存.那既然是框架,必然需要有很好的定制性,这让我们又自然而然的想到了抽象.下面我们就一起来看看缓存的实现吧. 缓存接口 在教你写Android ImageLoader框架之图片加载与加载策略我们聊到了Loader,然后阐述了AbsLoader的基本逻辑,其中

教你写Android ImageLoader框架之图片加载与加载策略

在教你写Android ImageLoader框架之初始配置与请求调度中,我们已经讲述了ImageLoader的请求配置与调度相关的设计与实现.今天我们就来深入了解图片的具体加载过程以及加载的策略(包括按顺序加载和逆序加载) ,在这其中我会分享我的一些设计决策,也欢迎大家给我提建议. 图片的加载 Loader与LoaderManager的实现 在上一篇文章教你写Android ImageLoader框架之初始配置与请求调度中,我们聊到了Loader与LoaderManager. ImageLoa