[Android] 数据实体的自动存取--SQLite篇
本例代码以SQLite为数据存取载体。
在"SharedPreferences篇"中,已知数据的自动存储原理是使用Java反射的方法获取数据实体类中的Field进行的存储的。
当以SQLite为数据存取载体时,需要解决一个问题是:如何标明类中的某个Field是primary key(主键)呢。
为解决此问题,此处引入并使用了Java Annotation(内注)。Annotation可以保留一些自定义的注释信息并且这些可以在被编译后仍保留着甚至被JVM运行时获取。相应文章请查看:[Java] Annotation(内注)实例一则
本示例代码实现了一个Mark Annotation(标记内注),用于修饰Field标明其为主键。
被修饰的主键将影响自动生成的sql执行语句。如下代码:
package lab.sodino.autosave;import java.lang.reflect.Field;import android.content.ContentValues;import android.database.Cursor;import lab.sodino.autosave.annotation.primary;public class GoodsBean {@primary/** 标明了是主键*/public long _id;public String name;public int price;public boolean isPaid;/** 测试用。 */public byte testByte;public byte[] arrByte;/** 测试用。 */public short testShort;public float cicle;public double testDouble;public String toString() {StringBuffer strBuffer = new StringBuffer();strBuffer.append("_id[" + _id + "]\n");strBuffer.append("name[" + name + "]\n");strBuffer.append("price[" + price + "]\n");strBuffer.append("isPaid[" + isPaid + "]\n");strBuffer.append("cicle[" + cicle + "]\n");strBuffer.append("testByte[" + testByte + "]\n");strBuffer.append("arrByte.len[" + (arrByte == null ? "N/A" : arrByte.length) + "]\n");strBuffer.append("testShort[" + testShort + "]\n");strBuffer.append("testDouble[" + testDouble + "]\n");return strBuffer.toString();}public static GoodsBean newInstance() {GoodsBean bean = new GoodsBean();bean._id = 128l;bean.name = "AutoSave";bean.price = 1024;bean.isPaid = true;bean.cicle = 2.356f;bean.arrByte = new String("SodinoArrBytes").getBytes();bean.testByte = 8;bean.testShort = 128;bean.testDouble = 9856.2145d;return bean;}public static ContentValues translate2ContentValues(GoodsBean bean) {ContentValues cv = new ContentValues();Field[] arrField = GoodsBean.class.getFields();try {for (Field f : arrField) {if (f.isAccessible() == false) {f.setAccessible(true);}String name = f.getName();Object value = f.get(bean);LogOut.out(GoodsBean.class.getName(), "name:" + name + " " + String.valueOf(value));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 (IllegalArgumentException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();}return cv;}public static GoodsBean cursor2GoodsBean(Cursor cursor) {GoodsBean bean = new GoodsBean();if (cursor.isBeforeFirst()) {cursor.moveToFirst();}Field[] arrField = GoodsBean.class.getFields();try {for (Field f : arrField) {String columnName = f.getName();int columnIdx = cursor.getColumnIndex(columnName);if (columnIdx != -1) {if (f.isAccessible()) {f.setAccessible(true);}Class<?> type = f.getType();if (type == byte.class) {f.set(bean, (byte) cursor.getShort(columnIdx));} else if (type == short.class) {f.set(bean, cursor.getShort(columnIdx));} else if (type == int.class) {f.set(bean, cursor.getInt(columnIdx));} else if (type == long.class) {f.set(bean, cursor.getLong(columnIdx));} else if (type == String.class) {f.set(bean, cursor.getString(columnIdx));} else if (type == byte[].class) {f.set(bean, cursor.getBlob(columnIdx));} else if (type == boolean.class) {f.set(bean, cursor.getInt(columnIdx) == 1);} else if (type == float.class) {f.set(bean, cursor.getFloat(columnIdx));} else if (type == double.class) {f.set(bean, cursor.getDouble(columnIdx));}}}} catch (IllegalArgumentException e) {e.printStackTrace();} catch (IllegalAccessException e) {e.printStackTrace();}return bean;}}