数据结构

家谱树数据结构

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? = null

}

每个家族树成员包含三个成员:memberEntity、spouseEntity、childModels。其中memberEntity是当前成员的数据库信息,spouseEntity是当前成员配偶的信息,childModels是孩子的数据模型的集合。请注意childModels的类型是List,也就是说childModels不仅包含孩子的基本信息,还包含孩子的配偶以及孩子的孩子信息。这是一种递归的表示方法,通过这种方法可以无限延伸下去。

3、数据库操作

@Dao
interface BaseDao {

    @Insert
    fun insertItem(item: T) //插入单条数据

    @Insert
    fun insertItems(items: List) //插入list数据

    @Delete
    fun deleteItem(item: T) //删除item

    @Update
    fun updateItem(item: T) //更新item

}

@Dao
interface FamilyMemberDao: BaseDao {

    /**
     * 根据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

    /**
     * 查询全部结果
     */
    @Query("SELECT * FROM members")
    fun getAllMembers(): List

}

继承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 {
        return appDataBase.familyMemberDao().getChildMembers(id)
    }

    /**
     * 更新FamilyMemberEntity;必须在非主线程中进行
     */
    fun updateMember(member: FamilyMemberEntity) {
        appDataBase.familyMemberDao().updateItem(member)
    }

    /**
     * 插入FamilyMemberEntity;必须在非主线程中进行
     */
    fun insertMember(member: FamilyMemberEntity) {
        appDataBase.familyMemberDao().insertItem(member)
    }
}

3、生成家族树数据模型

  1. 获取家族树根节点
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 {
    var memberList = FamilyDataBaseHelper.getInstance(context).getChildMembers(id)
    var memberModelList = ArrayList()
    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)

对应的家族树如下:


数据结构_第1张图片
familytre.jpg

你可能感兴趣的:(数据结构)