手寫(xiě)orm框架

寫(xiě)在前面

ORM框架,關(guān)系映射框架,只需要提供持久化類和數(shù)據(jù)庫(kù)表之間的關(guān)系,就可以在運(yùn)行時(shí)候進(jìn)行數(shù)據(jù)持久化,通常javaweb使用hibernate或者mybatis,本文就是寫(xiě)了一個(gè)簡(jiǎn)易版的orm框架。。只是實(shí)現(xiàn)了部分功能

功能介紹

1.可以根據(jù)表結(jié)構(gòu)自動(dòng)生成實(shí)體類
2.可直接插入,修改刪除對(duì)象,不需要寫(xiě)sql語(yǔ)句
3.在查詢時(shí)候需要自己寫(xiě)SQL語(yǔ)句,支持多行,單行,某一個(gè)字段的查詢
4.支持自定義實(shí)體類查詢,當(dāng)在進(jìn)行連表查詢的時(shí)候,得到的數(shù)據(jù)是自定義的,可自定義一個(gè)實(shí)體類進(jìn)行接收
5.連接使用了連接池,效率相對(duì)高一點(diǎn)

1.接口設(shè)計(jì)

  • Query接口:符合查詢,對(duì)外提供服務(wù)的核心類
  • QueryFactory類:管理query對(duì)象
  • TypeConvertor接口:負(fù)責(zé)數(shù)據(jù)類型轉(zhuǎn)換
  • TableContext類:負(fù)責(zé)獲取數(shù)據(jù)庫(kù)的表結(jié)構(gòu)和類結(jié)構(gòu)的關(guān)系,并可以根據(jù)表結(jié)構(gòu)生成類結(jié)構(gòu),
  • DBManager類:根據(jù)配置信息,維持連接對(duì)象的管理
    工具類
    JdbcUtils 用來(lái)封裝通用的jdbc操作
    StringUtils 用來(lái)封裝常用的字符串操作
    ReflectUtils 用來(lái)封裝反射相關(guān)的操作
    PathUtils 用來(lái)操作本地文件路徑相關(guān)的操作
    JavaFileUtils
    核心bean
  • COlumnInfo 封裝表中一個(gè)字段的信息
  • Configuration 封裝整個(gè)項(xiàng)目的配置信息
  • TableInfo: 封裝一張表的信息
  • JavaFeildInfo:用于封裝一個(gè)屬性和get set方法的數(shù)據(jù)(在自動(dòng)生成java文件的時(shí)候用)

2.具體實(shí)現(xiàn)

1.query接口設(shè)計(jì)

框架封裝了常用的幾個(gè)方法

//將某個(gè)實(shí)體類持久化到數(shù)據(jù)庫(kù)中
public void insert(Object object);
//從數(shù)據(jù)庫(kù)中刪除某個(gè)數(shù)據(jù)
 public void delete(Object object)
//從數(shù)據(jù)庫(kù)中刪除某條數(shù)據(jù),指定id
 public void delete(Class clazz,Object id) ;
//更新某條數(shù)據(jù)
public void update(Object object,String[] fieldNames);
//根據(jù)傳入的sql語(yǔ)句進(jìn)行 查詢數(shù)據(jù),某個(gè)類型的數(shù)據(jù)
 public List queryRows(String sql,Class clazz,Object[] params);
//查找某一列的數(shù)據(jù)
 public Object queryValue(String sql,Object[] params);
//執(zhí)行增刪改sql語(yǔ)句的方法
public int executeDML(String sql,Object[] params);

2.數(shù)據(jù)類型轉(zhuǎn)換器

因?yàn)椴恢理?xiàng)目用的什么數(shù)據(jù)庫(kù),所以數(shù)據(jù)類型也不一樣,類型轉(zhuǎn)換器是一個(gè)接口,提供了實(shí)現(xiàn),現(xiàn)在只提供了mysql數(shù)據(jù)類型轉(zhuǎn)換器

2.2.1

轉(zhuǎn)換器有兩個(gè)方法,一個(gè)是java數(shù)據(jù)類型轉(zhuǎn)換成數(shù)據(jù)庫(kù)數(shù)據(jù)類型,另一個(gè)是數(shù)據(jù)庫(kù)類型轉(zhuǎn)換成java數(shù)據(jù)類型,因?yàn)榇隧?xiàng)目需要根據(jù)數(shù)據(jù)庫(kù)表生成java文件,所以只實(shí)現(xiàn)了數(shù)據(jù)庫(kù)類型轉(zhuǎn)換成java數(shù)據(jù)類型,如果需要另外轉(zhuǎn)換,只需要反過(guò)來(lái)即可

3.Configuration封裝配置信息

配置文件是db.properties,在src下

driver = com.mysql.jdbc.Driver //數(shù)據(jù)庫(kù)驅(qū)動(dòng)
username = root  //用戶名
password = 123456 //密碼
useDB = mysql  //聲明使用的數(shù)據(jù)庫(kù)
url = jdbc:mysql://localhost:3306/test // 連接url
packageName = jk.zmn.sorm.pojo  //聲明自動(dòng)生成的實(shí)體類放在當(dāng)前項(xiàng)目哪個(gè)包下,可不存在

這個(gè)類主要是用來(lái)封裝用戶的配置信息,將配置信息保存起來(lái),使用更方便,配置類即是將這個(gè)屬性都封裝起來(lái)

4.DBManager類

這個(gè)類主要是用來(lái),讀取用戶的配置信息然后將信息封裝到configuration類中,管理數(shù)據(jù)庫(kù)連接,等功能


2.3.1 封裝配置信息

圖2.3.1封裝配置信息

2.3.2

圖2.3.2是管理數(shù)據(jù)庫(kù)連接,后期將會(huì)增加連接池功能

4.TableContext類

此類用來(lái)連接數(shù)據(jù)庫(kù),得到庫(kù)中的表,并封裝起來(lái),并且根據(jù)表信息自動(dòng)生成java文件,當(dāng)生成java實(shí)體類的時(shí)候,需要使用map將實(shí)體類的Class文件和表信息對(duì)應(yīng)存儲(chǔ)起來(lái),用于數(shù)據(jù)持久化,后面會(huì)講到

5.自動(dòng)生成java實(shí)體類實(shí)現(xiàn)

約定:如何根據(jù)表信息生成java類呢,我們先看看平時(shí)手動(dòng)生成的java實(shí)體類是什么樣子的,如表user,或_user 或t_user 再看看字段,id,name,或者t_id,t_name,我們自己寫(xiě)實(shí)體類會(huì)寫(xiě)成什么樣子呢,Class User 屬性寫(xiě)成 id,name或tname,tid, 那我們就先來(lái)個(gè)約定,如表名user,生成的類就叫User,首字母大寫(xiě),去掉下劃線,字段也是一樣,只需要去掉下劃線,get和set方法是getId 或者setName,首字母大寫(xiě),
思路: 上面我們已經(jīng)得到了數(shù)據(jù)庫(kù)中所有的表信息,也有了生成實(shí)體類的約定,那到底怎么生成呢,1.我們確定類名,根據(jù)表名得到得到類名, 2.屬性如何生成呢,還有g(shù)et set方法,我們將一個(gè)屬性和一個(gè)getset 方法封裝在一個(gè)類中,根據(jù)表中的字段信息,來(lái)生成一個(gè)字段對(duì)應(yīng)的屬性的相關(guān)信息,然后將所有字段的信息整合在這個(gè)類中,具體實(shí)現(xiàn)一下,我們還缺一些東西

5.1 ColumnInfo 類

封裝表中一個(gè)字段的信息,什么意思,
封裝了三個(gè)屬性,

  /**
    * 字段名稱
    */
    private String name;

    /**
     * 字段數(shù)據(jù)類型
     */
    private String dataType;

    /**
     * 字段鍵類型 0普通鍵,1主鍵 2外鍵
     */
    private int keyType;

5.2TableInfo

封裝一張表的信息

  /**
     * 表名
     */
    private String name;
    /**
     * 存放字段信息, 字段名和字段信息
     */
    private Map<String,ColumnInfo> columns;
    /**
     * 主鍵信息
     */
    private ColumnInfo onlyPriKey;
    /**
     * 聯(lián)合主鍵
     */
    private List<ColumnInfo> priKeys;

5.3JavaFeildInfo

用于封裝一個(gè)屬性和get set方法的數(shù)據(jù),最后拼接類文件的時(shí)候用

 /**
     * 屬性信息 private String feild
     */
    private String feildInfo;
    /**
     * 封裝get方法
     */
    private String getFeildInfo;
    /**
     * 封裝set方法
     */
    private String setFeildInfo;

有了上面的基本數(shù)據(jù),就可以進(jìn)行操作了

5.4 開(kāi)始生成文件

上面介紹了tablecontext類,用來(lái)得到數(shù)據(jù)庫(kù)中的表,使用map封裝起來(lái),附上源碼,接著下面看


    /**
     * 表名為key,表信息對(duì)象為value
     */
    public static Map<String,TableInfo> tables = new HashMap<String,TableInfo>();

    /**
     * 將po的class對(duì)象和表信息對(duì)象關(guān)聯(lián)起來(lái),便于重用!
     */
    public static  Map<Class,TableInfo>  poClassTableMap = new HashMap<Class,TableInfo>();

    private TableContext(){}

    static {
        try {
            //初始化獲得表的信息
            Connection con = DBManager.getConnection();
            DatabaseMetaData dbmd = con.getMetaData();

            ResultSet tableRet = dbmd.getTables(null, "%","%",new String[]{"TABLE"});

            while(tableRet.next()){
                String tableName = (String) tableRet.getObject("TABLE_NAME");

                TableInfo ti = new TableInfo(tableName,
                        new HashMap<String, ColumnInfo>(),new ArrayList<ColumnInfo>());
                tables.put(tableName, ti);

                ResultSet set = dbmd.getColumns(null, "%", tableName, "%");  //查詢表中的所有字段
                while(set.next()){
                    ColumnInfo ci = new ColumnInfo(set.getString("COLUMN_NAME"),
                            set.getString("TYPE_NAME"), 0);
                    ti.getColumns().put(set.getString("COLUMN_NAME"), ci);
                }

                ResultSet set2 = dbmd.getPrimaryKeys(null, "%", tableName);  //查詢t_user表中的主鍵
                while(set2.next()){
                    ColumnInfo ci2 = (ColumnInfo) ti.getColumns().get(set2.getObject("COLUMN_NAME"));
                    ci2.setKeyType(1);  //設(shè)置為主鍵類型
                    ti.getPriKeys().add(ci2);
                }

                if(ti.getPriKeys().size()>0){  //取唯一主鍵。。方便使用。如果是聯(lián)合主鍵。則為空!
                    ti.setOnlyPriKey(ti.getPriKeys().get(0));
                }
            }
        } catch (SQLException e) {
            e.printStackTrace();
        }


        //生成java文件
        updatePoFile();


        //將對(duì)應(yīng)的類和表封裝起來(lái)
        loadTablePoToMap();

    }

    /**
     *  根據(jù)數(shù)據(jù)庫(kù)表結(jié)構(gòu)生成pojo類
     */
    public static void updatePoFile(){
        JavaFileUtils.createJavaFileToPackage();
    }


    /**
    *  加載完數(shù)據(jù)庫(kù)中的表,生成pojo之后,把對(duì)應(yīng)的類和對(duì)應(yīng)的表關(guān)聯(lián)起來(lái)
    * @date 2018/6/15 19:44
    * @param
    * @return void
    */
    public static void loadTablePoToMap(){

        for (TableInfo tableInfo : tables.values()){
            //實(shí)體類
            Class<?> aClass = null;
            try {
                aClass = Class.forName(DBManager.getConfiguration().getPackageName()
                        +"."+StringUtils.UpFirstString(tableInfo.getName()));
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
            poClassTableMap.put(aClass,tableInfo);
        }


    }


5.5 使用javafileutils生成java文件

講一下思路:得到了所有的表信息,如何拼接成一個(gè)類
1.首先要先得到類名
根據(jù)表信息,得到j(luò)ava文件的類名,
2.得到所有的屬性和get set方法
得到表的一個(gè)字段信息,將字段的數(shù)據(jù)類型轉(zhuǎn)換成java數(shù)據(jù)類型,將字段名轉(zhuǎn)換成類的屬性名,拼接字符串,就得到了一個(gè)定義屬性的字符串,然后封裝get和set方法,將這一個(gè)屬性的信息,封裝在FieldInfo中,循環(huán)將所有的屬性都封裝完畢,
3.拼裝整個(gè)類文件
將包名,和類名和屬性一起封裝起來(lái),然后使用io流將文件輸出,問(wèn)題來(lái)了,輸出到哪里,指定了包,包不存在,使用PathUtils,將包名穿進(jìn)去,就會(huì)自動(dòng)創(chuàng)建包,

附源碼,
PathUtils

  String str=packageName; //"jk.zmn.auto.dfd";
        str = str.replace(".","\\");
        File file = new File("");
        String canonicalPath = null;
        try {
            canonicalPath = file.getCanonicalPath();
        } catch (IOException e) {
            e.printStackTrace();
        }

        canonicalPath += "\\src\\"+str;
//        String resource = Thread.currentThread().getContextClassLoader().getResource("/").getPath();
//        resource = resource.substring(1);
//        System.out.println(resource);
        File packageFile = new File(canonicalPath);
        if (!packageFile.exists()){
            packageFile.mkdirs();
        }

        return canonicalPath;
    }

JavaFileutils

private static Configuration configuration = DBManager.getConfiguration();
    /**
     * private String name;
     * <p>
     * private String dataType;
     * <p>
     * private int keyType;
     */
    public static javaFeildInfo createJavaFeild(ColumnInfo columnInfo, TypeConvertorHandler convertorHandler) {

        //將字段數(shù)據(jù)類型轉(zhuǎn)換成java數(shù)據(jù)類型
        String javaType = convertorHandler.JdbcType2JavaType(columnInfo.getDataType());

        String columnName = columnInfo.getName().toLowerCase();
        javaFeildInfo feildInfo = new javaFeildInfo();
        //生成屬性語(yǔ)句
        feildInfo.setFeildInfo("\tprivate " + javaType + " " + StringUtils.trimUnderLine(columnName) + ";\n");

        StringBuilder sb = new StringBuilder();
        sb.append("\tpublic " + javaType + " " + "get" + StringUtils.UpFirstString(columnName) + "() {\n");

        sb.append("\t\treturn " + columnName + ";\n");

        sb.append("\t}\n");

        feildInfo.setGetFeildInfo(sb.toString());


        StringBuilder sb1 = new StringBuilder();

        sb1.append("\tpublic void " + "set" + StringUtils.UpFirstString(columnName) + "(" + javaType + " " + columnName + ") {\n");

        sb1.append("\t\t this." + columnName + " = " + columnName + ";\n");

        sb1.append("\t}\n");

        feildInfo.setSetFeildInfo(sb1.toString());

        return feildInfo;
    }


    public static void createJavaFile(TableInfo tableInfo, TypeConvertorHandler typeConvertorHandler){

        //得到所有的列信息
        Map<String, ColumnInfo> columns = tableInfo.getColumns();

        ArrayList<javaFeildInfo> javaFeildInfos = new ArrayList<>();
        Collection<ColumnInfo> values = columns.values();

        //生成所有的java屬性信息和get set方法
        for (ColumnInfo columnInfo : values){
            javaFeildInfo javaFeild = createJavaFeild(columnInfo, typeConvertorHandler);
            javaFeildInfos.add(javaFeild);
        }

        StringBuilder sb = new StringBuilder();

        sb.append("package "+configuration.getPackageName()+";\n\n");
        sb.append("import java.sql.*;\n");
        sb.append("import java.util.*;\n\n");
        sb.append("public class "+StringUtils.UpFirstString(tableInfo.getName())+" {\n\n");

        for (javaFeildInfo javaFeildInfo: javaFeildInfos){
            sb.append(javaFeildInfo.getFeildInfo());
        }
        sb.append("\n");
        for (javaFeildInfo javaFeildInfo: javaFeildInfos){
            sb.append(javaFeildInfo.getGetFeildInfo());
        }
        for (javaFeildInfo javaFeildInfo: javaFeildInfos){
            sb.append(javaFeildInfo.getSetFeildInfo());
        }

        sb.append("}\n");
        //System.out.println(sb.toString());

        String classInfo = sb.toString();

        String filePathFromPackage = PathUtils.getFilePathFromPackage(configuration.getPackageName());
        File file = new File(filePathFromPackage, StringUtils.UpFirstString(tableInfo.getName()) + ".java");
        BufferedOutputStream bufferedOutputStream=null;
        try {
            bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(file));

            bufferedOutputStream.write(classInfo.getBytes(),0,classInfo.getBytes().length);

            bufferedOutputStream.flush();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                bufferedOutputStream.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        System.out.println("表"+tableInfo.getName()+"對(duì)應(yīng)的類"+StringUtils.UpFirstString(tableInfo.getName())+"已自動(dòng)生成..");
    }


    public static void createJavaFileToPackage(){

        Map<String, TableInfo> tables = TableContext.tables;
        TypeConvertorHandler convertorHandler = null;
        if (configuration.getUseDB().equalsIgnoreCase("mysql")){
            convertorHandler = new MysqlConvertorHandler();
        }
        for (TableInfo tableInfo:tables.values()){
            createJavaFile((tableInfo),convertorHandler);
        }
    }

6.查詢實(shí)現(xiàn)

如今實(shí)體類已經(jīng)有了,那么如何對(duì)數(shù)據(jù)進(jìn)行操作呢
,上面我們定義了一個(gè)Query接口,不同數(shù)據(jù)庫(kù)查詢可能不一樣,所以做一個(gè)mysqlQuery的實(shí)現(xiàn)類,做mysql的查詢

簡(jiǎn)單介紹添加方法,
傳入實(shí)體類,如何持久化到數(shù)據(jù)庫(kù)呢,還記得我們前面在得到數(shù)據(jù)庫(kù)表,生成java文件的時(shí)候?qū)ⅲ瑢?shí)體類的Class對(duì)象和表名存儲(chǔ)起來(lái)嗎,現(xiàn)在用到了哦

得到該類的Class對(duì)象,從map中取出表名,拼接sql語(yǔ)句,通過(guò)反射,得到該對(duì)象的所有的屬性,判斷是否為空,將不為空的屬性插入,那么該類的屬性的值怎么獲取呢,還是反射,根據(jù)屬性的get和set方法,反射調(diào)用該方法,得到屬性的值,將值和sql一起傳入執(zhí)行sql語(yǔ)句的方法,就完成持久化了

 // insert into logs(a,b) values (?,?)
        //得到類對(duì)應(yīng)的表信息
        Class<?> aClass = object.getClass();
        TableInfo tableInfo = TableContext.poClassTableMap.get(aClass);
        StringBuilder sb = new StringBuilder("insert into "+tableInfo.getName()+"(");
        //得到屬性
        Field[] fields = aClass.getDeclaredFields();

        ArrayList<Object> fieldValueList = new ArrayList<>();
        for (Field field : fields){
            String name = field.getName();
            Object value = ReflectUtils.invokeGet(object, name);
            if (value!=null){
                sb.append(name+",");
                fieldValueList.add(value);
            }
        }
        //將最后一個(gè),換成)
        sb.setCharAt(sb.length()-1,')');
        sb.append(" values(");

        for (int i=0;i<fieldValueList.size();i++){
            sb.append("?,");
        }

        sb.setCharAt(sb.length()-1,')');

        executeDML(sb.toString(),fieldValueList.toArray());

其他方法

    /**
    *  刪除一個(gè)對(duì)象
    * @date 2018/6/15 16:54
    * @param object 要移除的對(duì)象
    * @return void
    */
    public void delete(Object object){

        Class<?> aClass = object.getClass();

        TableInfo tableInfo = TableContext.poClassTableMap.get(aClass);
        //得到表的主鍵
        ColumnInfo onlyPriKey = tableInfo.getOnlyPriKey();

        String sql = "delete from "+tableInfo.getName()+" where "+onlyPriKey.getName()+"=?";

        //反射調(diào)用get方法,得到屬性的值
        Object o = ReflectUtils.invokeGet(object, onlyPriKey.getName());
        executeDML(sql,new Object[]{o});

    }
    /**
    *  刪除類 對(duì)應(yīng)的表中的數(shù)據(jù),刪除該id的對(duì)象
    * @date 2018/6/15 16:55
    * @param clazz  類對(duì)象
    * @param id  主鍵
    * @return void
    */
    public void delete(Class clazz,Object id) {
        // delete from logs where id=?

        TableInfo tableInfo = TableContext.poClassTableMap.get(clazz);
        ColumnInfo onlyPriKey = tableInfo.getOnlyPriKey();
        String sql = "delete from "+tableInfo.getName()+" where "+onlyPriKey.getName()+"=?";
        executeDML(sql.toString(),new Object[]{id});
    }

    /**
    *  更新對(duì)象字段的信息
    * @date 2018/6/15 16:57
    * @param object  對(duì)象
    * @param fieldNames  多個(gè)字段
    * @return void
    */
    public void update(Object object,String[] fieldNames){

        //obj{"uanme","pwd"}-->update 表名  set uname=?,pwd=? where id=?
        Class c = object.getClass();
        List<Object> params = new ArrayList<Object>();   //存儲(chǔ)sql的參數(shù)對(duì)象
        TableInfo tableInfo = TableContext.poClassTableMap.get(c);
        ColumnInfo priKey = tableInfo.getOnlyPriKey();   //獲得唯一的主鍵
        StringBuilder sql  = new StringBuilder("update "+tableInfo.getName()+" set ");

        for(String fname:fieldNames){
            Object fvalue = ReflectUtils.invokeGet(object,fname);
            params.add(fvalue);
            sql.append(fname+"=?,");
        }
        sql.setCharAt(sql.length()-1, ' ');
        sql.append(" where ");
        sql.append(priKey.getName()+"=? ");

        params.add(ReflectUtils.invokeGet(object,priKey.getName()));    //主鍵的值

        executeDML(sql.toString(), params.toArray());
    }


    /**
    *   根據(jù)參數(shù),查詢指定的數(shù)據(jù),多行記錄,單行記錄可直接get(0)
    * @date 2018/6/15 16:59
    * @param sql  sql語(yǔ)句
    * @param clazz   類對(duì)象
    * @param params   sql語(yǔ)句參數(shù)
    * @return java.util.List
    */
    public List queryRows(String sql,Class clazz,Object[] params){
        Connection connection = DBManager.getConnection();
        PreparedStatement ps = null;
        List<Object> rows = new ArrayList<Object>();
        ResultSet resultSet = null;
        try {
            ps = connection.prepareStatement(sql);
            JdbcUtils.handlerParams(ps,params);
            resultSet = ps.executeQuery();
            //得到返回結(jié)果又多少列
            ResultSetMetaData metaData = resultSet.getMetaData();

            while (resultSet.next()){

                Object o = clazz.newInstance();

                for (int i=0;i<metaData.getColumnCount();i++){
                    //得到每一列的名稱
                    String columnLabel = metaData.getColumnLabel(i + 1);
                    Object columnValue = resultSet.getObject(i + 1);
                    ReflectUtils.invokeSet(o, columnLabel, columnValue);
                }

                rows.add(o);
            }

            return rows;

        } catch (Exception e) {
            e.printStackTrace();
        }finally {
            DBManager.close(connection,ps);
        }
        return null;
    }



    /**
    *   查詢某個(gè)字段的數(shù)據(jù)
    * @date 2018/6/15 17:05
    * @param sql  sql語(yǔ)句
    * @param params   參數(shù)
    * @return java.lang.Object 封裝查詢到的數(shù)據(jù)
    */
    public Object queryValue(String sql,Object[] params){

        Connection connection = DBManager.getConnection();
        PreparedStatement ps = null;
        ResultSet resultSet = null;
        Object o =null;
        try {
            ps = connection.prepareStatement(sql);
            JdbcUtils.handlerParams(ps,params);
            resultSet = ps.executeQuery();
            while (resultSet.next()){
                o = resultSet.getObject(1);
            }
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }finally {
            DBManager.close(connection,ps);
        }
        return o;
    }

 /**
    * 執(zhí)行sql語(yǔ)句
    * @date 2018/6/15 16:50
    * @param sql  sql語(yǔ)句
    * @param params  參數(shù)
    * @return int  SQL影響的行數(shù)
     *
    */
    public int executeDML(String sql,Object[] params){

        Connection connection = DBManager.getConnection();
        int count = 0;

        PreparedStatement ps = null;
        try {
            ps = connection.prepareStatement(sql);

            JdbcUtils.handlerParams(ps,params);
            System.out.println(ps);

            count = ps.executeUpdate();
        } catch (SQLException e) {
            e.printStackTrace();
        }finally {
            DBManager.close(connection,ps);
        }
        System.out.println("count:"+count);
        return count;
    }

以上,基礎(chǔ)的增刪改查就可以實(shí)現(xiàn)了

7.項(xiàng)目修改

1.工廠模式得到Query對(duì)象,

private static QueryFactory queryFactory = new QueryFactory();

    private static Class c;

    static {
        if (DBManager.getConfiguration().getUseDB().equalsIgnoreCase("mysql")){

            try {
                c = Class.forName("jk.zmn.sorm.core.MySqlQuery");
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }
    }
    /*
     構(gòu)造器私有化
     */
    private QueryFactory(){
    }

    public static Query createQuery(){
        try {
            return (Query) c.newInstance();
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

2.添加連接池功能
當(dāng)對(duì)數(shù)據(jù)庫(kù)操作很頻繁的時(shí)候,如果每次都新建鏈接,關(guān)閉鏈接,很耗資源,使用連接池保存鏈接,提高項(xiàng)目的效率

/**
     * 連接池對(duì)象
     */
    private List<Connection> pool;

    /**
     * 最大連接數(shù)
     */
    private static final int POOL_MAX_SIZE = DBManager.getConfiguration().getPoolMaxSize();
    /**
     * 最小連接池
     */
    private static final int POOL_MIN_SIZE = DBManager.getConfiguration().getPoolMinSize();


    /**
     * 初始化連接池,使池中的連接數(shù)達(dá)到最小值
     */
    public void initPool() {
        if(pool==null){
            pool = new ArrayList<Connection>();
        }

        while(pool.size()<DBPool.POOL_MIN_SIZE){
            pool.add(DBManager.getConnection());
            System.out.println("初始化池,池中連接數(shù):"+pool.size());
        }
    }


    /**
     * 從連接池中取出一個(gè)連接
     * @return
     */
    public synchronized Connection getConnection() {
        int last_index = pool.size()-1;
        Connection conn = pool.get(last_index);
        pool.remove(last_index);

        return conn;
    }

    /**
     * 將連接放回池中
     * @param conn
     */
    public synchronized void close(Connection conn){

        if(pool.size()>=POOL_MAX_SIZE){
            try {
                if(conn!=null){
                    conn.close();
                }
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }else {
            pool.add(conn);
        }
    }


    public DBPool() {
        initPool();
    }

3.測(cè)試

如此一來(lái),項(xiàng)目大致就結(jié)束了,直接打成jar包,由別的項(xiàng)目引入
新建項(xiàng)目,導(dǎo)入此jar包

添加


image.png

image.png

image.png

這里的count是影響數(shù)據(jù)庫(kù)的行數(shù)

查詢


image.png
image.png

演示到這里
源碼看這里:https://gitee.com/zhangqiye/SORM
QQ群:552113611

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 1、通過(guò)CocoaPods安裝項(xiàng)目名稱項(xiàng)目信息 AFNetworking網(wǎng)絡(luò)請(qǐng)求組件 FMDB本地?cái)?shù)據(jù)庫(kù)組件 SD...
    陽(yáng)明AI閱讀 16,205評(píng)論 3 119
  • 朋友:并不時(shí)常想起,卻無(wú)處不在。
    佳民lc閱讀 647評(píng)論 0 0
  • 看過(guò)《月亮與六便士》后,我一直篤信作者毛姆不僅是一位偉大的作家,而且也是一位很偉大的心里學(xué)家。盡管在此之前,同...
    45a400eab9e6閱讀 153評(píng)論 0 3
  • 《奇葩說(shuō)》第三季又開(kāi)始了,其實(shí)對(duì)于前2季的影響已經(jīng)算是有點(diǎn)模糊了,只是覺(jué)得當(dāng)時(shí)看的時(shí)候的確是被幾集的論題引發(fā)過(guò)一些...
    橘子醬666閱讀 3,193評(píng)論 27 55
  • 如果我們不能在你失敗時(shí)支持你,那我如何在你勝利時(shí)說(shuō)愛(ài)你; 國(guó)足都贏了,路上的你還害怕寂寞嗎? 在這場(chǎng)12強(qiáng)賽場(chǎng),國(guó)...
    東莞市品牌商學(xué)院閱讀 231評(píng)論 0 0

友情鏈接更多精彩內(nèi)容