家谱树数据结构
1、家庭成员数据库表存储结构,代码使用room存储数据
@Entity(tableName = "members")
data class FamilyMemberEntity(var name: String) {
constructor() : this("")
// 主键自增
@PrimaryKey(autoGenerate = true)
@ColumnInfo(name = "id")
@SerializedName("id")
var id: Long = 0
// 父亲id
@ColumnInfo(name = "fatherId")
@SerializedName("fatherId")
var fatherId: Long? = null
// 配偶id
@ColumnInfo(name = "spouseId")
@SerializedName("spouseId")
var spouseId: Long? = null
// 性别
@ColumnInfo(name = "sex")
@SerializedName("sex")
var sex: Int = 0
// 手机号
@ColumnInfo(name = "phone")
@SerializedName("phone")
var phone: String? = null // 手机号
...
}
其中id作为数据库主键自增。而fatherId和spouseId与其他成员建立联系,因为在一个家族之中一个成员的父亲和配偶都是唯一的(不考虑离异情况),而成员的母亲节点可以以父亲的配偶来获得(一夫一妻的情况),以此自上而下形成家族树关系。
2、家族树成员数据模型
/**
* 家族树数据模型
* */
data class FamilyMemberModel(var memberEntity: FamilyMemberEntity) {
// 配偶
var spouseEntity: FamilyMemberEntity? = null
// 孩子
var childModels: List<FamilyMemberModel>? = null
}
每个家族树成员包含三个成员:memberEntity、spouseEntity、childModels。其中memberEntity是当前成员的数据库信息,spouseEntity是当前成员配偶的信息,childModels是孩子的数据模型的集合。请注意childModels的类型是List<FamilyMemberModel>,也就是说childModels不仅包含孩子的基本信息,还包含孩子的配偶以及孩子的孩子信息。这是一种递归的表示方法,通过这种方法可以无限延伸下去。
3、数据库操作
@Dao
interface BaseDao<T> {
@Insert
fun insertItem(item: T) //插入单条数据
@Insert
fun insertItems(items: List<T>) //插入list数据
@Delete
fun deleteItem(item: T) //删除item
@Update
fun updateItem(item: T) //更新item
}
@Dao
interface FamilyMemberDao: BaseDao<FamilyMemberEntity> {
/**
* 根据id查询FamilyMemberEntity
*/
@Query("SELECT * FROM members WHERE id = :id ")
fun getMemberById(id: Long): FamilyMemberEntity
/**
* 根据id查询配偶信息
*/
@Query("SELECT * FROM members WHERE spouseId = :spouseId ")
fun getSpouseMemberById(spouseId: Long): FamilyMemberEntity
/**
* 根据id查询所有子FamilyMemberEntity集合
*/
@Query("SELECT * FROM members WHERE fatherId = :id ")
fun getChildMembers(id: Long): List<FamilyMemberEntity>
/**
* 查询全部结果
*/
@Query("SELECT * FROM members")
fun getAllMembers(): List<FamilyMemberEntity>
}
继承RoomDatabase
@Database(entities = {FamilyMemberEntity.class}, version = 1)
abstract public class FamilyDataBase extends RoomDatabase {
public abstract FamilyMemberDao familyMemberDao();
}
这段代码使用java编写,之前使用kotlin,会报FamilyDataBase_impl未生成的错误,不知道啥原因,使用java就好了。
数据库操作工具类
class FamilyDataBaseHelper constructor(context: Context) {
private val appDataBase = Room.databaseBuilder(context, FamilyDataBase::class.java,
"family.db").build()!!
companion object {
@Volatile
var INSTANCE: FamilyDataBaseHelper? = null
fun getInstance(context: Context): FamilyDataBaseHelper {
if (INSTANCE == null) {
synchronized(FamilyDataBaseHelper::class) {
if (INSTANCE == null) {
INSTANCE = FamilyDataBaseHelper(context.applicationContext)
}
}
}
return INSTANCE!!
}
}
/**
* 根据id获取Member
*/
fun getFamilyMember(id: Long): FamilyMemberEntity{
return appDataBase.familyMemberDao().getMemberById(id)
}
/**
* 根据id获取配偶Member
*/
fun getSpouseMember(id: Long): FamilyMemberEntity{
return appDataBase.familyMemberDao().getSpouseMemberById(id)
}
/**
* 根据id获取子Member
*/
fun getChildMembers(id: Long): List<FamilyMemberEntity> {
return appDataBase.familyMemberDao().getChildMembers(id)
}
/**
* 更新FamilyMemberEntity;必须在非主线程中进行
*/
fun updateMember(member: FamilyMemberEntity) {
appDataBase.familyMemberDao().updateItem(member)
}
/**
* 插入FamilyMemberEntity;必须在非主线程中进行
*/
fun insertMember(member: FamilyMemberEntity) {
appDataBase.familyMemberDao().insertItem(member)
}
}
3、生成家族树数据模型
- 获取家族树根节点
var familyMember = FamilyDataBaseHelper.getInstance(this).getFamilyMember(1)
在非主线程调用,demo里面数据库只有一个家族树,所以我用第一条作为整个树的根节点。实际情况可以在表中添加一个根节点的标记字段还获取根节点。
2.通过跟节点生成家族树模型
if (familyMember != null) {
var familyMemberModel = familyMember.generateMember(this)
}
这里调用generateMember方法来生成数据模型,我们来看一下这个方法的源码
/**
* 将数据库数据转换成家族树成员模型
* */
fun generateMember(context: Context) : FamilyMemberModel {
var familyMemberModel = FamilyMemberModel(this)
familyMemberModel.spouseEntity = FamilyDataBaseHelper.getInstance(context).getSpouseMember(id)
familyMemberModel.childModels = getChildMembers(context)
return familyMemberModel
}
private fun getChildMembers(context: Context): List<FamilyMemberModel> {
var memberList = FamilyDataBaseHelper.getInstance(context).getChildMembers(id)
var memberModelList = ArrayList<FamilyMemberModel>()
for (member in memberList) {
memberModelList.add(member.generateMember(context))
}
return memberModelList
}
其中当前节点的配偶通过查询数据库获得,获取孩子节点的getChildMembers方法里面会递归调用generateMember方法,从而延伸获取到整个家族树。
4、我们来插入一些测试数据,看一下最后显示的效果。
// 插入第一条数据,同时也是整个家族树的跟节点
var familyMember = FamilyMemberEntity("王根")
familyMember.imagePath = "111.jpg"
familyMember.phone = "18156094171"
familyMember.sex = 1
FamilyDataBaseHelper.getInstance(this).insertMember(familyMember)
familyMember = FamilyMemberEntity("王明")
familyMember.imagePath = "222.jpg"
familyMember.phone = "18156096666"
familyMember.fatherId = 1 // 父亲id为1,表示其父亲未第1条插入的数据,也就是上面的王根
familyMember.sex = 1
FamilyDataBaseHelper.getInstance(this).insertMember(familyMember)
familyMember = FamilyMemberEntity("王芸")
familyMember.imagePath = "222.jpg"
familyMember.phone = "18156096666"
familyMember.fatherId = 1 // 父亲id为1,表示其父亲未第1条插入的数据,也就是上面的王根
familyMember.sex = 0
FamilyDataBaseHelper.getInstance(this).insertMember(familyMember)
familyMember = FamilyMemberEntity("王恩")
familyMember.imagePath = "222.jpg"
familyMember.phone = "18156096666"
familyMember.fatherId = 2 // 父亲id为2,表示其父亲未第2条插入的数据,也就是上面的王明
familyMember.sex = 0
FamilyDataBaseHelper.getInstance(this).insertMember(familyMember)
对应的家族树如下:
familytre.jpg
网友评论