Android greendao實(shí)踐教程

1.引言

目前做的一款app坠宴,全部都是基于本地?cái)?shù)據(jù)庫(kù)粉私,于是采用第三方數(shù)據(jù)庫(kù)greendao。因?yàn)橹皩?duì)greendao沒(méi)有深層次的研究壁顶,都是照著博客上學(xué)的珠洗,沒(méi)想到被博客坑了。網(wǎng)上搜索的千篇一律若专,都是照著官網(wǎng)上翻譯的许蓖,有很多需要著重注意的地方都被忽略了,導(dǎo)致我在使用的時(shí)候遇到大量的坑调衰。因此我單獨(dú)的寫(xiě)了一個(gè)簡(jiǎn)單的項(xiàng)目來(lái)驗(yàn)證我踩過(guò)的坑膊爪。但是有些情況卻沒(méi)有出現(xiàn),不得其解嚎莉。
官網(wǎng)的地址

2.正文

2.1 @ToOne

一節(jié)課一個(gè)學(xué)生對(duì)應(yīng)一個(gè)老師米酬,所以學(xué)生:老師=1:1

@Entity
public class Student {
    @Id
    private Long id;//主鍵

    private Long tid;//外鍵
    @ToOne(joinProperty = "tid")
    private Teacher teacher;
    
}

teacher:

@Entity
public class Teacher {
    @Id
    private Long id;//主鍵
    private Long idCard;//身份證號(hào)碼

}

插入student和techaer:

                DaoSession daoSession = daoMaster.newSession();
                StudentDao studentDao = daoSession.getStudentDao();
                TeacherDao teacherDao = daoSession.getTeacherDao();
                Student student=new Student();
                Teacher teacher=new Teacher();
                teacher.setIdCard(333L);
                Long key=teacherDao.insert(teacher);
                student.setTid(key);
                studentDao.insert(student);

當(dāng)然通過(guò)student.setTeacher();來(lái)進(jìn)行級(jí)聯(lián)插入也是可以的。親測(cè)趋箩。

注意:load()和loadDeep()

load()查詢(xún)赃额。不會(huì)把外鍵的信息查詢(xún)出來(lái)。但是假如人為的調(diào)用setTeacher,之后再load()查詢(xún)叫确,就會(huì)把Teacher的信息也查找出來(lái)

loadDeep:會(huì)將所有的信息都查詢(xún)出來(lái)跳芳,包括外鍵。

2.2 外鍵必須是關(guān)聯(lián)表的主鍵竹勉。

我想把身份證id作為student表中的外鍵飞盆。但是實(shí)際make project的時(shí)候報(bào)錯(cuò)。
student表:

@Entity
public class Student {
    @Id
    private Long id;//主鍵

    private String teacherIdCard;//外鍵
    @ToOne(joinProperty = "teacherIdCard")
    private Teacher teacher;
}

teacher表:

@Entity
public class Teacher {
    @Id
    private Long id;//主鍵
    private String idCard;//身份證號(hào)碼
    public String getIdCard() {
        return this.idCard;
    }
}
image.png

2.3 @Unite的使用饶米。

項(xiàng)目中桨啃,我本地表都是已經(jīng)存在的不是自己建立的∶适洌或許就是因?yàn)樽约航⒌亩皇巧傻膶?dǎo)致照瘾。@Unique沒(méi)得反應(yīng),md丧慈。

@Entity(createInDb = false)
public class Teacher implements Serializable{
    @Id
    @Property(nameInDb = "tid")
    private Long tid;//主鍵

    @Unique
    private String idCard;//身份證號(hào)碼

這樣做就行了析命。

2.4 將生成的db文件放到指定的文件路徑下主卫。網(wǎng)上有現(xiàn)成的代碼。在此把項(xiàng)目中的粘貼下鹃愤。

public class GreenDaoContext extends ContextWrapper {
    private String currentUserId;
    private Context mContext;

    public GreenDaoContext() {
        super(XinYiApplication.instance);
        this.mContext = XinYiApplication.instance;
    }

    /**
     * 獲得數(shù)據(jù)庫(kù)路徑芒涡,如果不存在浅缸,則創(chuàng)建對(duì)象
     * @param dbName
     */
    @Override
    public File getDatabasePath(String dbName) {
        // 判斷是否存在sd卡
        boolean sdExist = android.os.Environment.MEDIA_MOUNTED.equals(android.os.Environment.getExternalStorageState());
        if (!sdExist) {// 如果不存在,
            Log.e("SD卡管理:", "SD卡不存在栏渺,請(qǐng)加載SD卡");
            return null;
        } else {// 如果存在
            // 獲取sd卡路徑
            String dbDir = android.os.Environment.getExternalStorageDirectory().getAbsolutePath();
            dbDir += "/mlapp";// 數(shù)據(jù)庫(kù)所在目錄
            String dbPath = dbDir+"/"+dbName;// 數(shù)據(jù)庫(kù)路徑
            // 判斷目錄是否存在怔接,不存在則創(chuàng)建該目錄
            File dirFile = new File(dbDir);
            if (!dirFile.exists())
                dirFile.mkdirs();

            // 數(shù)據(jù)庫(kù)文件是否創(chuàng)建成功
            boolean isFileCreateSuccess = false;
            // 判斷文件是否存在,不存在則創(chuàng)建該文件
            File dbFile = new File(dbPath);
            if (!dbFile.exists()) {
                try {
                    isFileCreateSuccess = dbFile.createNewFile();// 創(chuàng)建文件
                } catch (IOException e) {
                    e.printStackTrace();
                }
            } else {
                isFileCreateSuccess = true;
            }
            // 返回?cái)?shù)據(jù)庫(kù)文件對(duì)象
            if (isFileCreateSuccess) {
                return dbFile;
            } else {
                return super.getDatabasePath(dbName);
            }
        }
    }

    /**
     * 重載這個(gè)方法凹耙,是用來(lái)打開(kāi)SD卡上的數(shù)據(jù)庫(kù)的姿现,android 2.3及以下會(huì)調(diào)用這個(gè)方法。
     *
     * @param name
     * @param mode
     * @param factory
     */
    @Override
    public SQLiteDatabase openOrCreateDatabase(String name, int mode,
                                               SQLiteDatabase.CursorFactory factory) {
        SQLiteDatabase result = SQLiteDatabase.openOrCreateDatabase(getDatabasePath(name), factory);
        return result;
    }

    /**
     * Android 4.0會(huì)調(diào)用此方法獲取數(shù)據(jù)庫(kù)肖抱。
     *
     * @param name
     * @param mode
     * @param factory
     * @param errorHandler
     * @see android.content.ContextWrapper#openOrCreateDatabase(java.lang.String, int,
     * android.database.sqlite.SQLiteDatabase.CursorFactory,
     * android.database.DatabaseErrorHandler)
     */
    @Override
    public SQLiteDatabase openOrCreateDatabase(String name, int mode, SQLiteDatabase.CursorFactory factory,
                                               DatabaseErrorHandler errorHandler) {
        SQLiteDatabase result = SQLiteDatabase.openOrCreateDatabase(getDatabasePath(name), factory);
        return result;
    }
}

然后通過(guò)如下的方法得到daoSession

DaoMaster.DevOpenHelper helper = new DaoMaster.DevOpenHelper(new GreenDaoContext(), "POSTerminal.db", null);
SQLiteDatabase db = helper.getWritableDatabase();
DaoMaster daoMaster = new DaoMaster(db);
DaoSession daoSession = daoMaster.newSession();

2.4 將db文件拷貝到指定文件夾下

public class CopyDBUtil {

    public static void copyRawDBToApkDb() {

        OutputStream outputStream=null;
        InputStream inputStream=null;
        String apkDbPath = android.os.Environment.getExternalStorageDirectory().getAbsolutePath() + "/POSTerminal";
        String dbName = "/POSTerminal.db";
        boolean b = false;
        File f = new File(apkDbPath);
        if (!f.exists()) {
            f.mkdirs();
        }

        File dbFile = new File(apkDbPath + dbName);
        if (dbFile.exists()) {
            dbFile.delete();
        }
        try {
            dbFile.createNewFile();
            outputStream = new FileOutputStream(dbFile);//寫(xiě)入流
            inputStream = new FileInputStream(new File(android.os.Environment.getExternalStorageDirectory().getAbsolutePath() + "/mlapp/POSTerminal.db"));
            byte[] bytes = new byte[1024];
            int length;
            while ((length = inputStream.read(bytes)) > 0) {
                outputStream.write(bytes, 0, length);
            }
            //寫(xiě)完后刷新
            outputStream.flush();
            ToastUtil.showLong(XinYiApplication.instance,"復(fù)制成功");
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                if (inputStream != null) {//關(guān)閉流备典,釋放資源
                    inputStream.close();
                }
                if(outputStream!=null){
                    outputStream.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

2.5 建立索引(或者設(shè)置唯一屬性)

@Entity( indexes = {
        @Index(value = "idCard", unique = true)
})
public class Teacher implements Serializable{
    @Id
    @Property(nameInDb = "tid")
    private Long tid;//主鍵


    private String idCard;//身份證號(hào)碼
}

idCard屬性被插入一樣的值 就會(huì)報(bào)錯(cuò)。

2.6 @ToMany

一個(gè)老師對(duì)應(yīng)多個(gè)學(xué)生即1:N意述。

@ToMany 有三種情況提佣,根據(jù)需要選用不同的情況。

2.61 referencedJoinProperty 關(guān)聯(lián)

@Entity
public class Teacher implements Serializable {
    @Id
    private Long id;//主鍵
    private String name;
    @Unique
    private Long idCard;//身份證號(hào)碼
    
    //與上面的屬性沒(méi)得關(guān)系荤崇。referencedJoinProperty 與Student里面的idCard 相關(guān)拌屏。且是主鍵關(guān)聯(lián)
    @ToMany(referencedJoinProperty = "idCard")
    private List<Student> students;
}

student表:

@Entity
public class Student {
   @Id
   public Long id;
   private String name;

   //Teacher的主鍵(必須是主鍵,)
   public Long idCard;
   
}

總結(jié):A:B=1:N 假如是通過(guò)referencedJoinProperty 關(guān)聯(lián)的話(huà)天试,B里面有A的主鍵,屬性不同沒(méi)得關(guān)系..A里面的referencedJoinProperty 指向B中的A的主鍵表示的屬性槐壳。。例如上面的B_idCard.

2.62 joinProperties 關(guān)聯(lián)

teacher類(lèi)的定義:

@Entity
public class Teacher  {
    @Id
    private Long id;
    private String teacherName;

    //一下的是一體的
    @NotNull
    private Long tidCard;
    @ToMany(joinProperties = {
            @JoinProperty(name = "tidCard", referencedName = "tidCard")
    })
    private List<Student> students;

student類(lèi)的定義:

@Entity
public class Student {
    @Id
    private Long id;
    @NotNull
    private Long tidCard;

joinProperties 屬性將Teacher 里面的獨(dú)一的非主鍵喜每,當(dāng)做Student的外鍵。referencedJoinProperty 關(guān)聯(lián) 必須是主鍵作為Student的外鍵雳攘。

@ToMany注意:

通過(guò)查找teacher带兜,能獲得List<Student>。實(shí)際上當(dāng)你查找得到一個(gè)Teacher 對(duì)象的時(shí)候吨灭,其實(shí)List<Student>這個(gè)時(shí)候?yàn)榭盏母照铡V挥挟?dāng)你調(diào)用getStudents()的時(shí)候才會(huì)進(jìn)行查找。喧兄。這個(gè)與@ToOne的差別无畔。

greendao的總結(jié)就到這里,以后看博客真的要先看英文文檔吠冤。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末浑彰,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子拯辙,更是在濱河造成了極大的恐慌郭变,老刑警劉巖颜价,帶你破解...
    沈念sama閱讀 221,820評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異诉濒,居然都是意外死亡周伦,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,648評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén)未荒,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)专挪,“玉大人,你說(shuō)我怎么就攤上這事片排≌唬” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,324評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵划纽,是天一觀的道長(zhǎng)脆侮。 經(jīng)常有香客問(wèn)我,道長(zhǎng)勇劣,這世上最難降的妖魔是什么靖避? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,714評(píng)論 1 297
  • 正文 為了忘掉前任,我火速辦了婚禮比默,結(jié)果婚禮上幻捏,老公的妹妹穿的比我還像新娘。我一直安慰自己命咐,他們只是感情好篡九,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,724評(píng)論 6 397
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著醋奠,像睡著了一般榛臼。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上窜司,一...
    開(kāi)封第一講書(shū)人閱讀 52,328評(píng)論 1 310
  • 那天沛善,我揣著相機(jī)與錄音,去河邊找鬼塞祈。 笑死金刁,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的议薪。 我是一名探鬼主播尤蛮,決...
    沈念sama閱讀 40,897評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼斯议!你這毒婦竟也來(lái)了产捞?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,804評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤捅位,失蹤者是張志新(化名)和其女友劉穎轧葛,沒(méi)想到半個(gè)月后搂抒,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,345評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡尿扯,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,431評(píng)論 3 340
  • 正文 我和宋清朗相戀三年求晶,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片衷笋。...
    茶點(diǎn)故事閱讀 40,561評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡芳杏,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出辟宗,到底是詐尸還是另有隱情爵赵,我是刑警寧澤,帶...
    沈念sama閱讀 36,238評(píng)論 5 350
  • 正文 年R本政府宣布泊脐,位于F島的核電站空幻,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏容客。R本人自食惡果不足惜秕铛,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,928評(píng)論 3 334
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望缩挑。 院中可真熱鬧但两,春花似錦、人聲如沸供置。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,417評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)芥丧。三九已至紧阔,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間续担,已是汗流浹背寓辱。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,528評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留赤拒,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,983評(píng)論 3 376
  • 正文 我出身青樓诱鞠,卻偏偏與公主長(zhǎng)得像挎挖,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子航夺,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,573評(píng)論 2 359

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

  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語(yǔ)法蕉朵,類(lèi)相關(guān)的語(yǔ)法,內(nèi)部類(lèi)的語(yǔ)法阳掐,繼承相關(guān)的語(yǔ)法始衅,異常的語(yǔ)法冷蚂,線(xiàn)程的語(yǔ)...
    子非魚(yú)_t_閱讀 31,664評(píng)論 18 399
  • 大神們都說(shuō)GreenDao性能最好,使用方便汛闸,最近在做一個(gè)項(xiàng)目蝙茶,剛好用到操作本地?cái)?shù)據(jù)庫(kù),so機(jī)緣巧合诸老,開(kāi)始學(xué)習(xí)Gr...
    馮奕歡閱讀 10,751評(píng)論 2 7
  • 一. Java基礎(chǔ)部分.................................................
    wy_sure閱讀 3,814評(píng)論 0 11
  • .數(shù)據(jù)庫(kù) 數(shù)據(jù)庫(kù)的發(fā)展: 文件系統(tǒng)(使用磁盤(pán)文件來(lái)存儲(chǔ)數(shù)據(jù))=>第一代數(shù)據(jù)庫(kù)(出現(xiàn)了網(wǎng)狀模型,層次模型的數(shù)據(jù)庫(kù))=...
    小Q逛逛閱讀 983評(píng)論 0 2
  • 思念總是如影隨形隆夯。 感到美好的天氣,路過(guò)山丘湖泊别伏,好希望和你一起去靜靜享受那樣的美景蹄衷。 嘗到美味的食物,經(jīng)過(guò)勾引味...
    汪汪的愛(ài)閱讀 509評(píng)論 0 0