DAO层通用实现,结果集ResultSet转化为javaBean的反射实现,自动生成javaBean

在学习持久层框架之前,反复编写dao层代码编烦了,就自己实现了一个能方便地根据数据库表创建javaBean,并实现其增删改查,结果集转化为List集合,sql编译语句里参数赋值的自动化的“框架”。本文所使用的数据库是mysql自带的simple data里的sakila数据库

先看一下使用效果:

  1. 先编写并运行测试类创建javaBean:
    Country,City,Address,Customer
package com.iss.db.dao.toolkit;

import java.sql.ResultSet;
import java.sql.SQLException;

import org.junit.Test;

import com.iss.db.dao.connectdb.OffLineConn;
import com.iss.db.dao.dbinfo.DBConfig;

/**
 * 创建javaBean源文件(下面的代码还可以进一步封装)
 */
public class CreateJavaBeanSource {
    @Test
public void test01() throws Exception{
        ResultSet rs = TableTool.execQuery(new OffLineConn(new DBConfig()).getConn().prepareStatement("select * from country where 1>2"));
        String descTable = DBTool.descTable(rs);
        System.out.println(descTable);
        DBTool.createClazzToSource(rs, "src/main/java", "com.iss.db.bean.Country", "country");
        rs = TableTool.execQuery(new OffLineConn(new DBConfig()).getConn().prepareStatement("select * from city where 1>2"));

      descTable = DBTool.descTable(rs);
    System.out.println(descTable);
    DBTool.createClazzToSource(rs, "src/main/java", "com.iss.db.bean.City", "city");

      rs = TableTool.execQuery(new OffLineConn(new DBConfig()).getConn().prepareStatement("select * from address where 1>2"));
      descTable = DBTool.descTable(rs);
    System.out.println(descTable);
    DBTool.createClazzToSource(rs, "src/main/java", "com.iss.db.bean.Address", "address");

      rs = TableTool.execQuery(new OffLineConn(new DBConfig()).getConn().prepareStatement("select * from customer where 1>2"));
      descTable = DBTool.descTable(rs);
    System.out.println(descTable);
    DBTool.createClazzToSource(rs, "src/main/java", "com.iss.db.bean.Customer", "customer");
}
}

上述代码中DBTool.createClazzToSource(包含所有列的结果集,工程src名,javaBean全类名,数据库表名),还可以进一步封装使之更易用

  1. 编写上述4个javaBean对应的DAO类:
    1. CounryDao.java :

package com.iss.db.dao.tablemanager;
import com.iss.db.bean.Country;
import com.iss.db.dao.tableinfo.TableDic;
public class CountryDao extends TableManager{
    public CountryDao(){
        super(Country.class,new TableDic("country_id", "country", "country"));
    }
}

2.CityDao.java

package com.iss.db.dao.tablemanager;
import com.iss.db.bean.City;
import com.iss.db.dao.tableinfo.TableDic;
public class CityDao extends TableManager {
    public CityDao() {
        super(City.class, new TableDic("city_id", "city", "city", "country_id"));
    }
}

3.AddressDao.java

public class AddressDao extends TableManager{
    public AddressDao(){
        super(Address.class, new TableDic("address_id", "address", "address","address2","district","city_id","postal_code","phone"));
    }
}

4.CustomerDao.java

public class CustomerDao extends TableManager{
    public CustomerDao(){
        super(Customer.class,new TableDic("customer_id", "customer","store_id","first_name","last_name","email","address_id","active"));
    }
}
**上述代码其实只是在给TableManager传入参数,参数提供javaBean的class信息,以及数据库表的主要信息new TableDic(“主键”,”表明”,”更新操作的字段1”,”更新操作的字段2”,……)**

实现过程:

**1. 核心问题:遍历结果集创建java对象很麻烦,各种重复操作,如何省去?**

1.学过反射,想到可以通过反射调用对象的set方法为之赋值。
2.如过自动赋值,那么对于ResultSet的每一行,如果遍历它的各个字段,查阅发现ResultSet.getMetaData()方法可以获取各个列的信息(名称,类型)。
3.调用javaBean对象的set方法需要考虑传入参数类型, 那么没问题, setmethod.getGenericParameterTypes()[0].getTypeName()可以办到。
4. SQL数据库类型明显要比java里的类型多,需要做个类型对应。
5. 如何自动生成java源文件,那不就是io文件流嘛,拼接好javaBean字符串写入文件即可。

**代码组织结构如下:** ![代码组织结构](https://img-blog.csdn.net/20170803161700485?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvc2luYXRfMzQ4MjAyOTI=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
对该功能实现分多个层是为了易于修改和扩展,上图中HeadPicDao.java,MyTool.java与本文介绍的东西无关。
1)包DAO层细分了几个包:
    1.  dao.connectdb: 获取数据库连接的抽象,可以是永久连接,可以使连接池,OffLineConn是对GetDBConn的一个开发时实现,实际中可以使用数据库连接池,远程连接等来实现。
    2.  dao.tableinfo: 数据库表关键信息的抽象,关键信息包括(主键,表名,更新操作的字段[]),是创建某个表DAO层唯一需要的输入,TableDic是对TableInfo的实现,也可以用从配置文件获取表信息的方法实现TableInfo。
    3.  dao.dbinfo: 对数据库信息的抽象,关键信息包括(驱动名,数据库url,用户名,密码),这里就把数据库的信息写死在了DBconfig.java了,如果想换成从配置文件获取,只需要写一个从配置文件获取数据库信息的类实现DBInfo接口即可(策略模式)。
    4.  dao.toolkit:工具类,获得连接后可以使用的工具DBTool,制定了表之后可用的工具TableTool,数据格式转化工具MyTool(实现json, javaBean, ResultSet 等值间的转化)
    5.  dao.tablemanager: 每个表Dao的模板类,以及每个数据表对应的继承类,在继承里指定对应的javaBean和tableinfo信息即可
2) 特点:
    1.  根据数据库表自动创建javaBean文件。
    2.  ResultSet到javaBean的变化依据数据库字段名在javaBean中找对应的set方法,判断set方法的输入参数类型和数据库表类型是否一致(类型匹配),匹配则调用这个set方法进行赋值。
    3.  更新类操作根据初始化时指定的数据库表信息里的主键信息、更新字段信息进行,程序根据这些字段名自动从javaBean中提取信息进行更新或者插入操作。
    4.  查询自动包装成javaBean,根据的是数据库表的属性。
    5.  综上,javaBean可以任意添加成员变量,其它方法,只需要满足javaBean里的get方法是数据库属性的超集、javaBean里的set方法是tableinfo指定更新属性的超集即可。

核心代码如下 ( 其余代码会在后面贴上 )

**1. 结果集转化为javaBean集合(MyTool.java里面的部分代码)**

数据类型映射表:

    // 类型对照表,试着用反射实现javaBean装箱操作
        public final static Map<String, String> TYPE_DIC = new HashMap<String, String>() {
    {
        put("VARCHAR", "java.lang.String");
        put("VARCHAR2", "java.lang.String");
        put("CHAR", "java.lang.String");
        put("TEXT", "java.lang.String");
        put("MEDIUMTEXT", "java.lang.String");
        put("LONGTEXT", "java.lang.String");
        put("INT", "java.lang.Integer,int");
        put("SMALLINT", "java.lang.Short,short");
        put("TINYINT", "java.lang.Short,short,java.lang.Boolean");
        put("SMALLINT UNSIGNED","java.lang.Short,short");
        put("FLOAT", "java.lang.Float,float");
        put("DECIMAL", "java.lang.Float,folat");
        put("DOUBLE", "java.lang.Double,double");
        put("YEAR", "java.sql.Date,java.util.Date");
        put("DATE", "java.sql.Date,java.util.Date");
        put("TIME", "java.sql.Date,java.util.Date");
        put("DATETIME", "java.sql.Timestamp,java.util.Date");
        put("TIMESTAMP", "java.sql.Timestamp,java.util.Date");
        put("ID", "java.lang.Long,long");
        put("BIT", "java.lang.Boolean,boolean");
        put("BINARY", "java.lang.Boolean,boolean");
        put("BOOLEAN", "java.lang.Boolean,boolean");
        put("BIGINT", "java.math.BigInteger,long");
        put("INTEGER", "java.lang.Integer,int");// 或者long ?
        put("BLOB", "java.lang.String");// 或者 java.lang.byte[] ?

        put("GEOMETRY","java.lang.String");
        put("TINYINT UNSIGNED","java.lang.Integer,int,java.lang.Byte,buty");
    }
};
        // 可以通过 valueOf(String arg)装箱的基本数据类型
        public final static Map<String, String> BASIC_TYPE = new HashMap<String, String>() {
            {
                put("int", "java.lang.Integer");
                put("long", "java.lang.Long");
                put("float", "java.lang.Float");
                put("double", "java.lang.Double");
                // put("char","java.lang.Character");//他没有以字符串为参数的构造方法,但是数据库没有与之对应的类型,这里不对其进行单独处理
                put("byte", "java.lang.Byte");
                put("boolean", "java.lang.Boolean");
                put("short", "java.lang.Short");
            }
        };

转换函数

    /**
     * ResultSet --> JavaBean
     * 传入javaBean的class,从结果集取出数据创建对象并返回
     * @param rs
     * @param clazz
     * @return
     */
    public static <T> T resultSetToJavaBean(ResultSet rs, Class<T> clazz) {
        T entity = null;
        // TODO: java.sql.ResultSet转化为JavaBean
        // 获取所有set方法以及set的属性名,并存入Map集合
        Method[] methods = clazz.getMethods();
        Map<String, Method> setMethods = new HashMap<String, Method>();
        for (Method method : methods) {
            // Pattern.compile("set.*").matcher(method.getName()).matches()
            if (method.getName().substring(0, 3).equals("set")) {
                setMethods.put(method.getName().substring(3,4).toLowerCase()+method.getName().substring(4), method);// 获取全部set方法的属性名以及方法本身
            }
        }
        // 从result中获取值创建JavaBean对象
        try {
            ResultSetMetaData metaData = rs.getMetaData();
            int cc = metaData.getColumnCount();
            T ob = clazz.newInstance();
            if (!rs.next()) {
                return null;
            }
            for (int i = 1; i <= cc; i++) {
                String coluname = metaData.getColumnName(i);// 列名,作为数据表列和JavaBean属性唯一匹配标识
                coluname = nameInDb2nameInJava(coluname);
                String coltype = metaData.getColumnTypeName(i);// 表的属性类型
                Method setmethod = setMethods.get(coluname);// set方法
                String argType = setmethod.getGenericParameterTypes()[0].getTypeName();// set方法的传入参数
                if (!setMethods.containsKey(coluname)) {// 如果在javaBean中找不到列属性
                    throw new Exception("属性名异常:javaBean中不包含" + coluname + "属性");
                } else if (TYPE_DIC.get(coltype) == null) {// 如果属性类型未列入
                    System.err.println("警告:" + coluname + "的类型为" + coltype + "是不常见类型,转化为String类型");
                } else if (!TYPE_DIC.get(coltype).contains(argType)) {// 如果同一属性的类型无法匹配
                    throw new Exception("类型不匹配:属性" + coluname + "的数据库类型为" + coltype + "而JavaBean中类型是" + argType);
                }
                if (BASIC_TYPE.containsKey(argType)) {
                    argType = BASIC_TYPE.get(argType);
                } // 如果是基本数据类型,则转化位java.lang下类型
                Object argOb = null;// set方法的传入值
                if (argType.contains("Date") || argType.contains("Time")) {
                    // 日期类型需要转化,而其他常见类型可以用传入字符串的构造方法创建对象
                    Timestamp data = rs.getTimestamp(nameInJava2nameInDb(coluname));
                    if (argType.contains("util")) {
                        // 如果是java.util.Date
                        argOb = new java.util.Date(data.getTime());
                    } else {
                        Class argClazz = Class.forName(argType);
                        argOb = argClazz.getConstructor(String.class).newInstance(data.getTime());
                    }
                } else if (BASIC_TYPE.containsValue(argType)) {
                    // 如果是基本类型,用构造方法装箱创建对象
                    Class argClazz = Class.forName(argType);
                    argOb = argClazz.getConstructor(String.class).newInstance(rs.getString(nameInJava2nameInDb(coluname)));
                } else {
                    // 其余的按照字符类型来处理
                    argOb = rs.getString(nameInJava2nameInDb(coluname));
                }
                // 调用JavaBean的set方法设置值
                setMethods.get(coluname).invoke(ob, argOb);
            }
            entity = ob;
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return entity;
    }

    /**
     * ResultSet --> JavaBean 符合开发习惯的函数封装
     * 
     * @param rs
     * @param clazz
     * @return
     */
    public static <T> T handler(ResultSet rs, Class<T> clazz) {
        return resultSetToJavaBean(rs, clazz);
    }

    /**
     * ResultSet -->  List<JavaBean>
     * 
     * @param rs
     * @param clazz
     * @return
     */
    public static <T> List<T> handlerList(ResultSet rs, Class<T> clazz) {
        List<T> list = new ArrayList<T>();
        T entity = null;
        do{
            entity = handler(rs, clazz);
            list.add(entity);
        }while(entity!=null);
        if(list.size()>0)
        list.remove(list.size()-1);
        return list;
    }
**2.自动生成javaBean源文件(DBTool.java里的部分代码)**
/**
 * 根据数据库结果集创建类的字符,如果输出到文件io流则是javaBean源文件
 * @param rs
 * @return
 */
public static String createClazz(ResultSet rs, String clazzName) throws Exception {
    StringBuffer sb = new StringBuffer();
    ResultSetMetaData metaData = rs.getMetaData();
    int cc = metaData.getColumnCount();
    Map<String, String> desc = new HashMap<String, String>();
    for (int i = 1; i <= cc; i++) {
        String coluname = metaData.getColumnName(i);// 列名,作为数据表列和JavaBean属性唯一匹配标识

        // 下划线命名法转化为驼峰命名法
        coluname = MyTool.nameInDb2nameInJava(coluname);
        String coltype = metaData.getColumnTypeName(i);// 表的属性类型
        desc.put(coluname, TYPE_DIC.get(coltype));
    }
    // 把基本类型的属性转为基本类型
    // 需要导的包
    List<String> importPackage = new ArrayList<String>();
    for (String filed : desc.keySet()) {
        // System.out.println(filed+": "+desc.get(filed));
        boolean flag = true;// 标记是否基本类型
        for (String bst : BASIC_TYPE.keySet()) {
            if (desc.get(filed).contains(bst)) {
                desc.replace(filed, bst);
                flag = false;
            }
        }
        if (flag) {
            if (desc.get(filed).contains(",")) {
                importPackage.add(desc.get(filed).substring(desc.get(filed).indexOf(',') + 1, desc.get(filed).length()));
            } else {
                importPackage.add(desc.get(filed));
            }
            desc.replace(filed,
                    desc.get(filed).substring(desc.get(filed).lastIndexOf('.') + 1, desc.get(filed).length()));
        }
    }
    // unique pakage-name
    List<String> uniquepackage = new ArrayList<String>();
    for (int i = 0; i < importPackage.size(); i++) {
        boolean flag = true;
        for(int j=0;j<uniquepackage.size();j++){
            if(uniquepackage.get(j).equals(importPackage.get(i))){
                flag  = false;
                break;
            }
        }
        if(flag){
            uniquepackage.add(importPackage.get(i));
        }
    }
    uniquepackage.remove("java.lang.String");
    importPackage = uniquepackage;
    // package name
    if (clazzName.contains(".")) {
        sb.append("package " + clazzName.substring(0, clazzName.lastIndexOf(".")) + ";\r\n\r\n");
        clazzName = clazzName.substring(clazzName.lastIndexOf(".") + 1, clazzName.length());
    }
    // import package
    for (String string : importPackage) {
        sb.append("import  "+string + ";\r\n");
    }
    // 类名
    sb.append("\r\npublic class " + clazzName + " {\r\n");
    // 定义属性
    for (String filed : desc.keySet()) {
        sb.append("\tprivate " + desc.get(filed) + "  " + filed + ";\r\n");
    }
    // 定义get/set方法
    for (String filed : desc.keySet()) {
        sb.append("\tpublic  void  set" + filed.substring(0, 1).toUpperCase() + filed.substring(1) + "( "
                + desc.get(filed) + " " + filed + " ) {\r\n");
        sb.append("\t\tthis." + filed + " = " + filed + ";\r\n\t}\r\n");
        sb.append("\tpublic  " + desc.get(filed) + "  get" + filed.substring(0, 1).toUpperCase()
                + filed.substring(1) + "() {\r\n");
        sb.append("\t\treturn this." + filed + ";\r\n\t}\r\n");
    }
    // 定义toString方法
    sb.append("\tpublic String toString() {\r\n\t\treturn  \"" + clazzName + " [");
    for (String filed : desc.keySet()) {
        sb.append(filed + "=\" + " + filed + " + \",");
    }
    sb.delete(sb.length() - 1, sb.length());
    sb.append("]\";\r\n\t}\r\n");
    sb.append("}\r\n\r\n");
    return sb.toString();
}

/**
 * 给出src文件名,给出javaBean的全类名,给出数据库表的名字自动创建数据表对应的javaBean的java源文件
 * 如:
 * new BeanTool().createClazzToSource("src/main/java","com.iss.db.bean.KKUser","user");
 * 
 * @param srcName
 * @param clazzFullName
 * @param tableName
 */
public static void createClazzToSource(ResultSet rs,String srcName,String clazzFullName,String tableName){
    try {
        if(!srcName.endsWith("/")){
            srcName+="/";
        }
        String path = "";
        String fileName = "";
        if(clazzFullName.contains(".")){
            fileName = clazzFullName.substring(clazzFullName.lastIndexOf(".")+1,clazzFullName.length())+".java";
            path = srcName  +clazzFullName.substring(0,clazzFullName.lastIndexOf(".")).replace('.', '/')+"/";
        }else{
            fileName = clazzFullName+".java";
            path = srcName;
        }
        fileName = fileName.substring(0, 1).toUpperCase()+fileName.substring(1);
        System.out.println(path);
        System.out.println(fileName);
        File ff = new File(path+fileName);
        if(!ff.exists()){ff.createNewFile();}
        BufferedWriter bf = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(ff)));
        String a = createClazz(rs, clazzFullName);
        bf.write(a);bf.flush();bf.close();
    } catch (FileNotFoundException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    } catch (Exception e) {
        e.printStackTrace();
    }
}
**3.前面函数使用的属性名转化函数(MyTool.java里的部分代码)**

数据库采用下划线命名规则,java里采用驼峰式命名规则,需要转化

/**
 * 数据库里下划线命名规则转化为java里面驼峰式命名
 * @param dbname
 * @return
 */
public static String nameInDb2nameInJava(String nameInDb) {
    String coluname = nameInDb.toLowerCase();
    if (Pattern.compile("^\\S+_+\\S+$").matcher(coluname).find()) {
        char[] ca = coluname.toCharArray();
        for (int j = 1; j < ca.length - 1; j++) {
            if (ca[j]=='_') {
                ca[j]='\0';
                ca[j + 1] = Character.toUpperCase(ca[j + 1]);
            }
        }
        coluname = new String(ca);
    }
    return coluname.replaceAll("\0", "");
}

/**
 * 驼峰命名规则转化为下划线命规则
 * @param nameInJava
 * @return
 */
public static String nameInJava2nameInDb(String nameInJava) {
    char[] ca = nameInJava.toCharArray();
    StringBuffer sb = new StringBuffer();
    sb.append(ca[0]);
    for(int j=1;j<ca.length;j++) {
        Character cha = ca[j];
        if(Character.isUpperCase(cha)) {
            sb.append('_');
        }
        sb.append(cha);
    }
    return sb.toString().toLowerCase();
}
**4.初步封装数据库查询和更新以节省设置参数的重复**
package com.iss.db.dao.toolkit;

import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;

public class TableTool extends MyTool{

    /**
     * <pre>
     * 设置pstmt里面的第i个问号的值为传入的oo对象
     * 根据oo对象的数据类型设置
     * @param pstmt
     * @param i sql语句中的第i个问好
     * @param oo
     */
    private static void pstmtSet(PreparedStatement pstmt,int i,Object oo){
        try {
            String clazz = oo.getClass().getName();
            System.out.println("TableTool.pstmtSet()  : "+clazz);
            switch (clazz){
            case "int":
            case "java.lang.Integer":
                pstmt.setInt(i, (Integer)oo);
                break;
            case "float":
            case "java.lang.Float":
                pstmt.setFloat(i, (Float)oo);
                break;
            case "double":
            case "java.lang.Double":
                pstmt.setDouble(i, (Double)oo);
                break;
            case "long":
            case "java.lang.Long":
                pstmt.setLong(i, (Long)oo);
                break;
            case "java.util.Date":
                pstmt.setDate(i,(new java.sql.Date(((java.util.Date)oo).getTime())));
                break;
            case "boolean":
            case "java.lang.Boolean":
                pstmt.setBoolean(i, (boolean)oo);
                break;
            case "short":
            case "java.lang.Short":
                pstmt.setShort(i, (short)oo);
                break;
            case "java.lang.String":
                pstmt.setString(i, (String)oo);
                break;
            default:
                pstmt.setString(i, oo.toString());
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    /**
     * 执行有参数的更新语句
     * @param sql
     * @param o是若干个(0到多个)sql语句里面对应的参数
     * @return
     */
    public static  int execUpdate(PreparedStatement pstm,Object... o){
        int re=0;
        try {
            for(int i=1;i<=o.length;i++){
                pstmtSet(pstm,i,o[i-1]);
            }
            re = pstm.executeUpdate();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return re;
    }

    /**
     * 执行有参数的查询语句
     * @param sql
     * @param o是若干个(0到多个)sql语句里面对应的参数
     * @return
     */
    public static ResultSet execQuery(PreparedStatement pstm,Object... o)  {
        ResultSet rs = null;
        try {
            for(int i=1;o!=null&&i<=o.length;i++){
                pstmtSet(pstm,i,o[i-1]);
            }
            rs = pstm.executeQuery();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return rs;
    }

    /**
     * 执行无参数的更新语句
     * @param sql
     * @return
     */
    public static int execUpdate(Statement stmt ,String sql){
        int re=0;
        try {
            re = stmt.executeUpdate(sql);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return re;
    }

    /**
     * 执行无参查询语句
     * @param sql
     * @return
     */
    public  static ResultSet execQuery(Statement stmt,String sql){
        ResultSet rs = null;
        try {
            rs = stmt.executeQuery(sql);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return rs;
    }
}
  1. 最上层封装,实现通用的函数:
  1. 根据主键查询,返回javaBean(输入参数是主键赋了值的javaBean)
  2. 传入javaBean更新数据库里主键对应的数据项
  3. 传入javaBean删除数据库里主键与之对应的数据项
  4. 传入javaBean插入到数据库(对于mysql数据库可以返回新插入的那条数据)
  5. 运行含有where子句的查询删除操作
  6. 运行普通的查询更新有参或者无参sql语句返回结果集

TableManager .java

package com.iss.db.dao.tablemanager;

import java.lang.reflect.InvocationTargetException;
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.util.List;
import java.util.Map;

import com.iss.db.dao.connectdb.GetDBConn;
import com.iss.db.dao.connectdb.OffLineConn;
import com.iss.db.dao.dbinfo.DBConfig;
import com.iss.db.dao.tableinfo.TableInfo;
import com.iss.db.dao.toolkit.MyTool;
import com.iss.db.dao.toolkit.TableTool;
/**
 * 该类定义了所有数据表的增删查该操作,除了byWhere的查询和删除操作,其余均要求传入javaBean的对象
 * @author tim
 *
 */
public class TableManager {
    private   String UPDATE;
    private   String INSERT;
    private   String SLELECT_ALL;
    private   Class CLAZZ;
    protected TableInfo tableinfo = null;
    private GetDBConn getDBConn = null;
    protected PreparedStatement pstmt = null;
    protected Statement stmt = null;
    protected Connection conn = null;
    protected ResultSet rs = null;

    private void init() {
        String que = "";
        UPDATE = "UPDATE " + tableinfo.tableName() + " SET ";
        INSERT = "INSERT INTO " + tableinfo.tableName() + " (";
        for (String fil : tableinfo.updateArray()) {
            INSERT += fil + " ,";
            UPDATE += fil + "= ? ,";
            que += "?,";
        }
        UPDATE = UPDATE.substring(0, UPDATE.length() - 1);
        UPDATE += " WHERE " + tableinfo.pkName() + " = ?";
        INSERT = INSERT.substring(0, INSERT.length() - 1);
        que = que.substring(0, que.length() - 1);
        INSERT += ") VALUES(" + que + ")";
        SLELECT_ALL = "SELECT * FROM " + tableinfo.tableName() + " ";
        getDBConn = new OffLineConn(new DBConfig());// 这里制定数据库连接
    }

    public TableManager() {
        super();
    }

    public void setClazz(Class clazz) {
        this.CLAZZ = clazz;
    }

    public TableManager(Class clazz, TableInfo tableinfo) {
        super();
        this.CLAZZ = clazz;
        this.tableinfo = tableinfo;
        init();
    }

    protected Connection getConn() {
        conn = getDBConn.getConn();
        return conn;
    }

    protected PreparedStatement getPstmt() {
        return pstmt;
    }

    /**
     * 传入javaBean以更新数据库
     * 
     * @param o
     * @return
     */
    public boolean update(Object o) {
        release();
        getConn();
        Map<String, Method> methods = MyTool.getMethods(CLAZZ);
        Object[] args = new Object[tableinfo.updateArray().length + 1];
        try {
            for (int i = 0; i < args.length - 1; i++) {
                args[i] = methods.get(tableinfo.updateArray()[i]).invoke(o);
            }
            args[args.length - 1] = methods.get(tableinfo.pkName()).invoke(o);
            pstmt = conn.prepareStatement(UPDATE);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return 1 == TableTool.execUpdate(pstmt, args);
    }

    /**
     * 传入javaBean以完成数据库插入
     * 
     * @param o
     * @return
     */
    public boolean insert(Object o) {
        release();
        getConn();
        Map<String, Method> methods = MyTool.getMethods(CLAZZ);

        Object[] args = new Object[tableinfo.updateArray().length];
        try {
            for (int i = 0; i < args.length; i++) {
                args[i] = methods.get(tableinfo.updateArray()[i]).invoke(o);
            }
            pstmt = conn.prepareStatement(INSERT);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return 1 == TableTool.execUpdate(pstmt, args);
    }

    /**
     * 只对mysql数据库中主键自增的表有效
     * @param o
     * @return
     */
    public Object insertAndRetrunNew(Object o){
        release();
        getConn();
        Map<String, Method> methods = MyTool.getMethods(CLAZZ);

        Object[] args = new Object[tableinfo.updateArray().length];
        try {
            for (int i = 0; i < args.length; i++) {
                args[i] = methods.get(tableinfo.updateArray()[i]).invoke(o);
            }
            pstmt = conn.prepareStatement(INSERT,PreparedStatement.RETURN_GENERATED_KEYS);
            int pk = TableTool.execUpdate(pstmt, args);
            Map<String, Method> setMethods = MyTool.setMethods(CLAZZ);
            setMethods.get(tableinfo.pkName()).invoke(o, pk);
            return selectById(o);
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return null;
    }

/**
 * 查询并返回一个列表
 * @param where
 * @param args
 * @return
 */
    public List selectListByWhere(String where, Object... args) {
        release();
        getConn();
        try {
            pstmt = conn.prepareStatement(SLELECT_ALL + where);
            rs = TableTool.execQuery(pstmt, args);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return MyTool.handlerList(rs, CLAZZ);
    }

    /**
     * 输入一个javaBean,根据其主键删除
     * @param o
     * @return
     */
    public boolean delateByPk(Object o) {
        release();getConn();
        Map<String, Method> methods = MyTool.getMethods(CLAZZ);
        try {
            pstmt = conn
                    .prepareStatement("DELETE FROM " + tableinfo.tableName() + " WHERE " + tableinfo.pkName() + " = ?");
            Object pk = methods.get(tableinfo.pkName()).invoke(o);
            return 1 == TableTool.execUpdate(pstmt, pk);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 输入一个javaBean根据其主键查询
     * @param o
     * @return
     */
    public Object selectById(Object o){
        release();getConn();
        Map<String, Method> methods = MyTool.getMethods(CLAZZ);
        Object pk="";
        try {
            pk = methods.get(tableinfo.pkName()).invoke(o);
        } catch (Exception e) {
            e.printStackTrace();
        } 
        return selectByWhere(" WHERE " + tableinfo.pkName() + " = ?",pk);
    }
/**
 * 传入where字句删除数据
 * @param where
 * @param args
 * @return
 */
    public boolean deleteByWhere(String where, Object... args) {
        try {
            pstmt = conn.prepareStatement("DELETE FROM " + tableinfo.tableName() + " " + where);
            return 1 == TableTool.execUpdate(pstmt, args);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return false;
    }
/**
 * 传入where子句,根据where子句查询
 * @param where
 * @param args
 * @return
 */
    public Object selectByWhere(String where, Object... args) {
        release();
        getConn();
        try {
            pstmt = conn.prepareStatement(SLELECT_ALL + where);
            rs = TableTool.execQuery(pstmt, args);
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return MyTool.handler(rs, CLAZZ);
    }

    /**
     * 释放数据库连接资源
     */
    public void release() {
        try {
            if (rs != null) {
                rs.close();
                rs = null;
            }
            if (pstmt != null) {
                pstmt.close();
                pstmt = null;
            }
            if (stmt != null) {
                stmt.close();
                stmt = null;
            }
            if (conn != null) {
                conn.close();
                conn = null;
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    /**
     * 给一个完整查询语句,返回结果集
     * @param sql
     * @param args
     * @return
     */
    public ResultSet execQuery(String sql, Object... args) {
        release();
        getConn();
        try {
            if (args.length == 0) {

                stmt = conn.createStatement();

                rs = TableTool.execQuery(stmt, sql);
            } else {
                pstmt = conn.prepareStatement(sql);
                rs = TableTool.execQuery(pstmt, args);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return rs;
    }
    /**
     * 给一个完整更新语句,返回结果集
     * @param sql
     * @param args
     * @return
     */
    public int execUpdate(String sql, Object... args) {
        release();
        getConn();
        int a = 0;
        try {
            if (args.length == 0) {

                stmt = conn.createStatement();

                a = TableTool.execUpdate(stmt, sql);
            } else {
                pstmt = conn.prepareStatement(sql);
                a = TableTool.execUpdate(pstmt, args);
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return a;
    }

    /**
     * 析构方法中释放资源
     */
    protected void finalized() {
        release();
    }
}

其余代码

DBInfo.java

package com.iss.db.dao.dbinfo;
public interface DBInfo {
    public String getDriverName();
    public String getUrl();
    public String getUser();
    public String getPwd();
}

GetConfig .java

package com.iss.db.dao.dbinfo;
/**
 * 获取配置信息
 */
public interface GetConfig {
    public String getByKey(String key);
}
package com.iss.db.dao.dbinfo;

import java.util.HashMap;
import java.util.Map;

/**
 * GetConfig、DBInfo的一个非配置文件实现
 */
public class DBConfig implements GetConfig,DBInfo {

    private final Map<String,String> dbConfig = new HashMap<String,String>(){
        {
            put("driver","com.mysql.jdbc.Driver");
            put("host","localhost");
            put("port","3306");
            put("dbName","sakila");
            put("user","root");
            put("pwd","root");
            put("url","jdbc:mysql://"+get("host")+":"+get("port")+"/"+get("dbName")+"?useUnicode=true&characterEncoding=utf8");
        }
    };
    @Override
    public String getByKey(String key) {
        return dbConfig.get(key);
    }

    public DBConfig setByKey(String key,String value){
        if(dbConfig.containsKey(key)){
            dbConfig.replace(key, value);
        }else{
            dbConfig.put(key, value);
        }
        return this;
    }

    @Override
    public String getUrl() {
        return getByKey("url");
    }

    @Override
    public String getUser() {
        return getByKey("user");
    }

    @Override
    public String getPwd() {
        return getByKey("pwd");
    }

    @Override
    public String getDriverName() {
        return getByKey("driver");
    }
}

TableInfo .java

package com.iss.db.dao.tableinfo;
public interface TableInfo {
    public String tableName();
    public String pkName();
    public String[] updateArray();
}

TableDic.java

package com.iss.db.dao.tableinfo;

public class TableDic implements TableInfo {

    private String tableName ;
    private String pkname = "id";
    private String[] array;
    @Override
    public String pkName() {
        return pkname;
    }
    @Override
    public String[] updateArray() {
        return array;
    }
    public TableDic(String pk,String tableName,String...update){
        super();
        this.pkname = pk.toLowerCase();
        this.tableName = tableName;
        for(int i=0;i<update.length;i++){
            update[i] = update[i].toLowerCase();
        }
        this.array = update;
    }
    @Override
    public String tableName() {
        return tableName;
    }
}

=_=|| 本来还想改进改进,但是学了MyBatis发现MyBatis框架所拥有的功能就是我想要实现的,我就不必发明轮子了。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值