搭建自己的SQLiteDataBase框架(五)

本文介绍了一种在SQLite中实现一对多关系的方法,通过定义实体类及其对应的数据库表结构,展示了如何通过Java代码进行数据库的增删改查操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

搭建自己的SQLiteDataBase框架(五)


  • 一对多关系,同样也有两种关系,1,关联表存储对应关系,2,直接数据库操作增删改查
    此时实体类的对应模型如下:
@Table(name = "developer")
public class Developer implements Serializable {
    private static final long serialVersionUID = 1L;
    @Column(id = true)
    private String id;
    @Column
    private String name;
    @Column
    private int age;
    @Column(type = Column.ColumnType.SERIALIZABLE)
    private ArrayList<Skill> skills;
}

@Table(name = "company")
public class Company {
    @Column(id = true)
    private String id;
    @Column
    private String name;
    @Column
    private String url;
    @Column
    private String tel;
    @Column
    private String address;

    private String group;
    //添加一对多关系
    @Column(type = Column.ColumnType.TMANY,autoRefresh=true)
    private ArrayList<Developer> developers;
}

即:一个company可以对应多个developer,这个关系要理清

完善建表语句,相比之前变化略大:


    public static void createTable(SQLiteDatabase db, Class<?> clz) throws SQLException {
        System.out.println(getCreateTableStmt(clz));
        ArrayList<String> stmts = getCreateTableStmt(clz);
        for (String stmt : stmts) {
            db.execSQL(stmt);
        }
    }

    //建表语句,以Company为例说明
       private static ArrayList<String> getCreateTableStmt(Class<?> clz) {
        StringBuilder mColumnStmts = new StringBuilder();
        ArrayList<String> stmts = new ArrayList<String>();
        if (clz.isAnnotationPresent(Table.class)) {
            Field[] fields = clz.getDeclaredFields();
            for (int i = 0; i < fields.length; i++) {
                if (fields[i].isAnnotationPresent(Column.class)) {
                    if (fields[i].getAnnotation(Column.class).type() == Column.ColumnType.TMANY) {
                    //建关联表语句,create table if not exists company_developers( pk1 TEXT,pk2 TEXT)
                        stmts.add("create table if not exists " + getAssociationTableName(clz, fields[i].getName()) + "(" + PK1 + " TEXT, " + PK2
                                + " TEXT)");
                    }
                    mColumnStmts.append(getOneColumnStmt(fields[i]));
                    mColumnStmts.append(",");
                }
            }
            if (mColumnStmts.length() > 0) {
                mColumnStmts.delete(mColumnStmts.length() - 2, mColumnStmts.length());
            }
        }
        // create table if not exists company (id TEXT primary key,...)
        stmts.add("create table if not exists " + getTableName(clz) + " (" + mColumnStmts + ")");
        return stmts;
    }


        //获取关联表 表名
        public static String getAssociationTableName(Class<?> clz, String association) {
        return getTableName(clz) + "_" + association;
    }

完善增删改查:

 public <T> void newOrUpdate(T t) {
        ContentValues contentValues = new ContentValues();
        try {
            String idValue = (String) id_field_.get(t);
            for (Field field : fields) {
                if (field.isAnnotationPresent(Column.class)) {
                    field.setAccessible(true);
                    Class<?> clz = field.getType();
                    if (clz == String.class) {
                        System.out.println("key:" + DBUtils.getColumnName(field) + ",value:" + field.get(t).toString());
                        contentValues.put(DBUtils.getColumnName(field), field.get(t).toString());
                    } else if (clz == int.class || clz == Integer.class) {
                        contentValues.put(DBUtils.getColumnName(field), field.getInt(t));
                    } else {
                        Column column = field.getAnnotation(Column.class);
                        Column.ColumnType columnType = column.type();
                        if (!TextUtils.isValidate(columnType.name())) {
                            throw new IllegalArgumentException("you should set  type to the special column:" + t.getClass().getSimpleName() + "." + field.getName());
                        }
                        if (columnType == Column.ColumnType.SERIALIZABLE) {
                            contentValues.put(DBUtils.getColumnName(field), SerializeUtil.serialize(field.get(t)));
                        } else if (columnType == Column.ColumnType.TONE) {
                            Object tone = field.get(t);
                            if (tone == null) {
                                continue;
                            }
                            if (column.autoRefresh()) {
                                // save object to related table
                                DBManager.getInstance().getDao(tone.getClass()).newOrUpdate(tone);

                            }
                            if (tone.getClass().isAnnotationPresent(Table.class)) {
                                String idName = DBUtils.getIDColumnName(tone.getClass());
                                Field id_field = tone.getClass().getDeclaredField(idName);
                                id_field.setAccessible(true);
                                contentValues.put(DBUtils.getColumnName(field), id_field.get(tone).toString());
                            }
                        } else if (columnType == Column.ColumnType.TMANY) {//添加一对多关系
                            List<Object> tmany = (List<Object>) field.get(t);
                            if (!TextUtils.isValidate(tmany)) {
                                continue;
                            }
                            //先清空再插入
                            String associationTable = DBUtils.getAssociationTableName(t.getClass(), field.getName());
                            delete(associationTable, "pk1=?", new String[]{idValue});
                            ContentValues assosiationValues = new ContentValues();
                            for (Object object : tmany) {
                                if (column.autoRefresh()) {
                                    DBManager.getInstance().getDao(object.getClass()).newOrUpdate(object);
                                }
                                assosiationValues.clear();
                                assosiationValues.put(DBUtils.PK1, idValue);
                                String idName = DBUtils.getIDColumnName(object.getClass());
                                Field idField = object.getClass().getDeclaredField(idName);
                                idField.setAccessible(true);
                                assosiationValues.put(DBUtils.PK2, idField.get(object).toString());
                                newOrUpdate(associationTable, assosiationValues);
                            }
                        }
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            System.out.println("newOrUpdate:" + e.toString());
        }
        newOrUpdate(mTableName, contentValues);
    }

        //删除关联数据
        public void delete(String id) {
        try {
            delete(mTableName, mIdName + "=?", new String[]{id});
            //delete related association data
            for (Field field : mForeignds) {
                delete(DBUtils.getAssociationTableName(clz, field.getName()), "pk1=?", new String[]{id});
            }
        } catch (Exception e) {
            System.out.println(e.toString());
        }
    }

    //
     public T queryById(String id) {
        Cursor cursor = rawQuery(mTableName, mIdName + "=?", new String[]{id});
        T t = null;
        if (cursor.moveToNext()) {
            try {
                t = clz.newInstance();
                for (Field field : fields) {
                    if (field.isAnnotationPresent(Column.class)) {
                        field.setAccessible(true);
                        Class<?> clazz = field.getType();
                        if (clazz == int.class || clazz == Integer.class) {
                            field.setInt(t, cursor.getInt(cursor.getColumnIndex(DBUtils.getColumnName(field))));
                        } else if (clazz == String.class) {
                            field.set(t, cursor.getString(cursor.getColumnIndex(DBUtils.getColumnName(field))));
                        } else {
                            // TONE columnType.newInstance -- setId--set to T (lazy load)
                            // Serializable deserializable to object --set to T (lazy load)
                            Column column = field.getAnnotation(Column.class);
                            Column.ColumnType columnType = column.type();
                            if (!TextUtils.isValidate(columnType.name())) {
                                throw new IllegalArgumentException("you should set  type to the special column:" + t.getClass().getSimpleName() + "." + field.getName());
                            }
                            if (columnType == Column.ColumnType.SERIALIZABLE) {
                                field.set(t, SerializeUtil.deserialize(cursor.getBlob(cursor.getColumnIndex(DBUtils.getColumnName(field)))));
                            } else if (columnType == Column.ColumnType.TONE) {
                                String idtone = cursor.getString(cursor.getColumnIndex(DBUtils.getColumnName(field)));
                                if (!TextUtils.isValidate(idtone)) {
                                    continue;
                                }
                                Object tone = null;
                                if (column.autoRefresh()) {
                                    //去数据库查询
                                    tone = DBManager.getInstance().getDao(field.getType()).queryById(idtone);
                                } else {
                                    tone = field.getType().newInstance();
                                    if (field.getType().isAnnotationPresent(Table.class)) {
                                        String idName = DBUtils.getIDColumnName(field.getType());
                                        Field id_field = field.getType().getDeclaredField(idName);
                                        id_field.setAccessible(true);
                                        id_field.set(tone, idtone);
                                    }
                                }
                                field.set(t, tone);
                            } else if (columnType == Column.ColumnType.TMANY) {//添加一对多关系
                                //获取List<T>中的T
                                Class realatedClass = (Class) ((ParameterizedType) field.getGenericType()).getActualTypeArguments()[0];
                                Cursor tmanyCursor = db.rawQuery("select * from " + DBUtils.getAssociationTableName(clz, field.getName()) + " where " + DBUtils.PK1 + " =?", new String[]{id});
                                List list = new ArrayList();
                                String tmanyId = null;
                                Object tmany = null;
                                while (tmanyCursor.moveToNext()) {
                                    tmanyId = tmanyCursor.getString(tmanyCursor.getColumnIndex(DBUtils.PK2));
                                    if (column.autoRefresh()) {
                                        tmany = DBManager.getInstance().getDao(realatedClass).queryById(tmanyId);
                                    } else {
                                        tmany = realatedClass.newInstance();
                                        String idName = DBUtils.getIDColumnName(realatedClass);
                                        Field id_field = realatedClass.getDeclaredField(idName);
                                        id_field.setAccessible(true);
                                        id_field.set(tmany, tmanyId);
                                    }
                                    list.add(tmany);
                                }
                                if (!TextUtils.isValidate(list)) {
                                    continue;
                                }
                                field.set(t, list);
                            }

                        }

                    }
                }

            } catch (Exception e) {
                e.printStackTrace();
                System.out.println("queryById:" + e.toString());
            }
        }
        return t;
    }

测试一下:


 public void add() {
        Company company = new Company();
        company.setId("00001");
        company.setName("stay4it");
        company.setUrl("www.stay4it.com");
        company.setTel("10086");
        company.setAddress("Shanghai");
        Developer developer = new Developer();
        developer.setId("00001");
        developer.setName("Stay");
        developer.setAge(17);
        Skill skill = new Skill();
        skill.setName("coding");
        skill.setDesc("android");
        ArrayList<Skill> skills = new ArrayList<Skill>();
        skills.add(skill);
        developer.setSkills(skills);
        ArrayList<Developer> developers = new ArrayList<Developer>();
        developers.add(developer);
        company.setDevelopers(developers);
        DBManager.getInstance().getDao(Company.class).newOrUpdate(company);
    }

    public void queryCompanyById() {
        Company company = DBManager.getInstance().getDao(Company.class).queryById("00001");
        if (company != null) {
            System.out.println(company.toString());
        }
    }

看下日志输出:

11-17 11:18:43.812 26469-26469/project.charles.com.myapplication I/System.out: id:00001,name:stay4it,url:www.stay4it.com,tel:10086,address:Shanghai,developers[{"age":17,"id":"00001","name":"Stay","skills":[{"desc":"android","name":"coding"}]}]

接下来还有多对多的关系…

至此,DB框架的大体结构就成型了,后续就是在项目使用中的维护,扩展了,从简至繁,一步一步就构造出了一个简易的DB框架,如果只是轻量级使用SQLiteDataBase,自己搭建一个架子也就足够了

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值