Android非常輕量的SQLite數據庫訪問對象

jopen 12年前發布 | 33K 次閱讀 Android Android開發 移動開發

  在Android開發中我們經常會使用到SQLite數據庫以及數據庫的一些基本操作.  在這里介紹一種非常輕量級的數據庫訪問方法, 希望對于那些不想引入第三方ORM庫, 而是完全采用SQL操作數據庫的人能夠提供一些方便.
    基本思路和ORM差不多, 采用annotation來對實體類進行標注, 但是簡化了很多. 實體類的書寫方式, 以及數據庫的存儲和讀取方式和ORM基本一樣. 廢話不多說, 直接上代碼...

Example.java 

package com.pls.share.db;

import java.util.Date;

import android.database.sqlite.SQLiteDatabase; import android.util.Log;

import com.pls.share.db.entity.TUser;

/**

  • @author jiuwuerliu@sina.com
  • 調用示例 */ public class Example { static final String tag="Example";

    private SQLiteDatabase db; public SQLiteDatabase createDatabase(){

     SQLiteDatabase db=SQLiteDatabase.create(null);      
     String createdb=
             "CREATE TABLE IF NOT EXISTS t_user("
             +"id         VARCHAR(64) PRIMARY KEY,"
             +"name       VARCHAR(512),"
             +"status     INTEGER NOT NULL DEFAULT 0,"
             +"createTime DATETIME"
             +");";
     db.execSQL(createdb);        
     return db;
    

    }

    public Example(){

     db=createDatabase();
    

    }

    public void insert(){

     SqliteDAO dao=new SqliteDAO(db);
    
     TUser user=new TUser();
     user.setId("user001");
     user.setName("tsc9526");
     user.setCreateTime(new Date());
     user.setStatus(1);
    
     //插入對象到數據庫
     dao.insert(user);
    

    }

    public void load(){

     SqliteDAO dao=new SqliteDAO(db);
    
     TUser user=new TUser();
     user.setId("user001");
    
     //載入數據庫到對象
     dao.loadByPrimaryKey(user); 
    
     Log.i(tag, "ID: "+user.getId()+", name: "+user.getName()+", status: "+user.getStatus());
    

    }

}</pre>

TUser.java

package com.pls.share.db.entity;

import java.util.Date;

import com.pls.share.db.annotation.Id; import com.pls.share.db.annotation.Table; import com.pls.share.db.annotation.Transient;

/**

  • @author jiuwuerliu@sina.com
  • 數據庫實體對象 */ @Table(name="t_user") public class TUser{ /**

    • 主鍵字段 */ @Id private String id;

      private Integer status;

      private String name;

      private Date createTime;

      /**

    • 非數據庫字段 */ @Transient private String detail;

      public TUser(){}

      public String getId() { return id; }

      public void setId(String id) { this.id = id; }

      public Integer getStatus() { return status; }

      public void setStatus(Integer status) { this.status = status; }

      public Date getCreateTime() { return createTime; }

      public void setCreateTime(Date createTime) { this.createTime = createTime; }

      public String getDetail() { return detail; }

      public void setDetail(String detail) { this.detail = detail; }

      public String getName() { return name; }

      public void setName(String name) { this.name = name; }

}</pre></div>

 SqliteDAO.java

package com.pls.share.db;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import android.content.ContentValues;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.util.Log;

import com.pls.share.db.annotation.Id;
import com.pls.share.db.annotation.Table;
import com.pls.share.db.annotation.Transient;

/**
 * @author jiuwuerliu@sina.com
 *  
 */
public class SqliteDAO{ 
    static final String tag="DAO";

    /**
     * 訪問的數據庫
     */
    private SQLiteDatabase db;

    /**
     * 數據插入沖突處理方式:
     * 0-忽略
     * 1-拋出異常
     * 2-替換數據
     */
    private int conflictType=2;

    public SqliteDAO(SQLiteDatabase db){
        this.db=db;         
    }

    public SQLiteDatabase getSQLiteDatabase(){
        return db;
    }

    /**
     * 插入對象到數據庫, 存儲對象的所有字段到數據庫的對應字段,包括NULL字段.
     * @param entity  待插入的對象
     * @return 如果插入數據庫成功則返回該對象,否則返回NULL
     */
    public <T> T insert(T entity){
        return insert(entity,false);
    }

    /**
     * 插入對象到數據庫, 僅存儲對象的非空字段到數據庫,對象的NULL字段將被忽略.
     * @param entity 待插入的對象
     * @return 如果插入數據庫成功則返回該對象,否則返回NULL
     */
    public <T> T insertSelective(T entity){
        return insert(entity,true);
    }


    private <T> T insert(T entity,boolean selective){     
        ContentValues values=getContentValues(entity,selective);

        T exist_obj=this.loadByPrimaryKey(entity);
        if(exist_obj!=null){
            return exist_obj;
        }

        long r=0;
        if(conflictType==2){
            r=db.replace(getTableName(entity), null,values);            
        }else{
            r=db.insert(getTableName(entity), null, values);             
        }

        if(r>=0){
            return entity;
        }

        return null;                
    }

    /**
     * 根據主鍵刪除數據
     * @param entity 待刪除的對象, 主鍵只必須設置.
     * @return
     */
    public <T> int delete(T entity){
        Object[] args=getPrimarySelectionAndArgs(entity);
        return db.delete(getTableName(entity), (String)args[0], (String[])args[1]);     
    }


    /**
     * 根據主鍵從數據庫載入一條記錄到對象
     * @param entity 數據實體(必須初始化主鍵字段)
     * @return 成功則返回的該數據庫實體,失敗則返回NULL
     */
    public <T> T loadByPrimaryKey(T entity){
        Object[] args=getPrimarySelectionAndArgs(entity);
        Cursor cursor=db.query(getTableName(entity), null,(String)args[0],(String[])args[1], null,null,null);
        try{
            if(cursor.moveToNext()){
                T db_entity=getEntity(cursor,entity);
                return db_entity;
            }else{
                return null;
            }
        }finally{
            cursor.close();
        }
    }


    @SuppressWarnings("unchecked")
    public <T> List<T> loadAll(T entity,String orderBy){    
        List<T> entities=new ArrayList<T>();

        Cursor cursor=db.query(getTableName(entity), null,null,null, null,null,orderBy);
        try{
            if(cursor!=null && cursor.moveToFirst()){
                T obj=(T)entity.getClass().newInstance();
                getEntity(cursor,obj);

                entities.add(obj);

            }while(cursor.moveToNext());

            return entities;
        }catch(Exception e){
            Log.e(tag,""+e,e);

            return entities;
        }finally{
            cursor.close();
        }
    }

    /**
     * 更新數據庫實體,  更新對象的所有字段到數據庫的對應字段,包括NULL字段.
     * @param entity 待更新的對象(必須包含主鍵)
     * @return 成功更新的記錄數
     */
    public int updateByPrimaryKey(Object entity){
        return updateByPrimaryKey(entity,false);
    }

    /**
     * 更新數據庫實體,  僅更新對象的非空字段到數據庫的對應字段,對象的NULL字段將被忽略.
     * @param entity 待更新的對象(必須包含主鍵)
     * @return 成功更新的記錄數
     */
    public int updateByPrimaryKeySelective(Object entity){
        return updateByPrimaryKey(entity,true);
    }

    private int updateByPrimaryKey(Object entity,boolean selective){
        ContentValues values=getContentValues(entity,selective);
        Object[] args=getPrimarySelectionAndArgs(entity);

        int r=db.update(getTableName(entity), values, (String)args[0],(String[])args[1]);

        return r; 
    }

    /**
     * 從對象中解析出主鍵字段, 以及主鍵字段對應的值 
     * @param entity
     * @return
     */
    private Object[] getPrimarySelectionAndArgs(Object entity){
        Object[] ret=new Object[2];
        String selection=null;
        List<String> args=new ArrayList<String>();
        try{
            Class<?> entity_class=entity.getClass();          
            Field[] fs=entity_class.getDeclaredFields();
            for(Field f:fs){
                if(isPrimaryKey(f)){                
                    Method get=getGetMethod(entity_class,f);
                    if(get!=null){
                        Object o=get.invoke(entity);                        
                        String value=null;
                        if(o!=null){
                            value=o.toString();
                            if(selection==null){
                                selection=f.getName()+"=?";                             
                            }else{
                                selection+=" AND "+f.getName()+"=?";
                            }

                            args.add(value);

                        }else{
                            throw new RuntimeException("Primary key: "+f.getName()+" must not be null");
                        }
                    }
                }
            }           
            if(selection==null){
                throw new RuntimeException("Primary key not found!");
            }

            ret[0]=selection;
            ret[1]=args.toArray(new String[args.size()]);
            return ret;
        }catch(Exception e){
            throw new RuntimeException(e.getMessage(),e);
        }
    }

    /**
     * 將對象轉換為ContentValues
     * @param entity
     * @param selective
     * @return
     */
    private ContentValues getContentValues(Object entity,boolean selective){
        ContentValues values=new ContentValues();
        try{
            Class<?> entity_class=entity.getClass();          
            Field[] fs=entity_class.getDeclaredFields();
            for(Field f:fs){
                if(isTransient(f)==false){              
                    Method get=getGetMethod(entity_class,f);
                    if(get!=null){
                        Object o=get.invoke(entity);
                        if(!selective || (selective && o!=null)){
                            String name=f.getName();                        
                            Class<?> type=f.getType();
                            if(type==String.class){
                                values.put(name,(String)o);
                            }else if(type==int.class || type==Integer.class){
                                values.put(name,(Integer)o);
                            }else if(type==float.class || type==Float.class){
                                values.put(name,(Float)o);
                            }else if(type==long.class || type==Long.class){
                                values.put(name,(Long)o);
                            }else if(type==Date.class){
                                values.put(name,datetimeToString((Date)o));
                            }else{  
                                values.put(name,o.toString());                              
                            }
                        }
                    }
                }
            }
            return values;
        }catch(Exception e){
            throw new RuntimeException(e.getMessage(),e);
        }
    }

    /**
     * 將數據庫記錄轉換為對象
     * 
     * @param cursor
     * @param entity
     * @return
     */
    private <T> T getEntity(Cursor cursor, T entity){ 
        try{
            Class<?> entity_class=entity.getClass();

            Field[] fs=entity_class.getDeclaredFields();
            for(Field f:fs){
                int index=cursor.getColumnIndex(f.getName());
                if(index>=0){                    
                    Method set=getSetMethod(entity_class,f);
                    if(set!=null){
                        String value=cursor.getString(index);                                           
                        if(cursor.isNull(index)){
                            value=null;
                        }
                        Class<?> type=f.getType();
                        if(type==String.class){
                            set.invoke(entity,value);
                        }else if(type==int.class || type==Integer.class){
                            set.invoke(entity,value==null?(Integer)null:Integer.parseInt(value));
                        }else if(type==float.class || type==Float.class){
                            set.invoke(entity,value==null?(Float)null:Float.parseFloat(value));
                        }else if(type==long.class || type==Long.class){
                            set.invoke(entity,value==null?(Long)null:Long.parseLong(value));
                        }else if(type==Date.class){
                            set.invoke(entity,value==null?(Date)null:stringToDateTime(value));
                        }else{  
                            set.invoke(entity,value);                       
                        }                            
                    }
                }
            }           
            return entity;
        }catch(Exception e){
            throw new RuntimeException(e.getMessage(),e);
        }
    }

    private String datetimeToString(Date d){
        SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        if(d!=null){
            return sdf.format(d);
        }
        return null;
    }

    private Date stringToDateTime(String s){
        SimpleDateFormat sdf=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        if(s!=null){
            try {
                return sdf.parse(s);
            } catch (ParseException e) {             
                Log.e(tag,"解析時間錯誤: "+s,e);
            }
        }
        return null;
    }

    private Method getGetMethod(Class<?> entity_class,Field f){
        String fn=f.getName();
        String mn="get"+fn.substring(0,1).toUpperCase()+fn.substring(1);
        try{            
            return entity_class.getDeclaredMethod(mn);
        }catch(NoSuchMethodException e){
            Log.w(tag,"Method: "+mn+" not found.");

            return null;
        }
    }

    private Method getSetMethod(Class<?> entity_class,Field f){
        String fn=f.getName();
        String mn="set"+fn.substring(0,1).toUpperCase()+fn.substring(1);
        try{            
            return entity_class.getDeclaredMethod(mn,f.getType());
        }catch(NoSuchMethodException e){
            Log.w(tag,"Method: "+mn+" not found.");

            return null;
        }
    }

    /**
     * 檢查是否為主鍵字段
     */
    private boolean isPrimaryKey(Field f){       
        Annotation an=f.getAnnotation(Id.class);
        if(an!=null){
            return true;             
        }
        return false;
    }

    private boolean isTransient(Field f){        
        Annotation an=f.getAnnotation(Transient.class);
        if(an!=null){
            return true;             
        }
        return false;
    }



    private String getTableName(Object entity){
        Table table=entity.getClass().getAnnotation(Table.class);
        String name= table.name();
        return name;
    }

    public int getConflictType() {
        return conflictType;
    }

    public void setConflictType(int conflictType) {
        this.conflictType = conflictType;
    }


}

Id.java

package com.pls.share.db.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * @author jiuwuerliu@sina.com
 * 
 * 標注為主鍵字段
 */
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME) 
public @interface Id {

}

Table.java

package com.pls.share.db.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * @author jiuwuerliu@sina.com
 * 
 *  標注數據庫表名
 */
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME) 
public @interface  Table {
    /**
     * @return 數據庫表名
     */
    String name();
}

Transient.java

package com.pls.share.db.annotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * @author jiuwuerliu@sina.com
 * 
 * 標注為非數據庫字段
 */
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME) 
public @interface Transient {

}
 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!