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());
}
}