Android greendao实践教程

1.引言

目前做的一款app,全部都是基于本地数据库,于是采用第三方数据库greendao。因为之前对greendao没有深层次的研究,都是照着博客上学的,没想到被博客坑了。网上搜索的千篇一律,都是照着官网上翻译的,有很多需要着重注意的地方都被忽略了,导致我在使用的时候遇到大量的坑。因此我单独的写了一个简单的项目来验证我踩过的坑。但是有些情况却没有出现,不得其解。
官网的地址

2.正文

2.1 @ToOne

一节课一个学生对应一个老师,所以学生:老师=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;//身份证号码

}

插入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);

当然通过student.setTeacher();来进行级联插入也是可以的。亲测。

注意:load()和loadDeep()

load()查询。不会把外键的信息查询出来。但是假如人为的调用setTeacher,之后再load()查询,就会把Teacher的信息也查找出来

loadDeep:会将所有的信息都查询出来,包括外键。

2.2 外键必须是关联表的主键。

我想把身份证id作为student表中的外键。但是实际make project的时候报错。
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;//身份证号码
    public String getIdCard() {
        return this.idCard;
    }
}
image.png

2.3 @Unite的使用。

项目中,我本地表都是已经存在的不是自己建立的。或许就是因为自己建立的而不是生成的导致。@Unique没得反应,md。

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

    @Unique
    private String idCard;//身份证号码

这样做就行了。

2.4 将生成的db文件放到指定的文件路径下。网上有现成的代码。在此把项目中的粘贴下。

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

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

    /**
     * 获得数据库路径,如果不存在,则创建对象
     * @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卡不存在,请加载SD卡");
            return null;
        } else {// 如果存在
            // 获取sd卡路径
            String dbDir = android.os.Environment.getExternalStorageDirectory().getAbsolutePath();
            dbDir += "/mlapp";// 数据库所在目录
            String dbPath = dbDir+"/"+dbName;// 数据库路径
            // 判断目录是否存在,不存在则创建该目录
            File dirFile = new File(dbDir);
            if (!dirFile.exists())
                dirFile.mkdirs();

            // 数据库文件是否创建成功
            boolean isFileCreateSuccess = false;
            // 判断文件是否存在,不存在则创建该文件
            File dbFile = new File(dbPath);
            if (!dbFile.exists()) {
                try {
                    isFileCreateSuccess = dbFile.createNewFile();// 创建文件
                } catch (IOException e) {
                    e.printStackTrace();
                }
            } else {
                isFileCreateSuccess = true;
            }
            // 返回数据库文件对象
            if (isFileCreateSuccess) {
                return dbFile;
            } else {
                return super.getDatabasePath(dbName);
            }
        }
    }

    /**
     * 重载这个方法,是用来打开SD卡上的数据库的,android 2.3及以下会调用这个方法。
     *
     * @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会调用此方法获取数据库。
     *
     * @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;
    }
}

然后通过如下的方法得到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);//写入流
            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);
            }
            //写完后刷新
            outputStream.flush();
            ToastUtil.showLong(XinYiApplication.instance,"复制成功");
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            try {
                if (inputStream != null) {//关闭流,释放资源
                    inputStream.close();
                }
                if(outputStream!=null){
                    outputStream.close();
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

2.5 建立索引(或者设置唯一属性)

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


    private String idCard;//身份证号码
}

idCard属性被插入一样的值 就会报错。

2.6 @ToMany

一个老师对应多个学生即1:N。

@ToMany 有三种情况,根据需要选用不同的情况。

2.61 referencedJoinProperty 关联

@Entity
public class Teacher implements Serializable {
    @Id
    private Long id;//主键
    private String name;
    @Unique
    private Long idCard;//身份证号码
    
    //与上面的属性没得关系。referencedJoinProperty 与Student里面的idCard 相关。且是主键关联
    @ToMany(referencedJoinProperty = "idCard")
    private List<Student> students;
}

student表:

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

   //Teacher的主键(必须是主键,)
   public Long idCard;
   
}

总结:A:B=1:N 假如是通过referencedJoinProperty 关联的话,B里面有A的主键,属性不同没得关系..A里面的referencedJoinProperty 指向B中的A的主键表示的属性。。例如上面的B_idCard.

2.62 joinProperties 关联

teacher类的定义:

@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类的定义:

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

joinProperties 属性将Teacher 里面的独一的非主键,当做Student的外键。referencedJoinProperty 关联 必须是主键作为Student的外键。

@ToMany注意:

通过查找teacher,能获得List<Student>。实际上当你查找得到一个Teacher 对象的时候,其实List<Student>这个时候为空的。只有当你调用getStudents()的时候才会进行查找。。这个与@ToOne的差别。

greendao的总结就到这里,以后看博客真的要先看英文文档。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,542评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,596评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,021评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,682评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,792评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,985评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,107评论 3 410
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,845评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,299评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,612评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,747评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,441评论 4 333
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,072评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,828评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,069评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,545评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,658评论 2 350

推荐阅读更多精彩内容

  • 1. Java基础部分 基础部分的顺序:基本语法,类相关的语法,内部类的语法,继承相关的语法,异常的语法,线程的语...
    子非鱼_t_阅读 31,602评论 18 399
  • 大神们都说GreenDao性能最好,使用方便,最近在做一个项目,刚好用到操作本地数据库,so机缘巧合,开始学习Gr...
    冯奕欢阅读 10,743评论 2 7
  • 一. Java基础部分.................................................
    wy_sure阅读 3,805评论 0 11
  • .数据库 数据库的发展: 文件系统(使用磁盘文件来存储数据)=>第一代数据库(出现了网状模型,层次模型的数据库)=...
    小Q逛逛阅读 960评论 0 2
  • 思念总是如影随形。 感到美好的天气,路过山丘湖泊,好希望和你一起去静静享受那样的美景。 尝到美味的食物,经过勾引味...
    汪汪的爱阅读 506评论 0 0