輕量級封裝DbUtils&Mybatis之一律要

Why

一時興起,自覺得是的對Jdbc訪問框架作了一個簡單的摸底,近期主要採用Mybatis,以前也有很多采用Dbutils,所以但願能讓這兩個框架折騰的更好用。
DbUtils:很是簡單的Jdbc訪問框架,極爲輕量級,對數據查詢結果集轉換成目標的對象或列表或其它集合結構作了很好的支持(xxHandler)。
Mybatis:ibatis(暫未使用過)的升級版,目前所知它至少有兩個坑,其一是假分頁(參考DefaultResultSetHandler的skipRows方法),其二是不能支持對象列表存儲時對自增id字段的賦值(至少包括3.2.6和3.3.0版本)。java

參考項目

mybatis分頁組件(也支持排序,經過外置增長的排序和分頁選項,在mapper文件中配置sql不包含排序):mybatis-paginationmysql

輕量級改造概要

Dbutilsgit

  • 簡單的封裝,增長代碼複用,並儘可能支持泛型化

Mybatisgithub

  • 實際的處理分頁攔截器,暫只支持MySQL和Oracle(目前網絡上關於此已經有了大量的實踐,可是我的認爲某些實踐破壞了Mybatis自己的一些優良特性,細節將在後面的文章給出說明)
  • 處理對象列表存儲時自動對自增主鍵賦值,目前幾乎徹底照搬了Git上的一個項目mybatis-batch-insert的內容,只是稍作修改。

場景

試想一下,當使用原生Jdbc執行SQL時,咱們但願它有哪些feature呢?sql

  • 支持查詢泛型對象列表
  • 支持插入對象列表時自動填充主鍵
  • 支持插入對象列表
  • 支持批量插入和更新
  • 支持SQL語句生成和解析
  • 支持多種數據庫
  • 支持結果集處理成各種存儲結構(list,map)

實現細節

方言

除去標準SQL支持,不一樣數據庫的SQL語法略有差別(雖然知道的很少),好比分頁,MySQL採用limit關鍵字支持,Oracle則採用rownum支持。數據庫

方言枚舉(目前僅支持MySQL和Oracle,其它的暫時用不到)express

package org.wit.ff.jdbc.dialect;

/**
 * Created by F.Fang on 2015/11/19.
 */
public enum DialectType {
    MYSQL, ORACLE
}

方言定義
請參考mybatis-pagination項目裏關於方言的定義,此處就不引用他的代碼了,請爲他的Job增長人氣。apache

標準SQL生成

標準SQL支持

請參考Mybatis的AbstractSQLBuilder和SQLBuilder數組

SQLBuilder(有修改,增長分頁支持)

/*
 *    Copyright 2009-2012 The MyBatis Team
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */
package org.wit.ff.jdbc.sql;

import org.wit.ff.jdbc.dialect.Dialect;

public abstract class SQLBuilder extends AbstractSQLBuilder<SQLBuilder> {

    protected boolean paging;
    protected int offset;
    protected int pageSize;

    @Override
    public SQLBuilder getSelf() {
        return this;
    }

    protected abstract Dialect getDialect();

    public SQLBuilder PAGE(int offset, int pageSize) {
        paging = true;
        // 這裏做爲底層接口不作任何檢查,上層業務調用時檢查.
        this.offset = offset;
        this.pageSize = pageSize;
        return this;
    }

    @Override
    public String toString() {
        if(paging){
            return getDialect().getLimitString(super.toString(), offset, pageSize);
        }else{
            return super.toString();
        }
    }

}

MySQLBuilder

package org.wit.ff.jdbc.sql.db;


import org.wit.ff.jdbc.dialect.Dialect;
import org.wit.ff.jdbc.dialect.db.MySQLDialect;
import org.wit.ff.jdbc.sql.SQLBuilder;

/**
 * Created by F.Fang on 2015/2/16.
 * Version :2015/2/16
 */
public class MySQLBuilder extends SQLBuilder {

    private Dialect dialect = new MySQLDialect();

    @Override
    public Dialect getDialect() {
        return dialect;
    }
}

OracleBuilder

package org.wit.ff.jdbc.sql.db;

import org.wit.ff.jdbc.dialect.Dialect;
import org.wit.ff.jdbc.dialect.db.OracleDialect;
import org.wit.ff.jdbc.sql.SQLBuilder;

/**
 * Created by F.Fang on 2015/11/20.
 */
public class OracleBuilder extends SQLBuilder {

    private Dialect dialect = new OracleDialect();

    @Override
    public Dialect getDialect() {
        return dialect;
    }
}

自增主鍵處理

自定義接收主鍵數據的接口網絡

package org.wit.ff.jdbc.id;

/**
 * Created by F.Fang on 2015/2/16.
 * Version :2015/2/16
 */
public interface IdGenerator {
    /**
     * 參數爲數組的緣由是考慮聯合主鍵,雖然暫時不會有對聯合主鍵的支持.
     * @param value
     */
    void parseGenKey(Object[] value);
}

數據接口定義

package org.wit.ff.jdbc.access;


import org.wit.ff.jdbc.converter.ParamsConverter;

import java.util.List;

/**
 * Created by F.Fang on 2015/3/31.
 * 簡單公共數據訪問層.
 * Version :2015/3/31
 */
public interface IDataAccessor {

    /**
     * 查詢
     * @param sql
     * @param resultType 對象類型
     * @param <T>
     * @return
     */
    <T> List<T> query(String sql, Class<T> resultType);

    /**
     * 查詢,若是返回類型是具體類型,那麼就採用
     * @param sql 查詢語句
     * @param params 查詢參數
     * @param resultType 返回類型
     * @param <T>
     * @return
     */
    <T> List<T> query(String sql, Object[] params, Class<T> resultType);


    /**
     * insert 對象列表.
     * @param sql insert語句.
     * @param params 對象參數列表.
     * @param paramsType 參數類型.
     * @param converter 參數轉換器.
     * @param <T>
     */
    <T> void insert(String sql, List<T> params, Class<T> paramsType, ParamsConverter<T> converter);

    /**
     * insert batch.
     * @param sql
     * @param params
     */
    void insert(String sql, Object[][] params);

    /**
     * single insert.
     * @param sql
     * @param params
     */
    void insert(String sql, Object[] params);

    /**
     * batch update.
     * @param sql
     * @param params
     * @return
     */
    int[] update(String sql, Object[][] params);

    /**
     * single update.
     * @param sql
     * @param params
     * @return
     */
    int update(String sql, Object[] params);

    /**
     * 刪除,刪除可採用條件替代批量.
     * @param sql
     * @param params
     * @return
     */
    int delete(String sql, Object[] params);

}

參數處理

package org.wit.ff.jdbc.converter;

/**
 * Created by F.Fang on 2015/3/31.
 * 用於參數轉換的接口.
 * Version :2015/3/31
 */
public interface ParamsConverter<T> {
    Object[] convert(T obj);
}

結果集處理

暫無(目前開源社區有大量的相關API)

QA

相關文章
相關標籤/搜索