Android GreenDao3.2表关联及缓存相关

最近项目中 使用GreenDao数据库 遇到了以前没有踩过的坑:表的一对一 一对多关联以及缓存。

      sqlite数据库是没有缓存一说的 但是greenDao貌似是有滴 今天捋一捋权当备忘。

      基础集成的部分及注解解释部分 直接推荐一片文章就不赘述了。【戳我】

      所谓一对一:就是目标实体只对应一个源实体 我们只要操作目标实体就能获得相应的唯一源实体信息 目标与源的信息关联由greenDao去做了处理

     所谓一对多:就是目标实体对应多个源实体 我们只要操作目标实体就能获得相应的多个源实体信息 目标与源的信息关联由greenDao去做了处理

 场景描述:

        数据库中有Teacher表一个,如下:

比较简单只有主键id和name两个属性且name属性唯一

@Entity
public class Teacher {
    @Id(autoincrement = true)
    private Long id;

    @NotNull
    @Unique
    private String name;

... ...

}

  那么随着业务的发展 要给老师们配备女朋友 稳定工作^_^ 在建GirlFriend表一个,如下:

     很简单只有主键id和name两个属性,

@Entity
public class GirlFriend {
    @Id(autoincrement = true)
    private Long id;

    private String name;
          ... ...
}

但是一个老师只能有一个女朋友呦 就形成了一对一的关系了

          这个时候就该我们的@ToOne标记出场了给谁标记 怎么去标呢? 这里主要是对老师进行操作 那么老师就是目标实体

          女朋友就是源实体 让目标实体去关联源实体 我们给目标实体去添加@ToOne标记就好了 修改下目标实体如下:

@Entity
public class Teacher {
    @Id(autoincrement = true)
    private Long id;

    @NotNull
    @Unique
    private String name;

    private Long g_id;  // 关联两个表的外键
    @ToOne(joinProperty = "g_id")
    private GirlFriend mGirlFriend;  // 源实体
                 
		... ...

}

关于joinProperty 在源码中的解释是:

Name of the property inside the current entity which holds the key of related entity. 我的理解是:当前实体(目标实体)的属性名称(即g_id)持有相关实体(源实体)的键(id,在GirlFriend表中就是主键)

Make Project之后我们会发现目标实体多了个关键的方法getMGirlFriend()

## 记得升级下数据库版本号 不然会报错

/** To-one relationship, resolved on first access. */
@Generated(hash = 400379903)
public GirlFriend getMGirlFriend() {
    Long __key = this.g_id;
    if (mGirlFriend__resolvedKey == null
            || !mGirlFriend__resolvedKey.equals(__key)) {
        final DaoSession daoSession = this.daoSession;
        if (daoSession == null) {
            throw new DaoException("Entity is detached from DAO context");
        }
        GirlFriendDao targetDao = daoSession.getGirlFriendDao();
	// 实际上就是拿这个外键g_id 去查了GirlFriend表
        GirlFriend mGirlFriendNew = targetDao.load(__key);
        synchronized (this) {
            mGirlFriend = mGirlFriendNew;
            mGirlFriend__resolvedKey = __key;
        }
    }
    return mGirlFriend;
}

这样基本就形成了老师---女友的一对一关系 。。。等等这还没完 给老师配备好女友之后记得要更新下老师的信息 要不然数据库中不会存储这个信息的

// 添加女友
private void addGF(Teacher teacher) {
    // 制造女友
    GirlFriend girlFriend = DataUtil.getGirlFriend();
    // 插入数据库
    mDaoManager.insertGirlFriend(girlFriend);
    // 查询女友 获得主键id
    GirlFriend girlFriend1 = mDaoManager.queryGirlFriend(girlFriend.getName());
    // 更新获得女友的Teacher
    mDaoManager.updateTeacher(teacher, girlFriend1.getId());
    List list = mDaoManager.queryTeachers(mKey);
    // 刷新页面
    refreshView(list);
}
*************************************************分割线****************************************************************************************

     又过了不久 业务继续升级 一个老师可以有多个学生 就形成了1对多的关系

先来张学生表,只有主键id、name和score分数三个属性:

@Entity
public class Student {
    @Id(autoincrement = true)
    private Long id;
    private String name;
    private float score;
    
	... ...
}


 这个时候就该我们的@ToMany标记出场了给谁标记 怎么去标呢? 这里是在上面添加女友的基础上对老师进行操, 那么老师依然是目标实体,学生是源实体;让目标实体去关联源实体 我们给目标实体去添加@ToMany标记同时源实体要添加@ToOne标记与老师对应修改下如下:

首先对源实体做一对一的修改:

@Entity
public class Student {
    @Id(autoincrement = true)
    private Long id;
    private String name;
    private float score;
    
    private Long t_id;  // 其实就是Teacher的主键
    // 这里老师是源实体
    @ToOne(joinProperty = "t_id") //被引用
    private Teacher mTeacher;		
	
	... ...
}

     Make Project之后我们会发现目标实体多了个关键的方法getMTeacher()与一对一的类似就不贴代码了^_^

  接下来是目标实体老师的修改:

@Entity
public class Teacher {
    @Id(autoincrement = true)
    private Long id;

    @NotNull
    @Unique
    private String name;

    private Long g_id;  // 关联两个表的外键
    @ToOne(joinProperty = "g_id")
    private GirlFriend mGirlFriend;  // 源实体
    
    @ToMany(referencedJoinProperty = "t_id") // 与源实体 外键相对应
    private List mStudents;
		... ...

}

 关于referencedJoinProperty 源码中是这样注释的:

	Name of the property inside the target entity which holds id of the source (current) entity 我的理解是:指定目标实体与源实体的相关联的外键


 Make Project之后我们会发现目标实体多了个关键的方法getMStudents():

@Generated(hash = 1758362269)
public List getMStudents() {
    if (mStudents == null) {
        final DaoSession daoSession = this.daoSession;
        if (daoSession == null) {
            throw new DaoException("Entity is detached from DAO context");
        }
        StudentDao targetDao = daoSession.getStudentDao();
	// 其实就查询学生表将持有相同老师id的学生找出来
        List mStudentsNew = targetDao._queryTeacher_MStudents(id);
        synchronized (this) {
            if (mStudents == null) {
                mStudents = mStudentsNew;
            }
        }
    }
    return mStudents;
}

查看targetDao._queryTeacher_MStudents(id) 发现是StudentDao的方法

/** Internal query to resolve the "mStudents" to-many relationship of Teacher. */
public List _queryTeacher_MStudents(Long t_id) {
    synchronized (this) {
        if (teacher_MStudentsQuery == null) {
            QueryBuilder queryBuilder = queryBuilder();
            queryBuilder.where(Properties.T_id.eq(null));
            teacher_MStudentsQuery = queryBuilder.build();
        }
    }
    Query query = teacher_MStudentsQuery.forCurrentThread();
    query.setParameter(0, t_id);
    return query.list();
}
一目了然了!!!!-------别忘记升级数据库版本号!

这样老师---学生的一对多关系就有了 。。。但是 在给老师配备好学生之后更新老师的信息后然并卵并没有刷新我的界面 和上面一对一的情况不同啊 为毛 捋了好几遍流程没错啊 懵逼了!! 退出程序重新进 查询老师的信息 又显示刚添加的学生信息了 试验了几次都是这样 和同事讨论下了就怀疑缓存的问题 他很肯定sqlite mySqlite什么的是没有缓存一说的 难道greenDao自带缓存?? 上网查了下还真有 点击打开链接 具体如下:

 public TeacherDao getTeacherDao() {
        // 去除数据库缓存
	mDaoSession.clear();
        return mDaoSession.getTeacherDao();
    }

其实一对多还有两种方法 不过我没有研究就不搬砖了 详细的请戳我

为什么一对一的时候没问题 我也没有搞懂 有知道的大神欢迎指点!!

还有一个小功能就是查询Teacher的时候让学生按分数降序/升序排列

直接上代码了

@Entity
public class Teacher {
    @Id(autoincrement = true)
    private Long id;

    @NotNull
    @Unique
    private String name;

    private Long g_id;  // 关联两个表的外键
    @ToOne(joinProperty = "g_id")
    private GirlFriend mGirlFriend;  // 源实体

    @ToMany(referencedJoinProperty = "t_id")
    @OrderBy(value = "score DESC") // 根据分数降序排列
    private List mStudents;
	... ...
}
 
  
生成代码之后会在StudentDao中发生神奇的改变(红色标记):
 
  
/** Internal query to resolve the "mStudents" to-many relationship of Teacher. */
public List _queryTeacher_MStudents(Long t_id) {
    synchronized (this) {
        if (teacher_MStudentsQuery == null) {
            QueryBuilder queryBuilder = queryBuilder();
            queryBuilder.where(Properties.T_id.eq(null));
            queryBuilder.orderRaw("T.'SCORE' DESC");
            teacher_MStudentsQuery = queryBuilder.build();
        }
    }
    Query query = teacher_MStudentsQuery.forCurrentThread();
    query.setParameter(0, t_id);
    return query.list();
}

好了这次就这么多了 最后附上Demo https://github.com/JamesP1949/GreenDaoDemo

最后我彦神镇楼!^_^

Android GreenDao3.2表关联及缓存相关_第1张图片




你可能感兴趣的:(Android)