android 自做一个简单的ORM数据库框架

来源:互联网 发布:税收数据 编辑:程序博客网 时间:2024/05/15 17:22

好久没用过数据库了, 今天突然来精神,花了近四个小时,研究了一下这玩意,在此记录成果


首先创建俩个注解类,表示id和数据库忽略字段

package com.yzx.frames.tool.db.annotation;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;@Target(value = ElementType.FIELD)@Retention(value = RetentionPolicy.RUNTIME)public @interface DBIgnore {}

package com.yzx.frames.tool.db.annotation;import java.lang.annotation.ElementType;import java.lang.annotation.Retention;import java.lang.annotation.RetentionPolicy;import java.lang.annotation.Target;@Target(value = ElementType.FIELD)@Retention(value = RetentionPolicy.RUNTIME)public @interface ID {}


然后创建实体类的帮助方法类:



package com.yzx.frames.tool.db;import java.lang.reflect.Field;import java.util.HashMap;import java.util.Map;import com.yzx.frames.tool.db.annotation.DBIgnore;import com.yzx.frames.tool.db.annotation.ID;public class ClassHelper {/** * 判断实体类的注释是否正确 *  * @param clz */public static void checkAnnotation(Class<?> clz) {int idCount = 0;int ignoreCount = 0;//Field[] fs = clz.getDeclaredFields();//if (fs.length < 1)throw new IllegalArgumentException("实体类没有属性");//for (Field f : fs) {f.setAccessible(true);if (f.getAnnotation(ID.class) != null) {if (f.getType() != Integer.class && f.getType() != String.class)throw new IllegalArgumentException("id只能是int 或 String");idCount++;}if (f.getAnnotation(DBIgnore.class) != null)ignoreCount++;}//if (idCount == 0)throw new IllegalArgumentException("实体类没有id");if (idCount > 1)throw new IllegalArgumentException("实体类id只能有一个");if (fs.length - ignoreCount < 1)throw new IllegalArgumentException("实体类无可用属性");}/** * 同步遍历回调实体类的属性Field *  * @param clz * @param idCallback *            是id的时候回调 * @param colCallback *            普通字段回调 */public static void callUsefullFields(Class<?> clz, FieldCallback idCallback, FieldCallback colCallback) {Field[] fs = clz.getDeclaredFields();for (Field f : fs) {f.setAccessible(true);if (f.getAnnotation(DBIgnore.class) != null)continue;if (f.getAnnotation(ID.class) != null)idCallback.call(f);elsecolCallback.call(f);}}/** * 获取对象中 属性和值的映射map *  * @param obj * @param containsNull *            是否包含值为null的字段 * @return */public static Map<String, Object> getFieldValueMap(final Object obj, final boolean containsNull) {final HashMap<String, Object> map = new HashMap<String, Object>();callUsefullFields(obj.getClass(), new FieldCallback() {// idpublic void call(Field f) {try {Object value = f.get(obj);if (!containsNull) {if (value != null)map.put(f.getName(), value);} elsemap.put(f.getName(), value);} catch (Exception e) {}}}, new FieldCallback() {// 普通public void call(Field f) {try {Object value = f.get(obj);if (!containsNull) {if (value != null)map.put(f.getName(), value);} elsemap.put(f.getName(), value);} catch (Exception e) {}}});return map;}/** * 获取对象主键的值 *  * @return */public static String getPrimaryKeyValue(Object obj) {Field[] fs = obj.getClass().getDeclaredFields();for (Field f : fs) {f.setAccessible(true);if (f.getAnnotation(ID.class) != null)try {return f.get(obj).toString();} catch (Exception e) {}}return null;}}

创建回调接口


package com.yzx.frames.tool.db;import java.lang.reflect.Field;public interface FieldCallback {void call(Field f);}


然后创建sql语句帮助类


package com.yzx.frames.tool.db;import java.lang.reflect.Field;import com.yzx.frames.tool.db.annotation.ID;public class SqlGetter {/** * 创建表的sql *  * @param clz * @return */public static String getCreateTable(Class<?> clz) {ClassHelper.checkAnnotation(clz);//String start = "CREATE TABLE  IF NOT EXISTS " + getTableName(clz);//final StringBuffer sbb = new StringBuffer();ClassHelper.callUsefullFields(clz, new FieldCallback() {// idpublic void call(Field fi) {if (fi.getType() == Integer.class)sbb.append(fi.getName() + " INTEGER PRIMARY KEY AUTOINCREMENT,");else if (fi.getType() == String.class)sbb.append(fi.getName() + " TEXT PRIMARY KEY ,");}}, new FieldCallback() {// 普通public void call(Field fi) {sbb.append(fi.getName() + " TEXT,");}});sbb.deleteCharAt(sbb.length() - 1);//String sql = new StringBuffer().append(start).append(" (").append(sbb.toString()).append(")").toString();return sql;}/** * 获取 获取全部数据的 sql *  * @param clz * @return */public static String getGetSql(Class<?> clz, String where) {return "SELECT * FROM " + getTableName(clz) + " WHERE " + where;}/** * 获取表名称 *  * @param clz * @return */public static String getTableName(Class<?> clz) {return clz.getName().replaceAll("\\.", "_");}/** * 获取id属性名称 *  * @param clz * @return 没有返回null */public static String getPrimaryKeyName(Class<?> clz) {Field[] fs = clz.getDeclaredFields();for (Field f : fs) {f.setAccessible(true);if (f.getAnnotation(ID.class) != null)return f.getName();}return null;}}

最后是主要的方法操作类

package com.yzx.frames.tool.db;import java.io.File;import java.lang.reflect.Field;import java.util.ArrayList;import java.util.List;import java.util.Map;import android.app.Application;import android.content.ContentValues;import android.database.Cursor;import android.database.sqlite.SQLiteDatabase;public class DBManager {private DBManager() {}private SQLiteDatabase db;public boolean save(Object obj) {Map<String, Object> map = ClassHelper.getFieldValueMap(obj, false);ContentValues cv = new ContentValues();for (Map.Entry<String, Object> en : map.entrySet())cv.put(en.getKey(), en.getValue().toString());long c = db.insert(SqlGetter.getTableName(obj.getClass()), null, cv);return c > 0;}public void save(List<Object> list) {db.beginTransaction();for (Object obj : list)save(obj);db.setTransactionSuccessful();}public boolean deleteById(Class<?> clz, String id) {String table = SqlGetter.getTableName(clz);String idName = SqlGetter.getPrimaryKeyName(clz);int c = db.delete(table, idName + " = '" + id + "'", null);return c > 0;}public boolean deleteByWhere(Class<?> clz, String where) {String table = SqlGetter.getTableName(clz);int c = db.delete(table, where, null);return c > 0;}public boolean update(Object obj, String idValue) {String tableName = SqlGetter.getTableName(obj.getClass());String idName = SqlGetter.getPrimaryKeyName(obj.getClass());Map<String, Object> map = ClassHelper.getFieldValueMap(obj, false);ContentValues cv = new ContentValues();for (Map.Entry<String, Object> en : map.entrySet())cv.put(en.getKey(), en.getValue().toString());int c = db.update(tableName, cv, idName + " = '" + idValue + "'", null);return c > 0;}public List<Object> getByWhere(Class<?> clz, String where) {final Cursor cur = db.rawQuery(SqlGetter.getGetSql(clz, where), null);ArrayList<Object> list = new ArrayList<Object>(0);if (cur != null && cur.getCount() > 0)while (cur.moveToNext()) {try {final Object ins = Class.forName(clz.getName()).newInstance();ClassHelper.callUsefullFields(ins.getClass(), new FieldCallback() {// idpublic void call(Field f) {setFieldValue(f, ins, cur.getString(cur.getColumnIndex(f.getName())));}}, new FieldCallback() {// 普通public void call(Field f) {setFieldValue(f, ins, cur.getString(cur.getColumnIndex(f.getName())));}});list.add(ins);} catch (Exception e) {}}closeCursor(cur);return list;}public List<Object> getAll(Class<?> clz) {return getByWhere(clz, "1 = 1");}public void close() {if (db != null)db.close();db = null;}//// ------------------------------------- priavte ↓-----------------------------------//private void setFieldValue(Field f, Object obj, Object value) {try {f.set(obj, value);} catch (Exception e) {}}private void closeCursor(Cursor c) {if (c != null)c.close();}//// ------------------------------------- static ↓ -------------------------------------//@SuppressWarnings("unused")private static Application context;private static File dbDir;/** * 初始化 *  * @param context * @param dbDir *            存储数据库的文件夹路径 */public static void init(Application context, String dbDir) {DBManager.context = context;DBManager.dbDir = new File(dbDir);DBManager.dbDir.mkdirs();}/** * 打开数据库 *  * @param dbName *            数据库名称 * @param clz *            对应的实体类的class * @return *  */public static DBManager open(String dbName, Class<?> clz) {DBManager dbm = new DBManager();{SQLiteDatabase db = SQLiteDatabase.openOrCreateDatabase(new File(dbDir, dbName + ".db"), null);db.execSQL(SqlGetter.getCreateTable(clz));dbm.db = db;}return dbm;}}



使用示例 :


首先在Application中写上:


DBManager.init(this, getFilesDir().getAbsolutePath());//第二个参数为数据库文件存储未知路径


Activity 中:

package com.yzx.frames.main;import java.util.List;import android.app.Activity;import android.os.Bundle;import android.widget.Toast;import com.yzx.frames.R;import com.yzx.frames.tool.db.DBManager;public class MainActivity extends Activity {private DBManager db;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);db = DBManager.open("test_db", Person.class);Person p = new Person();// 一个简单的实体类p.setAge("99");p.setName("yzx");p.setNumber("001");boolean b = db.save(p);Toast.makeText(this, b + "", Toast.LENGTH_SHORT).show();// true 表示存储成功 false 表示存储失败}@Overrideprotected void onDestroy() {super.onDestroy();if (db != null)db.close();}@Overridepublic void onBackPressed() {List<Object> list = db.getAll(Person.class);if (list.size() > 0)Toast.makeText(this, ((Person) (list.get(0))).getNumber() + "", Toast.LENGTH_SHORT).show();}}


Person实体类 :


package com.yzx.frames.main;import java.io.Serializable;import com.yzx.frames.tool.db.annotation.DBIgnore;import com.yzx.frames.tool.db.annotation.ID;public class Person implements Serializable {@DBIgnoreprivate static final long serialVersionUID = 4985156148924823533L;private String name;private String age;@IDprivate String number;public String getName() {return name;}public void setName(String name) {this.name = name;}public String getAge() {return age;}public void setAge(String age) {this.age = age;}public String getNumber() {return number;}public void setNumber(String number) {this.number = number;}}


没了

0 0
原创粉丝点击