小白逆袭之路-私人定制Android数据库工具类实现

小白逆袭之路-私人定制Android数据库工具类实现

  • 前言
    • 先来点废话
    • 开发中容易出现的错误
  • 言归正传,代码拉出来
    • 简单的注解开发
    • 然后编写我们的实体类,并使用注解
    • 接下来就是定制我们的帮助类了
      • 这边重点讲一下建表和插入
      • 下面是完整代码
  • 总结

前言

先来点废话

众所周知在Android开发中,SQLiteDatabse有一个帮助类SQLiteOpenHelper,它可以用来管理数据的创建和版本更新。它是一个abstract类,作为开发者我们可以实现该类来对数据库进行操作。

开发中容易出现的错误

1.每创建一张表,都需要写相应的建表语句
2.选择表的列名和实体类的字段名时纠结良久
3.建表语句和查询语句中有某个地方写错了,没对应上,将导致一系列错误
4.对每一张表都要写不同的sql语句,不厌其烦。

言归正传,代码拉出来

简单的注解开发

声明用于标记字段的注解,使得字段和列名一一对应。

package com.example.yrw.yuansqlite.annotion;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface DbFiled {
    String value();
}

声明用于标记实体类的注解,使得与表能够一一对应。

package com.example.yrw.yuansqlite.annotion;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface DbTable {
    String value();
}


然后编写我们的实体类,并使用注解

使用@DbTable标记类名Person与表名tb_person对应,使用@DbFiled标记字段age与列名age对应。

@DbTable("tb_person")
public class Person {
    @DbFiled("age")
    private Integer age;
    @DbFiled("name")
    private String name;

    public Person(Integer age, String name) {
        this.age = age;
        this.name = name;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

接下来就是定制我们的帮助类了

这边重点讲一下建表和插入

前面注解使用的好处体现出来了,在这边我们不用使用具体的表名了,我们可以直接通过 entity.getAnnotation(DbTable.class).value()获取表名。

 tableName = entity.getAnnotation(DbTable.class).value();

同理这里可以使用field.getAnnotation(DbFiled.class).value()和field.getType()获得列名以及它对应的字段的类型。

@Override
    public void onCreate(SQLiteDatabase sqLiteDatabase) {
        StringBuffer stringBuffer = new StringBuffer();
        stringBuffer.append("CREATE TABLE IF NOT EXISTS ");
        stringBuffer.append(tableName + " ( ");
        Field[] fields = entityClass.getDeclaredFields();
        for (Field field : fields) {
            Class type = field.getType();
            if (type == String.class) {
                stringBuffer.append(field.getAnnotation(DbFiled.class).value() + " TEXT,");
            } else if (type == Double.class) {
                stringBuffer.append(field.getAnnotation(DbFiled.class).value() + " DOUBLE,");
            } else if (type == Integer.class) {
                stringBuffer.append(field.getAnnotation(DbFiled.class).value() + " INTEGER,");
            } else if (type == Long.class) {
                stringBuffer.append(field.getAnnotation(DbFiled.class).value() + " BIGINT,");
            } else if (type == byte[].class) {
                stringBuffer.append(field.getAnnotation(DbFiled.class).value() + " BLOB,");
            } else {
                /**
                 * 如果是不支持的类型
                 */
                continue;
            }

        }
        if (stringBuffer.charAt(stringBuffer.length() - 1) == ',') {
            stringBuffer.deleteCharAt(stringBuffer.length() - 1);
        }
        stringBuffer.append(")");
        sqLiteDatabase.execSQL(stringBuffer.toString());

    }

通过此种方法来拼接的sql,我们就不必将注意力放在表名和列名上,只要我们的实体类创建好了,我们的帮助类在实例化的时候就会自动为我们建表。
下面再看看查询。

    public Long insert(T entity,SQLiteDatabase sqLiteDatabase) {
        ContentValues contentValues = getValues(entity);
        sqLiteDatabase.insert(tableName, null, contentValues);
        return null;
    }

    private ContentValues getValues(T entity) {
        ContentValues contentValues = new ContentValues();
        Iterator<Map.Entry<String, Field>> iterator = cacheMap.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry<String, Field> fieldEntry = iterator.next();
            //类中的字段名
            Field field = fieldEntry.getValue();
            //表中的列名
            String key = fieldEntry.getKey();

            field.setAccessible(true);

            try {
                Object object = field.get(entity);
                Class type = field.getType();
                if (type == String.class) {
                    String value = (String) object;
                    contentValues.put(key, value);
                } else if (type == Double.class) {
                    Double value = (Double) object;
                    contentValues.put(key, value);
                } else if (type == Integer.class) {
                    Integer value = (Integer) object;
                    contentValues.put(key, value);
                } else if (type == Long.class) {
                    Long value = (Long) object;
                    contentValues.put(key, value);
                } else if (type == byte[].class) {
                    byte[] value = (byte[]) object;
                    contentValues.put(key, value);
                } else {
                    continue;
                }


            } catch (IllegalAccessException e) {


            }
        }
        return contentValues;
    }

是不是有和前面相似的味道,我们在调用此方法的时候只要传入想要插入的对象的实例就可以。之后在针对每个类实现其dao方法时,我们都可以来调用此方法,如此就完全规避了sql语句。

下面是完整代码

public class  DBOpenHelper <T> extends SQLiteOpenHelper{
    private static final int VERSION = 1;//定义版本号
    private static final String DBNAME = "yuan.db";//定义数据库名称
    private Class<T> entityClass;//要插入的对象类型
    private String tableName;//表名
    private HashMap<String, Field> cacheMap;//用于保存列名和成员变量的映射


    public DBOpenHelper(Context context,Class<T> entity){
        super(context,DBNAME,null,VERSION);//重写父类的构造
        entityClass = entity;
        tableName = entity.getAnnotation(DbTable.class).value();
    }


    @Override
    public void onCreate(SQLiteDatabase sqLiteDatabase) {
        StringBuffer stringBuffer = new StringBuffer();
        stringBuffer.append("CREATE TABLE IF NOT EXISTS ");
        stringBuffer.append(tableName + " ( ");
        Field[] fields = entityClass.getDeclaredFields();
        for (Field field : fields) {
            Class type = field.getType();
            if (type == String.class) {
                stringBuffer.append(field.getAnnotation(DbFiled.class).value() + " TEXT,");
            } else if (type == Double.class) {
                stringBuffer.append(field.getAnnotation(DbFiled.class).value() + " DOUBLE,");
            } else if (type == Integer.class) {
                stringBuffer.append(field.getAnnotation(DbFiled.class).value() + " INTEGER,");
            } else if (type == Long.class) {
                stringBuffer.append(field.getAnnotation(DbFiled.class).value() + " BIGINT,");
            } else if (type == byte[].class) {
                stringBuffer.append(field.getAnnotation(DbFiled.class).value() + " BLOB,");
            } else {
                /**
                 * 如果是不支持的类型
                 */
                continue;
            }

        }
        if (stringBuffer.charAt(stringBuffer.length() - 1) == ',') {
            stringBuffer.deleteCharAt(stringBuffer.length() - 1);
        }
        stringBuffer.append(")");
        sqLiteDatabase.execSQL(stringBuffer.toString());

    }

    //重写父类的onUpgrade方法,以便数据库版本更新

    @Override
    public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
    }

    public Long insert(T entity,SQLiteDatabase sqLiteDatabase) {
        ContentValues contentValues = getValues(entity);
        sqLiteDatabase.insert(tableName, null, contentValues);
        return null;
    }

    private ContentValues getValues(T entity) {
        ContentValues contentValues = new ContentValues();
        Iterator<Map.Entry<String, Field>> iterator = cacheMap.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry<String, Field> fieldEntry = iterator.next();
            //类中的字段名
            Field field = fieldEntry.getValue();
            //表中的列名
            String key = fieldEntry.getKey();

            field.setAccessible(true);

            try {
                Object object = field.get(entity);
                Class type = field.getType();
                if (type == String.class) {
                    String value = (String) object;
                    contentValues.put(key, value);
                } else if (type == Double.class) {
                    Double value = (Double) object;
                    contentValues.put(key, value);
                } else if (type == Integer.class) {
                    Integer value = (Integer) object;
                    contentValues.put(key, value);
                } else if (type == Long.class) {
                    Long value = (Long) object;
                    contentValues.put(key, value);
                } else if (type == byte[].class) {
                    byte[] value = (byte[]) object;
                    contentValues.put(key, value);
                } else {
                    continue;
                }


            } catch (IllegalAccessException e) {


            }
        }
        return contentValues;
    }
}
public class  DBOpenHelper <T> extends SQLiteOpenHelper{
    private static final int VERSION = 1;//定义版本号
    private static final String DBNAME = "yuan.db";//定义数据库名称
    private Class<T> entityClass;//要插入的对象类型
    private String tableName;//表名
    private HashMap<String, Field> cacheMap;//用于保存列名和成员变量的映射


    public DBOpenHelper(Context context,Class<T> entity){
        super(context,DBNAME,null,VERSION);//重写父类的构造
        entityClass = entity;
        tableName = entity.getAnnotation(DbTable.class).value();
    }


    @Override
    public void onCreate(SQLiteDatabase sqLiteDatabase) {
        StringBuffer stringBuffer = new StringBuffer();
        stringBuffer.append("CREATE TABLE IF NOT EXISTS ");
        stringBuffer.append(tableName + " ( ");
        Field[] fields = entityClass.getDeclaredFields();
        for (Field field : fields) {
            Class type = field.getType();
            if (type == String.class) {
                stringBuffer.append(field.getAnnotation(DbFiled.class).value() + " TEXT,");
            } else if (type == Double.class) {
                stringBuffer.append(field.getAnnotation(DbFiled.class).value() + " DOUBLE,");
            } else if (type == Integer.class) {
                stringBuffer.append(field.getAnnotation(DbFiled.class).value() + " INTEGER,");
            } else if (type == Long.class) {
                stringBuffer.append(field.getAnnotation(DbFiled.class).value() + " BIGINT,");
            } else if (type == byte[].class) {
                stringBuffer.append(field.getAnnotation(DbFiled.class).value() + " BLOB,");
            } else {
                /**
                 * 如果是不支持的类型
                 */
                continue;
            }

        }
        if (stringBuffer.charAt(stringBuffer.length() - 1) == ',') {
            stringBuffer.deleteCharAt(stringBuffer.length() - 1);
        }
        stringBuffer.append(")");
        sqLiteDatabase.execSQL(stringBuffer.toString());

    }

    //重写父类的onUpgrade方法,以便数据库版本更新

    @Override
    public void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {
    }

    public Long insert(T entity,SQLiteDatabase sqLiteDatabase) {
        ContentValues contentValues = getValues(entity);
        sqLiteDatabase.insert(tableName, null, contentValues);
        return null;
    }

    private ContentValues getValues(T entity) {
        ContentValues contentValues = new ContentValues();
        Iterator<Map.Entry<String, Field>> iterator = cacheMap.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry<String, Field> fieldEntry = iterator.next();
            //类中的字段名
            Field field = fieldEntry.getValue();
            //表中的列名
            String key = fieldEntry.getKey();

            field.setAccessible(true);

            try {
                Object object = field.get(entity);
                Class type = field.getType();
                if (type == String.class) {
                    String value = (String) object;
                    contentValues.put(key, value);
                } else if (type == Double.class) {
                    Double value = (Double) object;
                    contentValues.put(key, value);
                } else if (type == Integer.class) {
                    Integer value = (Integer) object;
                    contentValues.put(key, value);
                } else if (type == Long.class) {
                    Long value = (Long) object;
                    contentValues.put(key, value);
                } else if (type == byte[].class) {
                    byte[] value = (byte[]) object;
                    contentValues.put(key, value);
                } else {
                    continue;
                }


            } catch (IllegalAccessException e) {


            }
        }
        return contentValues;
    }
}


总结

这边只是简单的介绍了建表和插入,有兴趣的小伙伴还可以完善删改查,以此为基础,还可以编写属于自己的数据库框架。

你可能感兴趣的:(java小白,android小白,安卓数据库帮助类,自动建表)