java注解反射实现数据库增删改查

2019-04-01  本文已影响0人  鹅鹅鹅曲项向天歌呀

声明:此例子是为了学习注解和反射的综合应用,但是功能是可以用的。我不能保证没有bug,因为我也没可劲的测试过,只是为了学习注解反射,比较好理解的一个例子。
1、声明表名注解,创建数据库表名使用

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

2、声明字段直接,创建表中的列使用

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface KeyName {
    String value(); //字段名称
    boolean isPrimaryKey() default false; //是否为主键
}

3、创建一个要存入数据库的对象
此处用Student为例子

@TableName("sdfsdfsdf")
public class Student {
    //表中的列名为sql_userName,并且是主键
    @KeyName(value = "sql_userName", isPrimaryKey = true)
    private String userName;
    @KeyName(value = "sql_age")
    private int age;  
    //没有被注解的字段,默认就是属性名字
    private String sex;

    public Student() {
    }

    public Student(String userName, int age, String sex) {
        this.userName = userName;
        this.age = age;
        this.sex = sex;
    }
    //get() 和set()方法...省略了,要写上。。。。
    @Override
    public String toString() {
        return "Student{" +
                "userName='" + userName + '\'' +
                ", age=" + age +
                ", sex='" + sex + '\'' +
                '}';
    }
}

4、创建 SQLiteOpenHelper 单例
我们要去动态的创建表,所以这里只创建数据,不做其他操作。

public class SQLiteManager {
    public SQLiteManager() {
    }
    private static SQLiteOpenHelper SQ_LITE_UTIL = null;
    public static SQLiteOpenHelper getSqLiteUtil(Context context, String name) {
        if (SQ_LITE_UTIL == null) {
            synchronized (SQLiteOpenHelper.class) {
                if (SQ_LITE_UTIL == null) {
                    SQ_LITE_UTIL = new SQLiteOpenHelper(context, name, null, 1) {
                        @Override
                        public void onCreate(SQLiteDatabase db) {
                        }

                        @Override
                        public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
                        }
                    };
                }
            }
        }
        return SQ_LITE_UTIL;
    }

}

4、定义一个增删检查的接口类

也可以不写,定义这个接口是为了规范方法的。
public interface IDataBaseInterface {
    <_Tx> boolean insert(_Tx object);
    <_Tx> boolean insert(_Tx... object);
    <_Tx> boolean insert(List<_Tx> objectList);
    <_Tx> boolean update( _Tx object);
    <_Tx> boolean update(_Tx... object);
    <_Tx> boolean update( List<_Tx> objectList);
    <_Tx> boolean delete(_Tx object);
    <_Tx> boolean delete(_Tx... object);
    <_Tx> boolean delete(List<_Tx> objectList);
    <_Tx> List<_Tx> select(Class<_Tx> txClass,AbsSelect object);

}

5、 !!重点在这里!! 通过注解反射实现增删改查
代码里面都写了注释咯~~~

public class DataBaseImpl implements IDataBaseInterface {
    private Context context;
    String sqlName;

    static Map<String, String> keyTokey = new HashMap<>();//记录属性类型和sql中的数据类型,目的是为了转换数据类型

    static {
        keyTokey.put(String.class.getSimpleName(), "TEXT");
        keyTokey.put(Integer.class.getSimpleName(), "INTEGER");
        keyTokey.put("int", "INTEGER");
        keyTokey.put(Long.class.getSimpleName(), "TEXT");
        keyTokey.put(Short.class.getSimpleName(), "INTEGER");
        keyTokey.put(Double.class.getSimpleName(), "REAL");
        keyTokey.put(Boolean.class.getSimpleName(), "BLOB");
    }

    public DataBaseImpl(Context context, String sqlName) {
        this.context = context;
        this.sqlName = sqlName;
    }

    @Override
    public <_Tx> boolean insert(_Tx object) {
        String primarKey = null;//主键名称
        String primarKeyTy = null;
        String primarKeySqlTy = null;
        Class aClass = object.getClass();
        //创建一行数据
        ContentValues contentValues = new ContentValues();
        //记录属性和属性的数据类型
        Map<String, Object> keyToValue = new HashMap<>();
        //获取类的表名注解
        TableName annotation = (TableName) aClass.getAnnotation(TableName.class);
        if (annotation != null) {
            Constant.tableName = annotation.value();
        } else {
            Constant.tableName = aClass.getSimpleName();
        }
        try {
            //反射所有属性
            Field[] declaredFields = Utils.getClassDeclaredFields(aClass);
            if (declaredFields != null) {
                for (Field itemField : declaredFields) {
                    itemField.setAccessible(true);
                    //获取属性的列名注解
                    KeyName keyName = itemField.getAnnotation(KeyName.class);
                    if (keyName != null) {//如果属性被注解了
                        if (keyName.isPrimaryKey()) {
                            //主键的名字从注解里面获取(写spl语句使用)
                            primarKey = keyName.value();
                            //主键的数据类型,判断主键的数据类型和sql的数据类型使用
                            primarKeyTy = ((Class) itemField.getGenericType()).getSimpleName();
                        }
                        //添加列名和内容
                        contentValues.put(keyName.value(), String.valueOf(itemField.get(object)));
                        //添加属性名称和属性的数据类型
                        keyToValue.put(keyName.value(), ((Class) itemField.getGenericType()).getSimpleName());
                    } else {
                        contentValues.put(itemField.getName(), String.valueOf(itemField.get(object)));
                        keyToValue.put(itemField.getName(), ((Class) itemField.getGenericType()).getSimpleName());
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        //构造创建表的sql语句
        StringBuilder stringBuilder = new StringBuilder();
        //移除主键,主键在spl语句中单独添加,不与其他列一起添加
        keyToValue.remove(primarKey);
        for (Map.Entry<String, Object> objectEntry : keyToValue.entrySet()) {
            String key = objectEntry.getKey();
            Object value = objectEntry.getValue();
            stringBuilder.append("," + key);
            for (Map.Entry<String, String> keyT : keyTokey.entrySet()) {
                if (keyT.getKey().equals(value.toString())) {
                    //循环map,拼接spl语句
                    stringBuilder.append(" " + keyT.getValue());
                }
                if (keyT.getKey().equals(primarKeyTy)) {
                    //获取主键在sql的数据类型
                    primarKeySqlTy = keyT.getValue();
                }
            }
        }
        //获取数据库
        SQLiteDatabase writableDatabase = SQLiteManager.getSqLiteUtil(context, sqlName).getWritableDatabase();
        String sql = "create table if not exists " + Constant.tableName + " (" + primarKey + " "
                + primarKeySqlTy + " primary key " + stringBuilder.toString() + ")";

        //先检查表是否存在
        boolean exist = Utils.isTableExist(writableDatabase, Constant.tableName);
        if (!exist) {
            writableDatabase.execSQL(sql);
        }
        //再检查是否有多余的列
        for (Map.Entry<String, Object> entry : keyToValue.entrySet()) {
            String keyTValue = null;
            if (!Utils.isColumnExist(writableDatabase, Constant.tableName, entry.getKey())) {
                for (Map.Entry<String, String> keyT : keyTokey.entrySet()) {
                    if (keyT.getKey().equals(entry.getKey())) {
                        keyTValue = keyT.getValue();
                    }
                }
                //更新表结构sql语句
                String upsql = "ALTER TABLE " + Constant.tableName + " ADD " + entry.getKey() + " " + keyTValue;
                writableDatabase.execSQL(upsql);
            }
        }

        //插入数据
        writableDatabase.insert(Constant.tableName, null, contentValues);
        writableDatabase.close();
        return false;
    }

    @Override
    public <_Tx> boolean insert(_Tx... object) {
        for (_Tx tx : object) {
            insert(tx);
        }
        return false;
    }

    @Override
    public <_Tx> boolean insert(List<_Tx> objectList) {
        for (_Tx tx : objectList) {
            insert(tx);
        }
        return false;
    }


    @Override
    public <_Tx> boolean update(_Tx object) {
        String primarKey = null;
        Class aClass = object.getClass();
        SQLiteDatabase writableDatabase = SQLiteManager.getSqLiteUtil(context, sqlName).getWritableDatabase();
        ContentValues contentValues = new ContentValues();
        String primarKeyValue = null;
        try {
            Field[] declaredFields = Utils.getClassDeclaredFields(aClass);
            for (Field itemField : declaredFields) {
                itemField.setAccessible(true);
                //主键
                KeyName keyName = itemField.getAnnotation(KeyName.class);
                if (keyName != null) {
                    if (keyName.isPrimaryKey()) {
                        primarKey = keyName.value();//主键的名字从注解里面获取
                        primarKeyValue = String.valueOf(itemField.get(object));
                    }
                    contentValues.put(keyName.value(), String.valueOf(itemField.get(object)));
                } else {
                    contentValues.put(itemField.getName(), String.valueOf(itemField.get(object)));
                }
            }
            writableDatabase.update(Constant.tableName, contentValues, primarKey + "=?", new String[]{primarKeyValue});
            writableDatabase.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    @Override
    public <_Tx> boolean update(_Tx... object) {

        for (_Tx tx : object) {
            update(tx);
        }
        return false;
    }

    @Override
    public <_Tx> boolean update(List<_Tx> objectList) {
        for (_Tx tx : objectList) {
            update(tx);
        }
        return false;
    }


    @Override
    public <_Tx> boolean delete(_Tx object) {
        String primarKey = null;
        Class aClass = object.getClass();
        SQLiteDatabase writableDatabase = SQLiteManager.getSqLiteUtil(context, sqlName).getWritableDatabase();
        String primarKeyValue = null;
        TableName annotation = (TableName) aClass.getAnnotation(TableName.class);
        if (annotation != null) {
            Constant.tableName = annotation.value();
        } else {
            Constant.tableName = aClass.getSimpleName();
        }
        try {
            Field[] declaredFields = Utils.getClassDeclaredFields(aClass);
            if (declaredFields != null) {
                for (Field itemField : declaredFields) {
                    itemField.setAccessible(true);
                    //主键
                    KeyName keyName = itemField.getAnnotation(KeyName.class);
                    if (keyName != null) {
                        if (keyName.isPrimaryKey()) {
                            primarKey = keyName.value();//主键的名字从注解里面获取
                            primarKeyValue = String.valueOf(itemField.get(object));
                        }
                    }
                }
            }

            writableDatabase.delete(Constant.tableName, primarKey + "=?", new String[]{primarKeyValue});
            writableDatabase.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    @Override
    public <_Tx> boolean delete(_Tx... object) {
        for (_Tx tx : object) {
            delete(tx);
        }
        return false;
    }

    @Override
    public <_Tx> boolean delete(List<_Tx> objectList) {
        for (_Tx tx : objectList) {
            delete(tx);
        }
        return false;
    }


    @Override
    public <_Tx> List<_Tx> select(Class<_Tx> txClass, AbsSelect absSelect) {
        //返回结果
        List<_Tx> _TxList = new ArrayList<>();
        //查询列名
        List<String> columnsList = new ArrayList<>();
        //记录查询sql的字段和属性的数据类型
        Map<String, String> keyToType = new HashMap<>();
        //存放查询出来的数据
        Map<String, Object> keyToValue = new HashMap<>();
        String selection = null;
        String[] selectionArgs = null;
        String groupBy = null;
        String having = null;
        String orderBy = null;
        String limit = null;
        if (absSelect != null) {
            if (!TextUtils.isEmpty(absSelect.tableName())) {
                Constant.tableName = absSelect.tableName();
            }
            selection = absSelect.selection();
            selectionArgs = absSelect.selectionArgs();
            groupBy = absSelect.groupBy();
            having = absSelect.having();
            orderBy = absSelect.orderBy();
            limit = absSelect.limit();
        }
        try {
            TableName annotation = (TableName) txClass.getAnnotation(TableName.class);
            if (annotation != null) {
                Constant.tableName = annotation.value();
            } else {
                Constant.tableName = txClass.getSimpleName();
            }
            Field[] declaredFields = Utils.getClassDeclaredFields(txClass);
            if (declaredFields != null) {
                for (Field itemField : declaredFields) {
                    itemField.setAccessible(true);
                    KeyName keyName = itemField.getAnnotation(KeyName.class);
                    if (keyName != null) {
                        //添加查询的列名
                        columnsList.add(keyName.value());
                        //记录属性(列名)和数据类型
                        keyToType.put(keyName.value(), ((Class) itemField.getGenericType()).getSimpleName());
                    } else {
                        columnsList.add(itemField.getName());
                        keyToType.put(itemField.getName(), ((Class) itemField.getGenericType()).getSimpleName());
                    }


                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (columnsList != null && columnsList.size() > 0 && keyToType != null && keyToType.size() > 0) {

            SQLiteDatabase writableDatabase = SQLiteManager.getSqLiteUtil(context, sqlName).getWritableDatabase();
            //查询数据
            Cursor cursor = writableDatabase
                    .query(Constant.tableName, columnsList.toArray(new String[]{}), selection, selectionArgs, groupBy, having, orderBy, limit);
            while (cursor.moveToNext()) {
                for (Map.Entry<String, String> entry : keyToType.entrySet()) {
                    //循环keyToType,如果获取到的数据类型是String.class.getSimpleName(),就去获取这个key(属性)在数据库中的值,并存放在keyToValue中,以此类推
                    if (entry.getValue().equals(String.class.getSimpleName())) { //String类型
                        keyToValue.put(entry.getKey(), cursor.getString(cursor.getColumnIndex(entry.getKey().trim())));
                    } else if (entry.getValue().equals("int")) {//int类型
                        keyToValue.put(entry.getKey(), cursor.getInt(cursor.getColumnIndex(entry.getKey().trim())));
                    } else if (entry.getValue().equals(Double.class.getSimpleName())) {//double类型
                        keyToValue.put(entry.getKey(), cursor.getDouble(cursor.getColumnIndex(entry.getKey().trim())));
                    } else if (entry.getValue().equals(Long.class.getSimpleName())) {//long类型
                        keyToValue.put(entry.getKey(), cursor.getLong(cursor.getColumnIndex(entry.getKey().trim())));
                    } else if (entry.getValue().equals(Short.class.getSimpleName())) {//short类型
                        keyToValue.put(entry.getKey(), cursor.getShort(cursor.getColumnIndex(entry.getKey().trim())));
                    } else if (entry.getValue().equals(Integer.class.getSimpleName())) {//Integer类型
                        keyToValue.put(entry.getKey(), cursor.getInt(cursor.getColumnIndex(entry.getKey().trim())));
                    } else if (entry.getValue().equals(Boolean.class.getSimpleName())) {//Integer类型
                        keyToValue.put(entry.getKey(), cursor.getBlob(cursor.getColumnIndex(entry.getKey().trim())));
                    }
                }

                try {
                    //反射构造方法
                    Constructor declaredConstructor = txClass.getDeclaredConstructor();
                    //打开权限
                    declaredConstructor.setAccessible(true);
                    //创建对象
                    _Tx objectClass = (_Tx) declaredConstructor.newInstance();
                    //反射对象的属性
                    Field[] declaredFields = Utils.getClassDeclaredFields(objectClass.getClass());
                    if (declaredFields != null) {
                        for (Field itemField : declaredFields) {
                            itemField.setAccessible(true);
                            KeyName keyName = itemField.getAnnotation(KeyName.class);
                            if (keyName != null) {
                                for (Map.Entry<String, Object> entry : keyToValue.entrySet()) {
                                    //如果keyToValue中key和对象的属性是相同的,就把值赋给属性
                                    if (entry.getKey().equals(keyName.value())) {
                                        itemField.set(objectClass, entry.getValue());
                                    }
                                }
                            } else {
                                for (Map.Entry<String, Object> entry : keyToValue.entrySet()) {
                                    if (entry.getKey().equals(itemField.getName())) {
                                        itemField.set(objectClass, entry.getValue());
                                    }
                                }
                            }
                        }
                    }
                    _TxList.add(objectClass);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            writableDatabase.close();
        }
        return _TxList;

    }


}

6、常量类

public class Constant {
  public static String tableName = "";//表名
}

7、Utils 判断表是否存在还是列是否存在以及过滤反射的字段

public class Utils {

   /**
    * 作用:判断表是否存在
    *
    * @param db        数据库
    * @param tableName 表名
    */
   public static  boolean isTableExist(SQLiteDatabase db, String tableName) {
       Cursor cursor = null;
       try {
           cursor = db.rawQuery("SELECT count(*) FROM sqlite_master WHERE type='table' AND name=?", new String[]{tableName});
           boolean hasNext = cursor.moveToNext();
           return hasNext && cursor.getInt(0) > 0;
       } finally {
           if (cursor != null) {
               cursor.close();
           }
       }
   }

   /**
    * 判断列-否存在
    *
    * @param db         数据库
    * @param columnName 列名
    */
   public static boolean isColumnExist(SQLiteDatabase db, String tableName, String columnName) {
       boolean result = false;
       Cursor cursor = null;

       try {
           cursor = db.rawQuery("select * from sqlite_master where name = ? and sql like ?"
                   , new String[]{tableName, "%" + columnName + "%"});
           result = null != cursor && cursor.moveToFirst();
       } catch (Exception e) {
           e.printStackTrace();
       } finally {
           if (null != cursor && !cursor.isClosed()) {
               cursor.close();
           }
       }
       return result;
   }

   /***
    *反射获取属性,屏蔽多余字段
    */
   public static Field[] getClassDeclaredFields(Class sClass) {
       List<Field> list = new ArrayList<>();
       Field[] fields = sClass.getDeclaredFields();
       if (fields != null) {
           for (Field field : fields) {
               if (!field.getName().equals("$change") && !field.getName().equals("serialVersionUID")) {
                   list.add(field);
               }
           }
       }
       Field[] fields1 = list.toArray(new Field[]{});
       return list.toArray(new Field[]{});
   }
}

8、查新使用的接口
规范方法

public interface ISelect {
    String tableName();
    String[] columns();
    String selection();
    String[] selectionArgs();
    String groupBy();
    String having();
    String orderBy();
    String limit();
}

9、实现查询的接口

默认都是空,但是查询的表名不可以为空哈,我查询的时候做了判断了~~
public class AbsSelect implements ISelect {
  @Override
  public String tableName() {
      return null;
  }

  @Override
  public String[] columns() {
      return null;
  }
  @Override
  public String selection() {
      return null;
  }
  @Override
  public String[] selectionArgs() {
      return null;
  }
  @Override
  public String groupBy() {
      return null;
  }
  @Override
  public String having() {
      return null;
  }
  @Override
  public String orderBy() {
      return null;
  }
  @Override
  public String limit() {
      return null;
  }

}

10、MainActivity
布局就不写了哈,就四个按钮,对应四个点击事件

public class MainActivity extends AppCompatActivity {

    private List<Student> list = new ArrayList<>();


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        list.add(new Student("小米", 7, "1"));
        list.add(new Student("小明", 8, "2"));
        list.add(new Student("小红", 9, "1"));
    }

    public void 增加(View view) {
        new DataBaseImpl(this, "PersonInfo").insert(list);
    }

    public void 删除(View view) {
        new DataBaseImpl(this, "PersonInfo").delete(new Student("小红", 9, "1"));
    }

    public void 修改(View view) {
        Student student = new Student("小米", 9, "nv");
        new DataBaseImpl(this, "PersonInfo").update(student);

    }

    public void 查看(View view) {
        //查询所有的数据咯
        List<Student> students = new DataBaseImpl(this, "PersonInfo").select(Student.class, new AbsSelect());
    }
}

-----------------------------THE END--------------------------

上一篇下一篇

猜你喜欢

热点阅读