手書きデータベースフレームワーク


目次
前言
Androidは今までオープンソースのフレームワークが多く、データベースのフレームワークもいくつか良いものがありますが、私たちの開発者にとってネット上には多くのフレームワークがあります.私たちは持ってきて使うだけで、一般的にプロジェクトで出会った問題を解決することができます.私たちが自分で書いたコードの量は少なく、開発のボトルネックを突破することも難しいです.開発モデルはCtrl+C Ctrl+Vになりました.依存してきたjarパッケージには、プロジェクトが必要としないものもあります.多くの冗長コード量が大きい場合、間接的にappが大きくなるため、この場合は手書きコードでこの問題を解決する必要があります.今日はデータベースフレームワークを書きます.
テキストセクション
1.まず新しいASプロジェクトプロジェクトを作成し、最上位のデータベースインタフェースIBaseDaoを構築する.ここでは、使用する方法を定義し、最も基礎的な添削・改ざんなどを行い、実装クラスを呼び出し、insert方法は挿入する必要があるオブジェクトである.もちろん、挿入する必要があるオブジェクトはユーザーによって決定されるべきである.
public interface IBaseDao{

    /**      */
    long insert(T entity);

    /**      */
    int delete(String condition,String[] value);

}

2.上記で定義したインタフェースを実装する実装クラスを再構築します.データベースを操作する必要があります.androidが提供するデータベース操作クラスを使用します.
SQLiteDatabase      ,               Class                        ,          ,              ,    java     ,        ,  User    ,User (    User      ,          )

ここに戻ると、テーブル名とオブジェクトフィールドを取得する方法が解決され、テーブルの具体的なコードロジックを確立してブレークポイントを一歩一歩見ていきます.
public class BaseDao implements IBaseDao{
    //     ,          
    private SQLiteDatabase sqLiteDatabase;
    //           java  
    private Class entityClass;
    //  
    private String tableName;
    //  ,        
    private boolean isInit = false;

    //        (key -     )
    private HashMap cacheMap;

    public boolean init(SQLiteDatabase sqLiteDatabase, Class entityClass) {
        this.sqLiteDatabase = sqLiteDatabase;
        this.entityClass = entityClass;
        //    (      )
        if (!isInit){
            //             
            tableName=entityClass.getAnnotation(DBTable.class).value();
            if (!sqLiteDatabase.isOpen()){
                return false;
            }
            //         
            String creatTableSql = getCreateTableSql();
            sqLiteDatabase.execSQL(creatTableSql);
            isInit = true;

            //       
            cacheMap = new HashMap<>();
            initCacheMap();
        }
        return isInit;
    }

    private void initCacheMap() {
        //1.       
        String sql = "select * from " + tableName +" limit 1,0";
        Cursor cursor = sqLiteDatabase.rawQuery(sql,null);
        String[] columnNames = cursor.getColumnNames();
        //2.        
        Field[] clounmnFields = entityClass.getDeclaredFields();
        //3.  2          
        for (String columnName: columnNames){
            Field resultField = null;
            for (Field field:clounmnFields){
                String fieldAnnotionName = field.getAnnotation(DBField.class).value();
                if (columnName.equals(fieldAnnotionName)){
                    resultField = field;
                    break;
                }
            }
            if (resultField != null){
                cacheMap.put(columnName,resultField);
            }
        }
    }

    /***
     *      
     * @return
     */
    private String getCreateTableSql() {
        StringBuffer stringBuffer = new StringBuffer();
        stringBuffer.append("create table if not exists ");
        stringBuffer.append(tableName+"(");
        //           
        Field[] fields = entityClass.getDeclaredFields();
        for (Field field: fields){
            Class type = field.getType();
            if (type == String.class){
                stringBuffer.append(field.getAnnotation(DBField.class).value()+" TEXT,");
            }else if (type == Integer.class){
                stringBuffer.append(field.getAnnotation(DBField.class).value()+" INTEGER,");
            }else if (type == Long.class){
                stringBuffer.append(field.getAnnotation(DBField.class).value()+" BIGINT,");
            }else if (type == Double.class){
                stringBuffer.append(field.getAnnotation(DBField.class).value()+" DOUBLE,");
            }else if (type == byte[].class){
                stringBuffer.append(field.getAnnotation(DBField.class).value()+" BLOB,");
            }else {
                continue;
            }
        }
        if (stringBuffer.charAt(stringBuffer.length() - 1) == ','){
            stringBuffer.deleteCharAt(stringBuffer.length() - 1);
        }
        stringBuffer.append(")");
        return stringBuffer.toString();
    }

    /**
     *
     * @param entity
     * @return
     */
    @Override
    public long insert(T entity) {
        //1.   ContentValues
        Map map = getValues(entity);
        //2.    
        ContentValues values = getContentValues(map);
        //3.    
        long result = sqLiteDatabase.insert(tableName,null,values);
        return result;
    }

    /**
     *     
     * @param condition
     * @return
     */
    @Override
    public int delete(String condition,String[] value) {
        sqLiteDatabase.delete(tableName,condition,value);
        return 0;
    }


    private ContentValues getContentValues(Map map) {
        ContentValues contentValues = new ContentValues();
        Set keys = map.keySet();
        Iterator iterator = keys.iterator();
        while (iterator.hasNext()){
            String key = iterator.next();
            String value = map.get(key);
            if (value != null){
                contentValues.put(key,value);
            }
        }
        return contentValues;
    }

    private Map getValues(T entity) {
        HashMap map = new HashMap<>();
        Iterator fieldItertor = cacheMap.values().iterator();
        while (fieldItertor.hasNext()){
            Field field = fieldItertor.next();
            field.setAccessible(true);
            //      
            try {
                Object object = field.get(entity);
                if (object == null){
                    continue;
                }
                String value = object.toString();
                //     _id name password
                String key = field.getAnnotation(DBField.class).value();
                if (!TextUtils.isEmpty(key) && !TextUtils.isEmpty(value)){
                    map.put(key,value);
                }
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
        return map;
    }
}

ここではUserオブジェクトですが、ここに@DBTableがありますが、これは表名を反射するために使用されています.以下に示すように、@Targetは注釈表示の位置で、パラメータが多く、対応して使用できます.ここではクラスに書いてあるので、ElementTypeを使用します.TYPE,2番目にその保持時間を設定,@Retention,ここで選択するのはRetentionPolicy.RUNTIMEは、実行時にDBTable反射機構でテーブル名を得ることができることを示していますが、オブジェクト情報のすべてのフィールドを取得する必要がある場合も同様に、ここでDBFieldを構築し続けます.これらの作業が終わったら、上に戻ってBaseDaoクラスコードを継続します.
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface DBField {
    String value();
}
@DBTable("tb_user")
public class User {
    @DBField("id")
    private Integer id;
    @DBField("name")
    private String name;
    @DBField("password")
    private String password;

    public User(Integer id, String name, String password) {
        this.id = id;
        this.name = name;
        this.password = password;
    }
}
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface DBTable {

    String value();

}

DBField
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface DBField {
    String value();
}

最終的な呼び出し方法:
BaseDao userDao = BaseDaoFactoty.getOurInstance().getBaseDao(User.class);
userDao.insert(new User(1,".","hahaha"));

demoアドレスは次のとおりです.https://github.com/w947329887/-