手把手带你撸一套Android简易ORM框架

Posted LeBron_Six

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了手把手带你撸一套Android简易ORM框架相关的知识,希望对你有一定的参考价值。

ORM概念

对象关系映射(Object Relational Mapping),通俗来讲就是建立关系型数据库与业务实体对象之间作一个映射关系。对于Java后端来说,例如mybatis、hibernate等,在android平台下,常见的数据库映射框架有 GreenDAO、Realm等。废话不多说,进入正题!

实体模型建立

既然是映射,自然需要对数据库表的字段结构与实体类之间建立一个连接关系。我们采用注解,来通过实体类生成一个表的结构。

注解列

ID

通过 @Id 注解来标识表的ID字段。

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Id 

主键

通过 @Unique 注解来标识一个主键。

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Unique 

自增长

通过 @AutoIncrement 注解来标识一个自增长的键。

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface AutoIncrement 

数据表的列

通过 @Column 注解来标识数据表的一个列,默认不能为null,可通过 nullable 属性修改。

@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface Column 

    boolean nullable() default false;

实体基类

首先,每一个表都有一个唯一的id,所以我们建立的基类里,包含了这个自增长的id。

public abstract class BaseEntity 

    @Id
    @AutoIncrement
    private Integer id; // 通过 @Id 与 @AutoIncrement 注解标识为自增长id

    public BaseEntity() 
    

    public Integer getId() 
        return id;
    

    public void setId(Integer id) throws DBException 
        if (id < 1) 
            throw new DBException(ErrMsg.ERR_INVALID_ID);
        
        this.id = id;
    

每一个继承实体基类的实体类,都必须生成他的 getset 方法,对于 boolean 来说,为了便于存储与操作,我们在数据库应当把它转换为 1 和 0 的模式。例如:

public class BookConfig extends BaseEntity 

    @Column
    protected String book_num;

    @Column
    protected String setting_key;

    @Column(nullable = true)
    protected String setting_value = "";

    @Column
    protected int status;

    @Column(nullable = true)
    protected int isModify = 1;

    public BookConfig() 
    

    public BookConfig(String book_num, String setting_key) 
        this.book_num = book_num;
        this.setting_key = setting_key;
    

    public String getBook_num() 
        return book_num;
    

    public void setBook_num(String book_num) 
        this.book_num = book_num;
    

    public String getSetting_key() 
        return setting_key;
    

    public void setSetting_key(String setting_key) 
        this.setting_key = setting_key;
    

    public String getSetting_value() 
        return setting_value;
    

    public void setSetting_value(String setting_value) 
        this.setting_value = setting_value;
    

    public int getStatus() 
        return status;
    

    public void setStatus(int status) 
        this.status = status;
    

    public int getIsModify() 
        return isModify;
    

    public void setIsModify(int isModify) 
        this.isModify = isModify;
    

这样,就创建了一个实体类了。为什么要去生成他的 getset 方法呢?这是因为我们需要通过反射来取出每一个字段,然后通过 getset 方法去设置字段的值。后面还会提到!

实体类映射成表结构

有个实体类之后,我们就需要把这个实体类转换成一个数据表,通过 @Column 注解去寻找实体类的每一个字段,然后拼接生成对应的SQL语句。

/**
  * 生成建表的SQL语句
  *
  * @param clazz        实体类
  * @param strTableName 表名字
  * @return
  */
 public static String genCreateTableSQL(Class clazz, String strTableName) 
     boolean isHaveKeyId = false;
     boolean isHaveColumnAnnotation = false;
     String strIdName = null;

     // 反射获取实体类的所有字段 
     Field[] fields = Utils.getDeclaredField(clazz);
     if (fields.length <= 0)
         return null;

     StringBuilder sb = new StringBuilder("CREATE TABLE IF NOT EXISTS " + strTableName + " ( ");
     StringBuilder sbUnique = new StringBuilder("");

     for (Field field : fields)  
         // 添加 自增长id
         if (field.isAnnotationPresent(Id.class)) 
             // 一个表只能有一个id
             if (isHaveKeyId)
                 continue;

             isHaveColumnAnnotation = true;

             Id id = field.getAnnotation(Id.class);
             strIdName = getColumnName(field);
             sb.append(strIdName);
             sb.append(" ");

             // type
             sb.append(fieldType2DBType(field.getGenericType().toString()));
             sb.append(" ");

             // primary key
             sb.append("NOT NULL PRIMARY KEY ");

             // is auto-increment
             if (field.isAnnotationPresent(AutoIncrement.class)
                     && (field.getGenericType().toString().equals("class java.lang.Integer") || field
                     .getGenericType().toString().equals("int"))) 
                 sb.append("AUTOINCREMENT");
             
             sb.append(",");

             isHaveKeyId = true;
          else if (field.isAnnotationPresent(Column.class))  
             // 添加其他列
             Column col = field.getAnnotation(Column.class);
             String strColName = getColumnName(field);
             sb.append(strColName);
             sb.append(" ");

             // 数据类型
             sb.append(fieldType2DBType(field.getGenericType().toString()));

             // 是否可以为空
             boolean canBeNull = col.nullable();
             if (!canBeNull) 
                 sb.append(" NOT NULL");
             
             sb.append(",");

             // is unique
             if (field.isAnnotationPresent(Unique.class)) 
                 sbUnique.append("CONSTRAINT \\"u" + strColName.toLowerCase() + "\\" UNIQUE (\\"" + strColName + "\\"),");
             
             isHaveColumnAnnotation = true;
         
     

     // nothing
     if (!isHaveColumnAnnotation && !isHaveKeyId)
         return null;

     // unique
     sb.append("CONSTRAINT \\"u" + strIdName.toLowerCase() + "\\" UNIQUE (\\"" + strIdName + "\\")");
     if (sbUnique.length() > 0) 
         sb.append(",");
         sb.append(sbUnique.deleteCharAt(sbUnique.length() - 1));
     
     // end
     sb.append(" )");

     return sb.toString();
 

/**
 * Java属性类型转换为数据库数据类型
 *
 * @param fieldGenericTyp
 * @return
 */
private static String fieldType2DBType(String fieldGenericTyp) 
    if (fieldGenericTyp.equals("class java.lang.String")) 
        return "VARCHAR";
     else if (fieldGenericTyp.equals("class java.lang.Boolean") || fieldGenericTyp.equals("boolean")
            || fieldGenericTyp.equals("class java.lang.Integer") || fieldGenericTyp.equals("int")
            || fieldGenericTyp.equals("class java.lang.Long") || fieldGenericTyp.equals("long")
            || fieldGenericTyp.equals("class java.lang.Short") || fieldGenericTyp.equals("short")
            || fieldGenericTyp.equals("class java.lang.Byte") || fieldGenericTyp.equals("byte")) 
        return "INTEGER";
     else if (fieldGenericTyp.equals("class [B")) 
        return "BLOB";
     else if (fieldGenericTyp.equals("class java.lang.Float") || fieldGenericTyp.equals("float")) 
        return "float";
     else if (fieldGenericTyp.equals("class java.lang.Double") || fieldGenericTyp.equals("double")) 
        return "double";
    
    return null;

这样的话,我们只要调用以下代码,就可以生成SQL语句。例如:

String sql = ORMUtils.genCreateTableSQL(BookConfig.class, "book_config");

数据库操作封装

表创建完之后,我们就需要封装一些基本数据库操作的方法,也就是增删改查。 首先,建立一个操作方法接口:

public interface IDAO<T extends BaseEntity> 

    /**
     * get the sqlite database object
     *
     * @return
     */
    SQLiteDatabase getDatabase();

    /**
     * init table name and entityClass
     *
     * @param tableName
     * @param clazz
     */
    void initTable(String tableName, Class<T> clazz);

    /**
     * get count of entities
     *
     * @return
     * @throws DBException
     */
    long getCount() throws DBException;

    boolean isTableExist(String tableName) throws DBException;

    /**
     * check table exists
     *
     * @return
     * @throws DBException
     */
    boolean isTableExist() throws DBException;

    /**
     * create table
     *
     * @throws DBException
     */
    void createTable() throws DBException;

    /**
     * create table
     *
     * @param tableName table name
     * @throws DBException
     */
    <T> void createTable(Class<T> entityClass, String tableName) throws DBException;

    /**
     * drop table
     *
     * @throws DBException
     */
    void dropTable() throws DBException;

    /**
     * drop all table
     *
     * @throws DBException
     */
    void dropAllTable() throws DBException;

    /**
     * save database entity
     *
     * @param entity
     * @throws DBException
     */
    void save(T entity) throws DBException;

    /**
     * delete database entity by id(primary key)
     *
     * @param id
     * @throws DBException
     */
    void delete(int id) throws DBException;

    /**
     * delete database entity by ids(primary key)
     *
     * @param ids
     * @throws DBException
     */
    void delete(int[] ids) throws DBException;

    /**
     * delete all data
     *
     * @throws DBException
     */
    void deleteAll() throws DBException;

    /**
     * update entity
     *
     * @param entity
     * @throws DBException
     */
    void update(T entity) throws DBException;

    /**
     * update entity by a condition string
     *
     * @param condition part of the update SQL command after keyword 'WHERE'
     *                  (i.e."UPDATE Person SET age = 35 WHERE condition")
     *                  (e.g. condition -- "name = 'Richard' OR name = 'Jefferson'")
     * @param entity
     * @throws DBException
     */
    void updateByCondition(String condition, T entity) throws DBException;

    /**
     * find entity by id
     *
     * @param id
     * @return
     * @throws DBException
     */
    T find(int id) throws DBException;

    /**
     * find last entity
     *
     * @return
     * @throws DBException
     */
    T findLastEntity() throws DBException;

    /**
     * find entities by a condition string
     *
     * @param condition part of the select SQL command after keyword 'WHERE'
     *                  (i.e."SELECT * FROM Person WHERE condition")
     *                  (e.g. condition -- "name = 'Richard' OR name = 'Jefferson'")
     * @return
     */
    List<T> findByCondition(String condition) throws DBException;

    /**
     * find all entities
     *
     * @return
     * @throws DBException
     */
    List<T> findAll() throws DBException;

接口主要封装了一些比较常用的增删改查方法,当然了,特别复杂的操作,还是需要配合SQL语句来进行执行,但是这样已经可以满足一些常用的基本操作了。

接着我们需要来具体实现这一系列方法:

public class DAO<T extends BaseEntity> extends SQLiteOpenHelper implements IDAO<T> 

    private Context mContext;

    private String mDBName;
    private String mTableName;
    private int mVersion;

    private SQLiteDatabase db;
    private Field[] fields;
    private Class<T> entityClass;

    public DBUpdateInfo info = new DBUpdateInfo();

    /**
     * constructor. only for operate the database and cannot operate the specified table.
     *
     * @param context to use to open or create the database
     * @param dbName  of the database name, it will be stored in /data/data/%package_name%/files
     * @param version number of the database (starting at 1)
     */
    public DAO(Context context, String dbName, int version) 
        this(context, dbName, null, null, version);
    

    /**
     * constructor
     *
     * @param context     to use to open or create the database
     * @param dbName      of the database name, it will be stored in /data/data/%package_name%/files
     * @param tableName   the name of table to needs to be operated
     * @param entityClass class for entity
     * @param version     number of the database (starting at 1)
     */
    public DAO(Context context, String dbName, String tableName, Class<T> entityClass, int version) 
        super(context, dbName, null, version);

        this.mContext = context;
        this.mDBName = dbName;
        this.mTableName = tableName;
        this.mVersion = version;

        this.db = getWritableDatabase();
        this.fields = Utils.getDeclaredField(entityClass);
        this.entityClass = entityClass;
    

    @Override
    public void onCreate(SQLiteDatabase db) 

    

    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) 
        info.isUpdate = true;
        info.from = oldVersion;
        info.to = newVersion;
    

    @Override
    public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) 
        info.isUpdate = true;
        info.from = oldVersion;
        info.to = newVersion;
    

    @Override
    public void initTable(String tableName, Class<T> clazz) 
        this.mTableName = tableName;
        this.entityClass = clazz;

        this.fields = Utils.getDeclaredField(entityClass);
    

    @Override
    public SQLiteDatabase getDatabase() 
        return db == null ? (db = getWritableDatabase()) : db;
    

    @Override
    public long getCount() throws DBException 
        if (TextUtils.isEmpty(mTableName))
            return 0;

        try 
            openDB(true);

            String sql = "SELECT COUNT(*) FROM " + mTableName;
            LogUtils.d(sql);

            Cursor cursor = db.rawQuery(sql, null);
            cursor.moveToFirst();
            long total = cursor.getLong(0);
            return total;
         catch (Exception e) 
            throw new DBException(ErrMsg.ERR_GET_COUNT);
         finally 
            closeDB();
        
    

    @Override
    public boolean isTableExist(String tableName) throws DBException 
        boolean isExist = false;
        if (TextUtils.isEmpty(tableName))
            return isExist;

        try 
            openDB(false);

            String sql = "SELECT COUNT(*) FROM Sqlite_master WHERE TYPE ='table' AND NAME ='" + tableName.trim() + "' ";
            LogUtils.d(sql);
            Cursor cursor = db.rawQuery(sql, null);
            if (cursor.moveToNext()) 
                int count = cursor.getInt(0);
                if (count > 0) 
                    isExist = true;
                
            
            return isExist;
         catch (Exception e) 
            throw new DBException(ErrMsg.ERR_IS_TABLE_EXISTS);
         finally 
            closeDB();
        
    

    @Override
    public boolean isTableExist() throws DBException 
        return !TextUtils.isEmpty(mTableName) && isTableExist(mTableName);
    

    @Override
    public void createTable() throws DBException 
        createTable(entityClass, mTableName);
    

    @Override
    public <T> void createTable(Class<T> entityClass, String tableName) throws DBException 
        try 
            openDB(true);

            String sql = ORMUtils.genCreateTableSQL(entityClass, tableName);
            LogUtils.i(sql);
            db.execSQL(sql);
         catch (Exception e) 
            e.printStackTrace();
            throw new DBException(ErrMsg.ERR_CREATE_TABLE, e);
         finally 
            closeDB();
        
    

    @Override
    public void dropTable() throws DBException 
        try 
            openDB(true);

            String sql = "DROP TABLE " + mTableName;
            LogUtils.d(sql);
            db.beginTransaction();
            db.execSQL(sql);
            db.setTransactionSuccessful();
         catch (Exception e) 
            throw new DBException(ErrMsg.ERR_DROP_TABLE, e);
         finally 
            db.endTransaction();
            closeDB();
        
    

    @Override
    public void dropAllTable() throws DBException 
        String strTabSql = "select name from sqlite_master where type='table' order by name";
        LogUtils.d("dropAllTable:" + strTabSql);

        try 
            openDB(false);

            db.beginTransaction();
            Cursor cursor = db.rawQuery(strTabSql, null);
            while (cursor.moveToNext()) 
                String name = cursor.getString(0);
                if (name.equals("sqlite_sequence")) 
                    continue;
                
                String sql = "DROP TABLE " + name;
                LogUtils.d(sql);
                db.execSQL(sql);
            
            db.setTransactionSuccessful();
         catch (Exception e) 
            e.printStackTrace();
            throw new DBException(ErrMsg.ERR_DROP_TABLE, e);
         finally 
            db.endTransaction();
            closeDB();
        
    

    @Override
    public void save(T entity) throws DBException 
        ContentValues values;
        try 
            openDB(true);

            values = Utils.putValue(fields, entity);
            if (values == null || values.size() <= 0) 
                throw new DBException(ErrMsg.ERR_SAVE_PARAM);
            

            long flag = db.insert(mTableName, null, values);
            if (flag < 1) 
                throw new DBException(ErrMsg.ERR_SAVE_PARAM);
            
         catch (Exception e) 
            throw new DBException(ErrMsg.ERR_SAVE_PARAM, e);
         finally 
            closeDB();
        
    

    @Override
    public void delete(int id) throws DBException 
        delete(new int[]id);
    

    @Override
    public void delete(int[] ids) throws DBException 
        int length = ids == null ? 0 : ids.length;
        if (length <= 0) 
            throw new DBException(ErrMsg.ERR_DEL_PARAM);
        

        Field pkField = ORMUtils.getPKField(fields);
        if (pkField == null) 
            throw new DBException(ErrMsg.ERR_GET_PRIMARY_KEY);
        

        Class pkType = pkField.getType();
        String columnName = ORMUtils.getColumnName(pkField);

        try 
            openDB(true);

            StringBuilder sbSql = new StringBuilder("DELETE FROM " + mTableName + " WHERE " + columnName);

            if (ids.length == 1) 
                sbSql.append(" = ");
             else 
                sbSql.append(" in (");
            

            String strSep = "";
            if (pkType == String.class) 
                strSep = "'";
            

            StringBuilder strEntityIds = new StringBuilder("");
            for (Serializable id : ids) 
                strEntityIds.append(strSep);
                strEntityIds.append(id);
                strEntityIds.append(strSep);
                strEntityIds.append(",");
            
            strEntityIds.deleteCharAt(strEntityIds.length() - 1);
            sbSql.append(strEntityIds.toString());

            if (ids.length > 1) 
                sbSql.append(")");
            
            LogUtils.d(sbSql.toString());
            db.execSQL(sbSql.toString());
         catch (Exception e) 
            throw new DBException(ErrMsg.ERR_DEL, e);
         finally 
            closeDB();
        
    

    @Override
    public void deleteAll() throws DBException 
        try 
            openDB(true);

            String delSql = "DELETE FROM " + mTableName;
            String revSeqSql = "UPDATE SQLITE_SEQUENCE SET SEQ=0 WHERE NAME='" + mTableName + "'";

            db.beginTransaction();
            db.execSQL(delSql);
            db.execSQL(revSeqSql);
            db.setTransactionSuccessful();

            LogUtils.d(delSql);
            LogUtils.d(revSeqSql);
         catch (Exception e) 
            throw new DBException(ErrMsg.ERR_DEL, e);
         finally 
            db.endTransaction();
            closeDB();
        
    

    @Override
    public void update(T entity) throws DBException 
        if (entity == null) 
            throw new DBException(ErrMsg.ERR_UPDATE_PARAM);
        

        Field pkField = ORMUtils.getPKField(fields);
        if (pkField == null) 
            throw new DBException(ErrMsg.ERR_GET_PRIMARY_KEY);
        

        Object pkValue = Utils.getPropValue(entity, pkField, entityClass);
        if (pkValue == null) 
            throw new DBException(ErrMsg.ERR_GET_PRIMARY_KEY_VALUE);
        

        ContentValues values;

        try 
            openDB(true);

            values = Utils.putValue(fields, entity);
            if (values.size() <= 0) 
                throw new DBException(ErrMsg.ERR_UPDATE_PARAM);
            

            int flag = db.update(mTableName, values, pkField.getName() + "=?",
                    new String[]String.valueOf(pkValue));
            if (flag < 1) 
                throw new DBException(ErrMsg.ERR_UPDATE_PARAM);
            
         catch (Exception e) 
            throw new DBException(ErrMsg.ERR_UPDATE, e);
         finally 
            closeDB();
        
    

    @Override
    public void updateByCondition(String condition, T entity) throws DBException 
        if (entity == null) 
            throw new DBException(ErrMsg.ERR_UPDATE_PARAM);
        

        ContentValues values;

        try 
            openDB(true);

            values = Utils.putValue(fields, entity);
            values.remove("id");
            if (values.size() <= 0) 
                throw new DBException(ErrMsg.ERR_UPDATE_PARAM);
            

            int flag = db.update(mTableName, values, condition, null);
            if (flag < 1) 
                throw new DBException(ErrMsg.ERR_UPDATE_PARAM);
            

         catch (Exception e) 
            throw new DBException(ErrMsg.ERR_UPDATE, e);
         finally 
            closeDB();
        
    

    @Override
    public T find(int id) throws DBException 
        Field pkField = ORMUtils.getPKField(fields);
        if (pkField == null) 
            throw new DBException(ErrMsg.ERR_GET_PRIMARY_KEY);
        

        String columnName = ORMUtils.getColumnName(pkField);
        try 
            openDB(true);

            String sql = "SELECT * FROM " + mTableName + " WHERE " + columnName + "=?";
            LogUtils.d(sql);
            Cursor cursor = db.rawQuery(sql, new String[]id + "");
            List<T> objList = Utils.cursor2Entity(entityClass, cursor);
            if (objList != null && objList.size() > 0) 
                return objList.get(0);
            
         catch (Exception e) 
            throw new DBException(ErrMsg.ERR_FIND, e);
         finally 
            closeDB();
        
        return null;
    

    @Override
    public T findLastEntity() throws DBException 
        Field pkField = ORMUtils.getPKField(fields);
        if (pkField == null) 
            throw new DBException(ErrMsg.ERR_GET_PRIMARY_KEY);
        

        String columnName = ORMUtils.getColumnName(pkField);
        try 
            openDB(true);

            String sql = "SELECT * FROM " + mTableName + " ORDER BY " + columnName + " desc LIMIT 1";
            LogUtils.d(sql);
            Cursor cursor = db.rawQuery(sql, new String[]);
            List<T> objList = Utils.cursor2Entity(entityClass, cursor);
            if (objList != null && objList.size() > 0) 
                return objList.get(0);
            
         catch (Exception e) 
            throw new DBException(ErrMsg.ERR_FIND, e);
         finally 
            closeDB();
        
        return null;
    

    @Override
    public List<T> findByCondition(String condition) throws DBException 
        if (TextUtils.isEmpty(condition)) 
            throw new DBException(null);
        

        try 
            openDB(true);

            String sql = "SELECT * FROM " + mTableName + " WHERE " + condition;
            LogUtils.d(sql);
            Cursor cursor = db.rawQuery(sql, new String[]);
            List<T> objList = Utils.cursor2Entity(entityClass, cursor);
            if (objList != null && objList.size() > 0) 
                return objList;
            
         catch (Exception e) 
            throw new DBException(null);
         finally 
            closeDB();
        
        return null;
    

    @Override
    public List<T> findAll() throws DBException 
        try 
            openDB(true);

            String sql = "SELECT * FROM " + mTableName;
            LogUtils.d(sql);
            Cursor cursor = db.rawQuery(sql, new String[]);
            List<T> objList = Utils.cursor2Entity(entityClass, cursor);
            if (objList != null && objList.size() > 0) 
                return objList;
            
         catch (Exception e) 
            throw new DBException(ErrMsg.ERR_FIND, e);
         finally 
            closeDB();
        
        return null;
    

    /**
     * Create and/or open a database that will be used for reading and writing.
     *
     * @param checkTable True if need check mTableName, false otherwise
     * @throws DBException
     */
    private void openDB(boolean checkTable) throws DBException 
        if (checkTable && TextUtils.isEmpty(mTableName)) 
            throw new DBException(ErrMsg.ERR_IS_TABLE_EXISTS);
        
        db = getWritableDatabase();
    

    /**
     * Releases a reference to the database
     * closing the database if the last reference was released.
     */
    private void closeDB() 
        if (db != null && db.isOpen()) 
            db.close();
        
    

    /**
     * database version update information
     */
    public class DBUpdateInfo 
        public boolean isUpdate = false;
        public int from;
        public int to;
    

那么,数据库查询出来的行,如何转换为实体呢? 就是通过实体类的 set 方法去赋值。


/**
  * 数据库查询->实体对象
  */
public static <T extends BaseEntity> List<T> cursor2Entity(Class<T> clazz, Cursor cursor) throws DBException 
    List<T> objList = new ArrayList<>();
    Field[] fields = getDeclaredField(clazz);
    try 
        if (cursor.moveToFirst()) 
            while (!cursor.isAfterLast()) 
                T obj = clazz.newInstance();

                for (int i = 0; i < cursor.getColumnCount(); i++) 
                    String strColName = cursor.getColumnName(i);
                    for (Field field : fields) 
                        if (field.getName().equals(strColName)) 
                            strColName = toUpperCaseFirstOne(strColName);
                            if (cursor.getType(i) == Cursor.FIELD_TYPE_NULL) 
                                continue;
                             else if (cursor.getType(i) == Cursor.FIELD_TYPE_FLOAT) 
                                clazz.getMethod("set" + strColName, field.getType()).invoke(obj,
                                        cursor.getFloat(i));
                             else if (cursor.getType(i) == Cursor.FIELD_TYPE_INTEGER) 
                                if (field.getGenericType().toString().equals("class java.lang.Boolean")
                                        || field.getGenericType().toString().equals("boolean")) 
                                    // e.g. boolean isOk; public boolean isOk() return isOk;    public void setOk()
                                    clazz.getMethod("set" + strColName.replaceFirst("Is", ""), field.getType()).invoke(obj,
                                            cursor.getInt(i) == 1 ? true : false);
                                 else if (field.getGenericType().toString().equals("class java.lang.Integer")
                                        || field.getGenericType().toString().equals("int")) 
                                    clazz.getMethod("set" + strColName, field.getType()).invoke(obj,
                                            cursor.getInt(i));
                                 else if (field.getGenericType().toString().equals("class java.lang.Long")
                                        || field.getGenericType().toString().equals("long")) 
                                    clazz.getMethod("set" + strColName, field.getType()).invoke(obj,
                                            (long) cursor.getInt(i));
                                 else if (field.getGenericType().toString().equals("class java.lang.Short")
                                        || field.getGenericType().toString().equals("short")) 
                                    clazz.getMethod("set" + strColName, field.getType()).invoke(obj,
                                            (short) cursor.getInt(i));
                                 else if (field.getGenericType().toString().equals("class java.lang.Byte")
                                        || field.getGenericType().toString().equals("byte")) 
                                    clazz.getMethod("set" + strColName, field.getType()).invoke(obj,
                                            (byte) cursor.getInt(i));
                                
                             else if (cursor.getType(i) == Cursor.FIELD_TYPE_STRING) 
                                clazz.getMethod("set" + strColName, field.getType()).invoke(obj,
                                        cursor.getString(i));
                             else if (cursor.getType(i) == Cursor.FIELD_TYPE_BLOB) 
                                clazz.getMethod("set" + strColName, field.getType()).invoke(obj,
                                        cursor.getBlob(i));
                             else 
                                throw new DBException(null);
                            
                            break;
                        
                    
                
                objList.add(obj);
                cursor.moveToNext();
            
            return objList;
        
     catch (Exception e) 
        e.printStackTrace();
        throw new DBException(null);
    
    return objList;

相反的,更新保存数据的时候,我们需要从实体对象取值。

public static <T> ContentValues putValue(Field[] fields, T entity) throws DBException 
    ContentValues values = new ContentValues();

    for (Field field : fields) 
        if (!field.isAccessible())
            field.setAccessible(true);

        String strColName = ORMUtils.getColumnName(field);
        if (strColName == null)
            continue;

        try 
            if (field.getGenericType().toString().equals("class java.lang.String")) 
                values.put(strColName, (String) (field.get(entity)));
             else if (field.getGenericType().toString().equals("class java.lang.Boolean")
                    || field.getGenericType().toString().equals("boolean")) 
                values.put(strColName, (((Boolean) (field.get(entity))) ? 1以上是关于手把手带你撸一套Android简易ORM框架的主要内容,如果未能解决你的问题,请参考以下文章

手把手带你撸一套Android简易ORM框架

手把手带你撸一个网易云音乐首页(下篇)

手把手带你撸一个网易云音乐首页(下篇)

手把手带你撸一个网易云音乐首页(上篇)

手把手带你撸一个网易云音乐首页(上篇)

手把手带你从0搭建一个Golang ORM框架(全)!