android自己動手封裝Sqllite數(shù)據(jù)庫

廢話:

android數(shù)據(jù)庫框架現(xiàn)在特別多,比如greenDAO,litepal都是各個大神封裝好的脓斩,有時候自己只知道用木西,卻不知道實現(xiàn)原理,于是自己準(zhǔn)備動手?jǐn)]一個随静。此框架是面向?qū)ο笫綌?shù)據(jù)庫框架設(shè)計

  • 對于用戶而言八千,調(diào)用一句話就可以實現(xiàn)增刪改查的代碼才是好代碼,基于這種考慮燎猛,我們的框架必不可少使用泛型恋捆、反射、注解重绷、等操作沸停,建議大家先了解一下這些java的基本操作。
  • 首先創(chuàng)建一個Bean類(模擬用戶插入數(shù)據(jù)庫的類)
//比如說User表  字段:id name password
public class User {
    private Integer id;
    private String name;
    private String password;
}
既然是創(chuàng)建表昭卓,用戶想自定義自己的字段名稱和表名愤钾,那么我們就用注解去標(biāo)志,在創(chuàng)建表或字段的時候候醒,如果有注解能颁,那么就取注解中的名稱,反之直接取bean中默認(rèn)的字段名稱倒淫。

新建表名的注解

/**
 *
 * 用來控制表名叫做什么的注解類
 */
@Target(ElementType.TYPE)//注解方法的
@Retention(RetentionPolicy.RUNTIME)//保留位置 必須運行時 執(zhí)行過程 獲取相關(guān)信息
public @interface DbTable {
    String value();
}
/**
 *
 * 用來控制字段名稱叫做什么的注解類
 */
@Target(ElementType.FIELD)//注解方法的
@Retention(RetentionPolicy.RUNTIME)//保留位置 必須運行時 執(zhí)行過程 獲取相關(guān)信息
public @interface DbField {
    String value();
}

那么我們的Bean類 如果想自定義表名伙菊,和自定義一些字段名稱,可以改成

@DbTable("tb_user")
public class User {
    @DbField("_id")
    private Integer id;
    private String name;
    private String password;
}

好了敌土,接下來镜硕,我們提供一個頂層接口類,此類的意義在于返干,給用戶提供整體功能的一個接口類 我們封裝增谦疾、刪、改犬金、查的具體實現(xiàn),用戶只需調(diào)用想用的功能,傳入一些定制化參數(shù)

/**
 * 封裝操作功能的接口類
 */

public interface IBaseDao<T> {
    long insert(T entity);

//    int delete(String where);
//
//    long update(T entity, String where);
//
//    List<T> query(String where);
//
//    List<T> query(String where, String orderBy, Integer startIndex, Integer limit);
//
//    List<T> query(String sql);

}

然后晚顷,我們則實現(xiàn)insert操作峰伙。插入操作,我們必須先自動創(chuàng)建一個表该默,并且類中持有數(shù)據(jù)庫的引用瞳氓,對數(shù)據(jù)庫操作,然后我們獲取表名栓袖,字段匣摘,因為字段是外部傳入,我們可以使用T泛型拿到裹刮,但是不靈活音榜,此處我使用了Class拿到字節(jié)碼進(jìn)行操作 更方便。

/**
 * 1.完成自動建表功能
 */

public class BaseDao<T> implements IBaseDao<T> {
    //持有數(shù)據(jù)庫的引用 對于數(shù)據(jù)庫操作
    private SQLiteDatabase sqLiteDatabase;
    //表名
    private String tableNmae;
    //持有操作數(shù)據(jù)庫所對應(yīng)的java類型
    private Class<T> entityClass;
    //標(biāo)識:用來標(biāo)識是否做過初始化操作
    private boolean isInit = false;

    //框架內(nèi)部邏輯捧弃,最好不要提供構(gòu)造方法給調(diào)用層調(diào)用
//    public BaseDao(SQLiteDatabase sqLiteDatabase, Class<T> entityClass) {
//        this.sqLiteDatabase = sqLiteDatabase;
//        this.entityClass = entityClass;
//    }
    public boolean init(SQLiteDatabase sqLiteDatabase, Class<T> entityClass) {
        this.sqLiteDatabase = sqLiteDatabase;
        this.entityClass = entityClass;
        //根據(jù)傳入的entityClass來建立表赠叼,只需建立一次
        if (!isInit) {
            isInit = true;
            //自動建表
            //取到表名 判斷表上有沒有自定義注解類名
            if (entityClass.getAnnotation(DbTable.class) == null) {
                //反射到類名
                tableNmae = entityClass.getSimpleName();
            } else {
                //取注解上的名字
                tableNmae = entityClass.getAnnotation(DbTable.class).value();
            }
            if (!sqLiteDatabase.isOpen()) {
                return false;//數(shù)據(jù)庫沒打開 初始化失敗
            }
            //執(zhí)行建表操作
            //create table if not exists tb_user(_id integer,name varchar2(20),password varchar(20))
            //單獨用個方法生成create命令
            String createTableSql = getCreateTableSql();
            sqLiteDatabase.execSQL(createTableSql);

        }

        return isInit;
    }
}


獲取到了表名,建表之前违霞,獲取傳入實體類所有成員變量類型嘴办。

    private String getCreateTableSql() {
        StringBuffer stringBuffer = new StringBuffer();
        stringBuffer.append("create table if not exists ");
        stringBuffer.append(tableNmae + "(");
        //反射得到所有的成員變量
        Field[] fields = entityClass.getDeclaredFields();
        for (Field field : fields) {
            Class type = field.getType();//拿到成員類型
            if (field.getAnnotation(DbField.class) != null) {
                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;
                }
            } else {
                if (type == String.class) {
                    stringBuffer.append(field.getName() + " TEXT,");
                } else if (type == Integer.class) {
                    stringBuffer.append(field.getName() + " INTEGER,");
                } else if (type == Long.class) {
                    stringBuffer.append(field.getName() + " BIGINT,");
                } else if (type == Double.class) {
                    stringBuffer.append(field.getName() + " DOUBLE,");
                } else if (type == byte[].class) {
                    stringBuffer.append(field.getName() + " BLOB,");
                } else {
                    //不支持的類型號
                    continue;
                }
            }
        //去掉最后一個逗號
        if (stringBuffer.charAt(stringBuffer.length() - 1) == ',') {
            stringBuffer.deleteCharAt(stringBuffer.length() - 1);
        }
        stringBuffer.append(")");
        return stringBuffer.toString();
        }
     

到此,此處我們的建表操作已經(jīng)寫好买鸽,但是如何提供給用戶使用呢涧郊,那么我們將再寫一個工廠類,用戶調(diào)用工廠類眼五,工廠類調(diào)用實現(xiàn)方法妆艘,則實現(xiàn)創(chuàng)表操作。

public class BaseDaoFactory {
    private static final BaseDaoFactory ourInstance = new BaseDaoFactory();

    public static BaseDaoFactory getOurInstance() {
        return ourInstance;
    }

    private SQLiteDatabase sqLiteDatabase;
    //定義建數(shù)據(jù)數(shù)據(jù)的路徑
    //建議寫在SD卡中 好處APP刪了 下次安裝 數(shù)據(jù)還在
    private String sqliteDatabasePath;

    private BaseDaoFactory() {
        //內(nèi)置sd卡路徑
        String sqlitePath = createSDCardOrOpenDir() + "/dao.db";
        if (sqlitePath == null) {
            //SD卡不存在
            return;
        }
        sqLiteDatabase = SQLiteDatabase.openOrCreateDatabase(sqlitePath, null);
    }

    public String createSDCardOrOpenDir() {
        if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {
            // 創(chuàng)建一個文件夾對象弹砚,賦值為外部存儲器的目錄
            File sdcardDir = Environment.getExternalStorageDirectory();
            //得到一個路徑双仍,內(nèi)容是sdcard的文件夾路徑和名字
            String path = sdcardDir.getPath() + "/dbImage";
            File newpath = new File(path);
            if (!newpath.exists()) {
                //若不存在,創(chuàng)建目錄桌吃,可以在應(yīng)用啟動的時候創(chuàng)建
                newpath.mkdirs();
            }
            return path;

        } else {
            return null;
        }

    }

    public <T> BaseDao<T> getBaseDao(Class<T> entityClass) {
        BaseDao baseDao = null;
        try {
            baseDao = BaseDao.class.newInstance();
            baseDao.init(sqLiteDatabase, entityClass);
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return baseDao;
    }

//此處測試一下 測試

   BaseDao baseDao = BaseDaoFactory.getOurInstance().getBaseDao(User.class);
        Toast.makeText(this, "執(zhí)行成功", Toast.LENGTH_SHORT);
  • CRUD操作 必不可少需要成員變量獲取字段和值等朱沃,此處反射太耗時,我們整體寫一個緩存參數(shù)茅诱,將成員變量和數(shù)據(jù)庫的字段緩存起來逗物,方便下次對對象操作可以直接從緩存里取數(shù)據(jù)
  //CacheMap  鍵值對  對應(yīng)著 字段 》成員變量
  private HashMap<String, Field> cacheMap; 

  private void initCacheMap() {
        //獲取所有列名 空表
        String sql = "select * from " + tableNmae + " limit 1,0";
        Cursor cursor = sqLiteDatabase.rawQuery(sql, null);
        String[] columnNames = cursor.getColumnNames();//獲取所有字段名字
        //獲取成員變量
        Field[] fields = entityClass.getDeclaredFields();
        for (Field field : fields) {
            field.setAccessible(true);//把字段設(shè)置可寫;
        }
        for (String columnName : columnNames) {//循環(huán)字段
            Field columField = null;
            for (Field field : fields) {//循環(huán)成員變量
                String fieldName = null;
                if (field.getAnnotation(DbField.class) != null) {
                    fieldName = field.getAnnotation(DbField.class).value();
                } else {
                    fieldName = field.getName();
                }
                if (fieldName.equals(columnName)) {//
                    columField = field;
                    break;
                }
            }
            cacheMap.put(columnName, columField);
        }

        //把字段和成員變量映射起來

    }

并且將初始化操作 放入init方法中。

  • Insert方法定義
    在頂層接口中瑟俭,定義一個insert(T entity)方法 在BaseDao去實現(xiàn)
    普通插入方法: sqLiteDatabase.insert(tableNmae,null,contentValues)
    contentValues對應(yīng)的則是插入對象的數(shù)據(jù)翎卓。
    封裝思路:第一步先從cacheMap獲取數(shù)據(jù) 并且將值傳入一個MAP,然后將MAP再封裝到ContentValues摆寄,此處之所以不直接用cacheMAp封裝到ContentValues失暴,因為后面會時常用到Map坯门。
 private Map<String, String> getValues(T entity) {
        Map<String, String> resultMap = new HashMap<>();
        //獲取傳入類的key  values
        Iterator<Field> iterator = cacheMap.values().iterator();
        while (iterator.hasNext()) {
            Field field = iterator.next();
            try {
                Object object = field.get(entity);//獲取成員變量的值
                String value = object.toString();
                if (object == null) {
                    continue;
                }
                String key = null;
                //獲取key
                if (field.getAnnotation(DbField.class)!= null) {
                    key = field.getAnnotation(DbField.class).value();
                } else {
                    key = field.getName();
                }
                if (!TextUtils.isEmpty(key) && !TextUtils.isEmpty(value)) {
                    resultMap.put(key, value);
                }
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
        return resultMap;
    }

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

    }

BaseDao實現(xiàn)類就可以

    public long insert(T entity) {
        Map<String, String> map = getValues(entity);
        ContentValues contentValues = getContentValues(map);
        long result = sqLiteDatabase.insert(tableNmae, null, contentValues);
        return result;
    }

測試:

   public void insertObject(View view) {
        BaseDao baseDao = BaseDaoFactory.getOurInstance().getBaseDao(Person.class);
        baseDao.insert(new Person("lcx",24));
        Toast.makeText(this, "執(zhí)行成功", Toast.LENGTH_SHORT).show();
    }

這是插入操作,接下來 我們可以進(jìn)行 修改+刪除操作

  • 修改
    正常修改操作:
sqLiteDatabase.update(tableNmae,contentvalues,"name=?",new String[] {"lcx"})

那么我們定義一個方法

 public long update(T entity, T where) {}

entity 傳入修改的對象
where 代表修改的條件

tatableNmae獲取得到逗扒,contentvalues也可以獲取到古戴,通過cacheMap獲取緩存的成員變量,再通過成員獲取傳入entity的值矩肩,最后封裝到ContentValues,
和insert一個道理现恼,然后具體條件,我們將定義一個內(nèi)部類黍檩,寫個構(gòu)造叉袍,傳入修改的MAp值,這樣我們就可以得到 “name=?" 和條件的值

 public class Condition {
        private String whereCause;
        private String[] whereArgs;

        public Condition(Map<String, String> whereCause) {
            ArrayList arrayList = new ArrayList();
            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.append("1=1");
            //取所有字段值
            Set keys = whereCause.keySet();
            Iterator iterator = keys.iterator();
            while (iterator.hasNext()) {
                String key = (String) iterator.next();
                String value = whereCause.get(key);
                if (value != null) {
                    stringBuilder.append(" and " + key + "=?");
                    arrayList.add(value);
                }
            }
            this.whereCause = stringBuilder.toString();
            this.whereArgs = (String[]) arrayList.toArray(new String[arrayList.size()]);
        }

        ;

最后我們的修改操作代碼 是這樣的

public long update(T entity, T where) {
//        UPDATE Person SET FirstName = 'Fred' WHERE LastName = 'Wilson'
//        sqLiteDatabase.update(tableNmae,contentvalues,"name=?",new String[] {"lcx"})
      long result = -1;
      Map map = getValues(entity);
      ContentValues contentValues = getContentValues(map);
      //定義內(nèi)部類  用來拼接修改參數(shù)及條件
      Map whereCause = getValues(where);
      Condition condition = new Condition(whereCause);
      sqLiteDatabase.update(tableNmae, contentValues, condition.whereCause, condition.whereArgs);
      return result;
  }
  • 刪除
    既然修改出來了 刪除就更簡單啦
    @Override
    public long delete(T where) {
//        sqLiteDatabase.delete(tableNmae,whrerClause,whereArgs);
        Map map = getValues(where);
        Condition condition = new Condition(map);
        long result = sqLiteDatabase.delete(tableNmae, condition.whereCause, condition.whereArgs);
        return result;

  • 查詢
    查詢的話 相比較刪除和修改稍微復(fù)雜一些刽酱,因為涉及查詢到的數(shù)據(jù)動態(tài)轉(zhuǎn)化集合對象喳逛。
    正常查詢
 sqLiteDatabase.query(tableName,null,"id=?",new String[],null,null,orderBy,"1,5");

封裝:

 @Override
    public List<T> query(T where) {
        return query(where, null, null, null);
    }

    @Override
    public List<T> query(T where, String orderBy, Integer startIndex, Integer limit) {
        //        sqLiteDatabase.query(tableName,null,"id=?",new String[],null,null,orderBy,"1,5");
        Map map = getValues(where);
        String limitString = null;
        if (startIndex != null && limit != null) {
            limitString = startIndex + " , " + limit;
        }
        Condition condition = new Condition(map);

        Cursor cursor = sqLiteDatabase.query(tableNmae, null, condition.whereCause, condition.whereArgs, null, null, orderBy, limitString);
        //定義一個用來解析游標(biāo)的方法
        List<T> result = getResult(cursor, where);
        return result;
    }

主要涉及到對象轉(zhuǎn)換。
循環(huán)查詢出的游標(biāo)肛跌,實例化傳入對象艺配,然后獲取緩存的所有Map 字段-成員變量,然后循環(huán)衍慎,得到數(shù)據(jù)庫字段转唉,獲取字段在游標(biāo)位置,獲取成員變量稳捆,通過成員變量獲取屬性赠法,判斷并進(jìn)入對應(yīng)各個屬性,動態(tài)設(shè)置Field的值乔夯。最后將對象添加集合 并返回集合數(shù)據(jù)

 //obj是用來表示User類的結(jié)構(gòu)
    private List<T> getResult(Cursor cursor, T obj) {
        ArrayList list = new ArrayList();
        Object item = null;
        while (cursor.moveToNext()) {
            try {
                item = obj.getClass().newInstance();//new User();
                Iterator iterator = cacheMap.entrySet().iterator();//字段-成員變量
                while (iterator.hasNext()) {
                    Map.Entry entry = (Map.Entry) iterator.next();
                    //取列名
                    String columnName = (String) entry.getKey();
                    //然后以列名拿到列名在游標(biāo)中的位置
                    Integer columnIndex = cursor.getColumnIndex(columnName);

                    Field field = (Field) entry.getValue();
                    Class type = field.getType();

                    if (columnIndex != -1) {
                        if (type == String.class) {
                            field.set(item, cursor.getString(columnIndex));//set(Object obj, Object value) : 向obj對象的這個Field設(shè)置新值value
                        } else if (type == Double.class) {
                            field.set(item, cursor.getDouble(columnIndex));
                        } else if (type == Integer.class) {
                            field.set(item, cursor.getInt(columnIndex));
                        } else if (type == Long.class) {
                            field.set(item, cursor.getLong(columnIndex));
                        } else if (type == byte[].class) {
                            field.set(item, cursor.getBlob(columnIndex));
                        } else {
                            continue;
                        }
                    }
                }
                list.add(item);
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
        cursor.close();
        return list;
    }

此處砖织,CURD 雛形已成,擴(kuò)展一下末荐,將工廠類生產(chǎn)BaseDao的擴(kuò)展下侧纯,傳入倆泛型,M代表傳入的User對象 T代表BaseDao甲脏,為了更靈活調(diào)用眶熬。

  public  <T extends BaseDao<M>,M> T  getBaseDao(Class<T> daoClass,Class<M> entityClass){
        BaseDao baseDao=null;
        try {
            baseDao=daoClass.newInstance();
            baseDao.init(sqLiteDatabase,entityClass);
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        return (T)baseDao;
    }

記得測試下


public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        verifyStoragePermissions(this);
    }

    public void insertObject(View view) {
        IBaseDao baseDao = BaseDaoFactory.getOurInstance().getBaseDao(BaseDaoNewImpl.class, User.class);
        baseDao.insert(new User(6, "abcd", "123"));
        Toast.makeText(this, "執(zhí)行成功!", Toast.LENGTH_SHORT).show();
    }


    private static final int REQUEST_EXTERNAL_STORAGE = 1;
    private static String[] PERMISSIONS_STORAGE = {
            "android.permission.READ_EXTERNAL_STORAGE",
            "android.permission.WRITE_EXTERNAL_STORAGE"};


    public static void verifyStoragePermissions(Activity activity) {

        try {
            //檢測是否有寫的權(quán)限
            int permission = ActivityCompat.checkSelfPermission(activity,
                    "android.permission.WRITE_EXTERNAL_STORAGE");
            if (permission != PackageManager.PERMISSION_GRANTED) {
                // 沒有寫的權(quán)限,去申請寫的權(quán)限块请,會彈出對話框
                ActivityCompat.requestPermissions(activity, PERMISSIONS_STORAGE, REQUEST_EXTERNAL_STORAGE);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public void updateObject(View view) {
        BaseDaoNewImpl baseDao = BaseDaoFactory.getOurInstance().getBaseDao(BaseDaoNewImpl.class, User.class);
        //update tb_user where name='jett' set password='1111'
        User user = new User();
        user.setName("abcd");
        User where = new User();
        where.setId(6);
        baseDao.update(user, where);
        Toast.makeText(this, "執(zhí)行成功!", Toast.LENGTH_SHORT).show();
    }

    public void deleteObject(View view) {
        BaseDao baseDao = BaseDaoFactory.getOurInstance().getBaseDao(BaseDaoNewImpl.class, User.class);
        User where = new User();
        where.setName("abcd");
        where.setId(6);
        baseDao.delete(where);
    }

    public void queryObject(View view) {
        BaseDaoNewImpl baseDao = BaseDaoFactory.getOurInstance().getBaseDao(BaseDaoNewImpl.class, User.class);
        User where = new User();
        where.setName("abcd");
        List<User> list = baseDao.query(where);
        Log.i("jett", "listsize=" + list.size());
        for (int i = 0; i < list.size(); i++) {
            System.out.println(list.get(i) + " i=" + i);
        }
    }
}

數(shù)據(jù)庫Demo:鏈接:https://pan.baidu.com/s/1SHTcCgzXpFkNd-ZHRrmZgg 密碼:hohw

  • 多用戶分庫

接下來娜氏,我們設(shè)計一個多用戶分庫功能。就是說每一個用戶數(shù)據(jù)庫都是獨立的墩新,這些大廠設(shè)計都是這樣的贸弥,每一個用戶對應(yīng)不同數(shù)據(jù)庫。

首先 為了方便BaseDao不生成多個實例海渊,我們把原本生成數(shù)據(jù)庫實例的方法改下

////設(shè)計一個數(shù)據(jù)庫連接池                                                                                       
private Map<String, BaseDao> hashMap = Collections.synchronizedMap(new HashMap<String, BaseDao>());  

 public <T extends BaseDao<M>, M> T getBaseDao(Class<T> daoClass, Class<M> entityClass) {      
     BaseDao baseDao = null;                                                                   
     try {                                                                                     
         if (hashMap.get(daoClass.getSimpleName()) != null) {                                  
             return (T) hashMap.get(daoClass.getSimpleName());                                 
         }                                                                                     
         baseDao = BaseDao.class.newInstance();                                                
         baseDao.init(sqLiteDatabase, entityClass);                                            
         hashMap.put(daoClass.getSimpleName(), baseDao);                                       
     } catch (InstantiationException e) {                                                      
         e.printStackTrace();                                                                  
     } catch (IllegalAccessException e) {                                                      
         e.printStackTrace();                                                                  
     }                                                                                         
     return (T) baseDao;                                                                       
 }                                                                                             

分庫的實現(xiàn)步驟

  • 獲取當(dāng)前登錄用戶 以及重寫一個插入方法(此方法可在新用戶登錄時候調(diào)用 把其余用戶狀態(tài)設(shè)置離線狀態(tài) 新用戶為在線狀態(tài))
public class UserDao extends BaseDao<User> {
    @Override
    public long insert(User entity) {
        //查詢表中所有的用戶記錄
        List<User> list = query(new User());
        User where = null;
        for (User user : list) {
            where = new User();
            where.setId(user.getId());
            user.setStatus(0);
            Log.i("lcx", "用戶" + user.getName() + "更改為未登錄狀態(tài)");
            update(user, where);
        }
        Log.i("lcx", "用戶" + entity.getName() + "登錄");
        entity.setStatus(1);
        return super.insert(entity);
    }

    /**
     * 得到當(dāng)前的登錄用戶
     */
    public User getCurrLoginUser() {
        User user = new User();
        user.setStatus(1);
        List<User> list = query(user);
        if (list.size() > 0) {
            return list.get(0);
        }
        return null;
    }
}
  • 定義一個枚舉類 用來產(chǎn)生當(dāng)前用戶的數(shù)據(jù)庫地址
用于產(chǎn)生私有數(shù)據(jù)庫在存放位置
 /**
 * 用于產(chǎn)生私有數(shù)據(jù)庫在存放位置
 */
public enum PrivateDataBaseEnums {
    database("");
    private String value;

    PrivateDataBaseEnums(String value) {

    }

    //用于產(chǎn)生路徑
    public String getValue() {
        UserDao userDao = BaseDaoFactory.getOurInstance().getBaseDao(UserDao.class, User.class);
        if (userDao != null) {
            User currUser = userDao.getCurrLoginUser();
            if (currUser != null) {
                File sdcardDir = Environment.getExternalStorageDirectory();
                //得到一個路徑绵疲,內(nèi)容是sdcard的文件夾路徑和名字
                String path = sdcardDir.getPath() + "/dbImage";
                File file = new File(path);
//                File file = new File("/data/data/com.example.a48608.ls4_databaseframework_20180307");
                if (!file.exists()) {
                    file.mkdirs();
                }
                ///data/data/com.example.a48608.ls4_databaseframework_20180307/n0003_login.db
                return file.getAbsolutePath() + "/" + currUser.getId() + "_login.db";
            }
        }
        return null;
    }
}
  • 定義一個工廠類 生產(chǎn)具體用戶的數(shù)據(jù)庫信息
    //這個用來生成不同對象的數(shù)據(jù)庫地址
    public <T extends BaseDao<M>, M> T getSubDao(Class<T> daoClass, Class<M> entityClass) {
        BaseDao baseDao=null;
        if(hashMap.get(PrivateDataBaseEnums.database.getValue())!=null){
            return (T) hashMap.get(PrivateDataBaseEnums.database.getValue());
        }
        Log.i("jett","生成數(shù)據(jù)庫文件的位置:"+PrivateDataBaseEnums.database.getValue());
        subSqliteDatabase=SQLiteDatabase.openOrCreateDatabase(PrivateDataBaseEnums.database.getValue(),null);
        try {
            baseDao=daoClass.newInstance();
            baseDao.init(subSqliteDatabase,entityClass);
            hashMap.put(PrivateDataBaseEnums.database.getValue(),baseDao);
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }

        return (T) baseDao;
    }

測試

 BaseDao userDao;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        userDao = BaseDaoFactory.getOurInstance().getBaseDao(UserDao.class, User.class);
    }

/*模擬用戶登錄的  此處的insert是UserDao的insert  就是說把當(dāng)前用戶User為在線狀態(tài) 其余為離線狀態(tài)**/
   public void clickLogin(View view) {
        //服務(wù)器傳回的信息
        User user = new User();
        user.setName("張三" + (++i));
        user.setPassword("123456");
        user.setId("N00" + i);
        //數(shù)據(jù)插入
        userDao.insert(user);
        Toast.makeText(this, "執(zhí)行成功!", Toast.LENGTH_SHORT).show();

    }
/*執(zhí)行這一步之前 我們已經(jīng)知道了 當(dāng)前用戶哲鸳,也已經(jīng)實例化了UserDAO,那么根據(jù)這兩點 執(zhí)行枚舉方法 得到當(dāng)前用戶數(shù)據(jù)庫地址,然后打開或者創(chuàng)建當(dāng)前用戶數(shù)據(jù)庫最岗, 并且初始化帕胆。  接下來進(jìn)行一個新增動作  就可以查看當(dāng)前用戶的數(shù)據(jù)庫插入的表數(shù)據(jù)*/
 public void clickSubInsert(View view) {
        Photo photo = new Photo();
        photo.setPath("data/data/my.jpg");
        photo.setTime(new Date().toString());
        PhotoDao photoDao =  BaseDaoSubFactory.getOurInstance().getSubDao(PhotoDao.class, Photo.class);
        photoDao.insert(photo);
        Toast.makeText(this, "執(zhí)行成功!", Toast.LENGTH_SHORT).show();
    }
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市般渡,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌芙盘,老刑警劉巖驯用,帶你破解...
    沈念sama閱讀 216,496評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)长酗,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,407評論 3 392
  • 文/潘曉璐 我一進(jìn)店門量窘,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人涡驮,你說我怎么就攤上這事。” “怎么了挖腰?”我有些...
    開封第一講書人閱讀 162,632評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長练湿。 經(jīng)常有香客問我猴仑,道長,這世上最難降的妖魔是什么肥哎? 我笑而不...
    開封第一講書人閱讀 58,180評論 1 292
  • 正文 為了忘掉前任辽俗,我火速辦了婚禮,結(jié)果婚禮上篡诽,老公的妹妹穿的比我還像新娘崖飘。我一直安慰自己,他們只是感情好杈女,可當(dāng)我...
    茶點故事閱讀 67,198評論 6 388
  • 文/花漫 我一把揭開白布朱浴。 她就那樣靜靜地躺著,像睡著了一般碧信。 火紅的嫁衣襯著肌膚如雪赊琳。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,165評論 1 299
  • 那天砰碴,我揣著相機(jī)與錄音躏筏,去河邊找鬼。 笑死呈枉,一個胖子當(dāng)著我的面吹牛趁尼,可吹牛的內(nèi)容都是我干的埃碱。 我是一名探鬼主播,決...
    沈念sama閱讀 40,052評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼酥泞,長吁一口氣:“原來是場噩夢啊……” “哼砚殿!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起芝囤,我...
    開封第一講書人閱讀 38,910評論 0 274
  • 序言:老撾萬榮一對情侶失蹤似炎,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后悯姊,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體羡藐,經(jīng)...
    沈念sama閱讀 45,324評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,542評論 2 332
  • 正文 我和宋清朗相戀三年悯许,在試婚紗的時候發(fā)現(xiàn)自己被綠了仆嗦。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,711評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡先壕,死狀恐怖瘩扼,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情垃僚,我是刑警寧澤集绰,帶...
    沈念sama閱讀 35,424評論 5 343
  • 正文 年R本政府宣布,位于F島的核電站冈在,受9級特大地震影響倒慧,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜包券,卻給世界環(huán)境...
    茶點故事閱讀 41,017評論 3 326
  • 文/蒙蒙 一纫谅、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧溅固,春花似錦付秕、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,668評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至亮元,卻和暖如春猛计,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背爆捞。 一陣腳步聲響...
    開封第一講書人閱讀 32,823評論 1 269
  • 我被黑心中介騙來泰國打工奉瘤, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人煮甥。 一個月前我還...
    沈念sama閱讀 47,722評論 2 368
  • 正文 我出身青樓盗温,卻偏偏與公主長得像藕赞,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子卖局,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,611評論 2 353

推薦閱讀更多精彩內(nèi)容