美文网首页
java注解反射实现数据库增删改查

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

作者: 鹅鹅鹅曲项向天歌呀 | 来源:发表于2019-04-01 18:29 被阅读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--------------------------

    相关文章

      网友评论

          本文标题:java注解反射实现数据库增删改查

          本文链接:https://www.haomeiwen.com/subject/hkcpbqtx.html