前言:因为项目很老,还是用的原生sqlite,因为建表还是手动构建sql,cursor转bean或者list都不灵活,特此用反射和 注解做了优化处理
首先创建我们的标注,有TableName,Primary,NotNull,DefaultText,DefaultInt,DefaultDecimal,Autoincrement
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
public @interface TableName {
public String tableName();
}
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
@Documented
public @interface Primary {
}
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface NotNull {
}
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface DefaultText {
public String defaultVal();
}
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface DefaultInt {
public int defaultVal();
}
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface DefaultDecimal {
public double defaultVal();
}
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Autoincrement {
}
然后创建我们的Book类
@TableName(tableName = "book")
public class Book {
@DefaultText(defaultVal = "世纪创奇")
private String name;
@Primary
@Autoincrement
private int id;
@DefaultInt(defaultVal = 2)
private int pages;
@DefaultDecimal(defaultVal = 2.24)
private double price;
@NotNull
private String mem;
private long date;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getPages() {
return pages;
}
public void setPages(int pages) {
this.pages = pages;
}
public double getPrice() {
return price;
}
public void setPrice(double price) {
this.price = price;
}
public String getMem() {
return mem;
}
public void setMem(String mem) {
this.mem = mem;
}
public long getDate() {
return date;
}
public void setDate(long date) {
this.date = date;
}
}
最后创建DbUtil类
public class DbUtil {
private static final String TAG = "DbUtil";
public static final Map<Class<?>, String> TYPES;
static {
//基本类型
TYPES = new HashMap<Class<?>, String>();
TYPES.put(byte.class, "BYTE");
TYPES.put(boolean.class, "INTEGER");
TYPES.put(short.class, "SHORT");
TYPES.put(int.class, "INTEGER");
TYPES.put(long.class, "LONG");
TYPES.put(String.class, "TEXT");
TYPES.put(byte[].class, "BLOB");
TYPES.put(float.class, "FLOAT");
TYPES.put(double.class, "DOUBLE");
//包装类型
TYPES.put(Byte.class, "BYTE");
TYPES.put(Boolean.class, "INTEGER");
TYPES.put(Short.class, "SHORT");
TYPES.put(Integer.class, "INTEGER");
TYPES.put(Long.class, "LONG");
TYPES.put(String.class, "TEXT");
TYPES.put(byte[].class, "BLOB");
TYPES.put(Float.class, "FLOAT");
TYPES.put(Double.class, "DOUBLE");
}
/**
* 根据类结构构造表。
*/
public static String getTableBuildingSQL(Class<?> clazz) {
StringBuilder strBuilder = new StringBuilder("create table if not exists ");
if (clazz.isAnnotationPresent(TableName.class)) {
String tableName = clazz.getAnnotation(TableName.class).tableName();
strBuilder.append(tableName);
} else {
strBuilder.append(clazz.getSimpleName());
}
strBuilder.append("(");
// getDeclaredFields():获取该类文件中声明的字段
// getFields():获取该类public声明字段
Field[] arrField = clazz.getDeclaredFields();
for (int i = arrField.length - 1; i >= 0; i--) {
Field f = arrField[i];
String type = TYPES.get(f.getType());
if (type == null) {
continue;
} else {
strBuilder.append(f.getName() + " " + type);
if (f.isAnnotationPresent(Primary.class)) {
strBuilder.append(" primary key ");
}
if (f.isAnnotationPresent(DefaultText.class)) {
String val = f.getAnnotation(DefaultText.class).defaultVal();
strBuilder.append(" DEFAULT \"" + val + "\"");
}
if (f.isAnnotationPresent(DefaultInt.class)) {
Object val = f.getAnnotation(DefaultInt.class).defaultVal();
strBuilder.append(" DEFAULT " + val);
}
if (f.isAnnotationPresent(DefaultDecimal.class)) {
Object val = f.getAnnotation(DefaultDecimal.class).defaultVal();
strBuilder.append(" DEFAULT " + val);
}
if (f.isAnnotationPresent(Autoincrement.class)) {
strBuilder.append(" AUTOINCREMENT");
}
if(f.isAnnotationPresent(NotNull.class)){
strBuilder.append(" NOT NULL");
}
if (i > 0) {
strBuilder.append(",");
}
}
}
strBuilder.append(")");
return strBuilder.toString();
}
/**
* 构造插入Contvalues
*
* @param bean
* @return
*/
public static ContentValues translate2ContentValues(Object bean) {
ContentValues cv = new ContentValues();
Field[] arrField = bean.getClass().getDeclaredFields();
try {
for (Field f : arrField) {
if (f.isAccessible() == false) {
f.setAccessible(true);
}
//排除自動增長的字段
if (f.isAnnotationPresent(Autoincrement.class)) {
continue;
}
String name = f.getName();
Object value = f.get(bean);
if (value instanceof Byte) {
cv.put(name, (Byte) value);
} else if (value instanceof Short) {
cv.put(name, (Short) value);
} else if (value instanceof Integer) {
cv.put(name, (Integer) value);
} else if (value instanceof Long) {
cv.put(name, (Long) value);
} else if (value instanceof String) {
cv.put(name, (String) value);
} else if (value instanceof byte[]) {
cv.put(name, (byte[]) value);
} else if (value instanceof Boolean) {
cv.put(name, (Boolean) value);
} else if (value instanceof Float) {
cv.put(name, (Float) value);
} else if (value instanceof Double) {
cv.put(name, (Double) value);
}
}
} catch (Exception e) {
Log.e(TAG,"translate2ContentValues error:" + e.getMessage());
}
return cv;
}
/**
* 从cursor中提取bean
*
* @param cursor
* @param cls
* @param <T>
* @return
*/
public static <T> T cursorToBean(Cursor cursor, Class<T> cls) {
T bean = null;
if (cursor != null && cursor.getCount() > 0) {
Field[] fields = cls.getDeclaredFields();
String[] columns = cursor.getColumnNames();
try {
while (cursor.moveToNext()) {
bean = cls.newInstance();
for (String column : columns) {
Field field = findFieldByName(fields, column);
if (field != null) {
String letter = column.substring(0, 1).toUpperCase();
String setter = "set" + letter + column.substring(1);
Method setMethod = cls.getMethod(setter, new Class[]{field.getType()});
setMethod.invoke(bean, getValueByField(cursor, column, field));
}
}
}
} catch (Exception e) {
Log.e(TAG,"cursorToBean error:" + e.getMessage());
}finally {
cursor.close();
}
}
return bean;
}
/**
* 从cursor中提取bean 列表
*
* @param cursor
* @param cls
* @param <T>
* @return
*/
public static <T> List<T> cursorToBeans(Cursor cursor, Class<T> cls) {
List<T> beans = new ArrayList<T>();
if (cursor != null && cursor.getCount() > 0) {
Field[] fields = cls.getDeclaredFields();
String[] columns = cursor.getColumnNames();
try {
while (cursor.moveToNext()) {
T bean = cls.newInstance();
for (String column : columns) {
Field field = findFieldByName(fields, column);
if (field != null) {
String letter = column.substring(0, 1).toUpperCase();
String setter = "set" + letter + column.substring(1);
Method setMethod = cls.getMethod(setter, new Class[]{field.getType()});
setMethod.invoke(bean, getValueByField(cursor, column, field));
}
}
beans.add(bean);
}
} catch (Exception e) {
Log.e(TAG,"cursorToBeans error:" + e.getMessage());
}finally {
cursor.close();
}
}
return beans;
}
/**
* 根据字段取出值
*
* @param cursor
* @param columnName
* @param field
* @return
*/
private static Object getValueByField(Cursor cursor, String columnName, Field field) {
int index = cursor.getColumnIndex(columnName);
if (index == -1) return null;// 如果不存在此列则返回null
Class fieldClass = field.getType();
// 根据属性类型从Cursor中获取值
if (fieldClass == String.class) return cursor.getString(index);
else if (fieldClass == int.class || fieldClass == Integer.class)
return cursor.getInt(index);
else if (fieldClass == Long.class || fieldClass == long.class)
return cursor.getLong(index);
else if (fieldClass == Double.class || fieldClass == double.class)
return cursor.getDouble(index);
else if (fieldClass == Float.class || fieldClass == float.class)
return cursor.getFloat(index);
else if (fieldClass == Short.class || fieldClass == short.class)
return cursor.getShort(index);
return null;
}
private static Field findFieldByName(Field[] fields, String name) {
for (Field field : fields) {
if (field.getName().equals(name)) {
return field;
}
}
return null;
}
}
注释已经解释了每个方法的作用。demo可以通过这个链接下载,http://download.youkuaiyun.com/download/hanshengjian/9771886,这是个module