众所周知在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;
}
}
这边只是简单的介绍了建表和插入,有兴趣的小伙伴还可以完善删改查,以此为基础,还可以编写属于自己的数据库框架。