1. 程式人生 > >ORMLite快速入門操作

ORMLite快速入門操作

大家在做安卓專案時肯定都會碰到資料庫儲存,原生的效率上會比較低,為了提高開發效率,大多公司會用一些框架,目前市面上比較流行的框架有ormlite、greenDao、SQLBrite、Realm等,其中ormlite是JDBC(Java資料庫連線)和Android的輕量級ORM java包,而GreenDao則是一種輕快地將物件對映到SQLite資料庫的ORM解決方案。
下面讓我們快速的學習一下ormlite的簡單使用

下載ORMLite Jar包

首先去ormlite官網下載所需的jar包,現在最新版本已經更新到5.0,分別為:ormlite-android-5.0.jar 和 ormlite-core-5.0.jar

定義Bean類

這裡我們定義兩個類,父母和孩子的關係
父母類

package com.liuw.ormlite.bean;

import com.j256.ormlite.field.DatabaseField;
import com.j256.ormlite.table.DatabaseTable;

/**
 * 父母
 */
//定義表名
@DatabaseTable(tableName = "tab_parent")
public class Parents {
    //generatedId定義主鍵自增長,columnName定義該欄位在資料庫中的列名
    @DatabaseField
(useGetSet=true,generatedId=true,columnName="id") private int id; @DatabaseField(useGetSet=true, columnName = "f_id") private String fid;//父母編號 @DatabaseField(useGetSet=true, columnName = "f_name") private String fname;//父親姓名 @DatabaseField(useGetSet=true, columnName = "m_name"
) private String mname;//母親姓名 public Parents() { } public Parents(String fid, String fname, String mname) { this.fid = fid; this.fname = fname; this.mname = mname; } public int getId() { return id; } public void setId(int id) { this.id = id; } public String getFid() { return fid; } public void setFid(String fid) { this.fid = fid; } public String getFname() { return fname; } public void setFname(String fname) { this.fname = fname; } public String getMname() { return mname; } public void setMname(String mname) { this.mname = mname; } @Override public String toString() { return "Parents{" + "id=" + id + ", fid='" + fid + '\'' + ", fname='" + fname + '\'' + ", mname='" + mname + '\'' + '}'; } }

child類,孩子是屬於某個父母,那肯定是需要parent類的主鍵才能找到關係,有的人可能會直接在child類裡宣告一個parent類裡的fid屬性,當做普通屬性來處理,但這樣就違背了面向物件思想
所以這裡我們採用面向物件思想應該是這樣,child屬於某個parent,在child類裡宣告外來鍵parent類來處理,這樣的話在獲取孩子資訊的同時也能獲取到對應父母的資訊

package com.liuw.ormlite.bean;

import com.j256.ormlite.field.DatabaseField;
import com.j256.ormlite.table.DatabaseTable;

/**
 * 孩子
 */
@DatabaseTable(tableName = "tab_child")
public class Childs {

    @DatabaseField(useGetSet=true,generatedId=true,columnName="id")
    private int id;

    @DatabaseField(useGetSet=true, columnName = "s_name")
    private String sname;//姓名

    @DatabaseField(useGetSet=true, columnName = "s_gender")
    private String sgender;//性別

    @DatabaseField(useGetSet=true, columnName = "s_age")
    private String sage;//年齡

    @DatabaseField(useGetSet=true, columnName = "s_phone")
    private String sphone;//聯絡方式

    //引入外來鍵(columnName值預設儲存父類中的主鍵對應的值,也可以換成foreignColumnName指定父類欄位,格式為foreignColumnName = "父表裡的欄位"
    //如foreignColumnName = "f_name",此時將會儲存父表裡對應的欄位內容)
    @DatabaseField(useGetSet=true, canBeNull = true, foreign = true, columnName = "s_parent")
    private Parents parents;//父母資訊

    public Childs() {

    }

    public Childs(String sname, String sgender, String sage) {
        this.sname = sname;
        this.sgender = sgender;
        this.sage = sage;
    }

    public String getSphone() {
        return sphone;
    }

    public void setSphone(String sphone) {
        this.sphone = sphone;
    }

    public int getId() {
        return id;
    }

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

    public String getSname() {
        return sname;
    }

    public void setSname(String sname) {
        this.sname = sname;
    }

    public String getSgender() {
        return sgender;
    }

    public void setSgender(String sgender) {
        this.sgender = sgender;
    }

    public String getSage() {
        return sage;
    }

    public void setSage(String sage) {
        this.sage = sage;
    }

    public Parents getParents() {
        return parents;
    }

    public void setParents(Parents parents) {
        this.parents = parents;
    }

    @Override
    public String toString() {
        return "Childs{" +
                "id=" + id +
                ", sname='" + sname + '\'' +
                ", sgender='" + sgender + '\'' +
                ", sage='" + sage + '\'' +
                ", parents=" + parents +
                '}';
    }
}

SQLiteOpenHelper類

原生的資料庫操作,都需要繼承SQLiteOpenHelper,而ormlite我們則需要繼承OrmLiteSqliteOpenHelper

package com.liuw.ormlite.dao;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.os.Environment;

import com.j256.ormlite.android.apptools.OrmLiteSqliteOpenHelper;
import com.j256.ormlite.dao.Dao;
import com.j256.ormlite.support.ConnectionSource;
import com.j256.ormlite.table.TableUtils;
import com.liuw.ormlite.bean.Childs;
import com.liuw.ormlite.bean.Courses;
import com.liuw.ormlite.bean.Parents;

import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;

public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
    private static final String TABLE_NAME = "ormlite_test.db";//預設是在data/data/包名/databases/路徑下
    public static final String DATABASE_PATH = Environment.getExternalStorageDirectory() + "/liuw/" + TABLE_NAME;//指定路徑
    private static final int DB_VERSION = 3;

    private Map<String, Dao> daos = new HashMap<String, Dao>();

    private DatabaseHelper(Context context) {
        super(context, DATABASE_PATH, null, DB_VERSION);
    }

    @Override
    public void onCreate(SQLiteDatabase database,
                         ConnectionSource connectionSource) {
        try {
            TableUtils.createTableIfNotExists(connectionSource, Childs.class);
            TableUtils.createTableIfNotExists(connectionSource, Courses.class);
            TableUtils.createTableIfNotExists(connectionSource, Parents.class);
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onUpgrade(SQLiteDatabase database,
                          ConnectionSource connectionSource, int oldVersion, int newVersion) {
           //整表刪除建立
//        try {
//            TableUtils.dropTable(connectionSource, Childs.class, true);
//            TableUtils.dropTable(connectionSource, Courses.class, true);
//            TableUtils.dropTable(connectionSource, Parents.class, true);
//            onCreate(database, connectionSource);
//        } catch (SQLException e) {
//            e.printStackTrace();
//        }
    //更新資料庫時只需新增新增欄位
        if (newVersion == 3) {
            //資料庫、表名、列名、型別
            DatabaseUtil.updateColumn(database, "tab_child", "s_phone", "VARCHAR", null);
        }
    }

    private static DatabaseHelper instance;

    /**
     * 單例獲取該Helper
     *
     * @param context
     * @return
     */
    public static synchronized DatabaseHelper getHelper(Context context) {
        context = context.getApplicationContext();
        if (instance == null) {
            synchronized (DatabaseHelper.class) {
                if (instance == null)
                    instance = new DatabaseHelper(context);
            }
        }

        return instance;
    }

    public synchronized Dao getDao(Class clazz) throws SQLException {
        Dao dao = null;
        String className = clazz.getSimpleName();

        if (daos.containsKey(className)) {
            dao = daos.get(className);
        }
        if (dao == null) {
            dao = super.getDao(clazz);
            daos.put(className, dao);
        }
        return dao;
    }

    /**
     * 釋放資源
     */
    @Override
    public void close() {
        super.close();

        for (String key : daos.keySet()) {
            Dao dao = daos.get(key);
            dao = null;
        }
    }

}

這裡詳細就不做介紹了,onCreate建立表,onUpgrade更新表,網上教程大多都是採用刪除再建立的方式更新,這裡我們可以通過自定義的DatabaseUtil類來實現表結構的更新,其實內部就是一個新增列的原生SQL語句,程式碼如下:

package com.liuw.ormlite.dao;

import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;

public class DatabaseUtil {
    public static void updateColumn(SQLiteDatabase db, String tableName,
                                    String columnName, String columnType, Object defaultField) {
        try {
            if (db != null) {
                Cursor c = db.rawQuery("SELECT * from " + tableName
                        + " limit 1 ", null);
                boolean flag = false;

                if (c != null) {
                    for (int i = 0; i < c.getColumnCount(); i++) {
                        if (columnName.equalsIgnoreCase(c.getColumnName(i))) {
                            flag = true;
                            break;
                        }
                    }
                    if (flag == false) {
                        String sql = "alter table " + tableName + " add "
                                + columnName + " " + columnType + " default "
                                + defaultField;
                        db.execSQL(sql);
                    }
                    c.close();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void deleteRecordsWithoutForeignKey(SQLiteDatabase db, String tableName){
        if (db != null) {
            String sql = "DELETE from " + tableName;
            db.execSQL(sql);
        }
    }
}

這樣做的好處是不用再整表刪除、建立,從而提高了工作效率

編寫Dao類

我們可以將需要的增、刪、改、查等方法都放在Dao裡,便於操作使用
父類Dao

package com.liuw.ormlite.dao;

import android.content.Context;

import com.j256.ormlite.dao.Dao;
import com.liuw.ormlite.bean.Parents;

import java.sql.SQLException;

public class ParentDao {
    private Dao<Parents, Integer> parentDao;
    private DatabaseHelper helper;

    public ParentDao(Context contex) {
        try {
            helper = DatabaseHelper.getHelper(contex);
            parentDao = helper.getDao(Parents.class);
            if (parentDao == null) {
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 增
     * @param parent
     */
    public void addParent(Parents parent) {
        try {
            parentDao.create(parent);
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }
}

孩子類Dao

package com.liuw.ormlite.dao;

import android.content.Context;

import com.j256.ormlite.dao.Dao;
import com.liuw.ormlite.bean.Childs;
import com.liuw.ormlite.bean.Parents;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

public class ChildDao {
    private Dao<Childs, Integer> childDao;
    private DatabaseHelper helper;

    public ChildDao(Context contex) {
        try {
            helper = DatabaseHelper.getHelper(contex);
            childDao = helper.getDao(Childs.class);
            if (childDao == null) {
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 增
     * @param child
     */
    public void addChild(Childs child) {
        try {
            childDao.create(child);
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    /**
     * 刪(通過實體)
     * @param child
     */
    public void delChild(Childs child) {
        try {
            childDao.delete(child);
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    /**
     * 刪(通過id)
     * @param id
     */
    public void delChildById(Integer id) {
        try {
            childDao.deleteById(id);
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    /**
     * 改
     * @param child
     */
    public void updateChild(Childs child) {
        try {
            childDao.update(child);
        } catch (SQLException e) {
            e.printStackTrace();
        }
    }

    /**
     * 查
     * @return
     */
    public List<Childs> queryAllChild() {
        ArrayList<Childs> childs = null;
        try {
            childs = (ArrayList<Childs>) childDao.queryForAll();
        } catch (SQLException e) {
            e.printStackTrace();
        }
        return childs;
    }

    /**
     * 獲取user
     * @param id child編號
     * @return
     */
    public Childs getChild(Integer id) {
        try {
            //父母資訊為空
            return childDao.queryForId(id);
        } catch (SQLException e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 獲取user
     * @param id child編號
     * @return
     */
    public Childs getChildAndParent(Integer id) {
        try {
            //父母資訊有值,此處的refresh也可通過在資料中新增foreignAutoRefresh = true來實現
            Childs child = childDao.queryForId(id);
            helper.getDao(Parents.class).refresh(child.getParents());
            return child;
        } catch (SQLException e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 獲取user
     * @param name child姓名
     * @return
     */
    public List<Childs> getChildByName(String name) {
        try {
            List<Childs> childs = childDao.queryBuilder().where().eq("s_name", name).query();
            return childs;
        } catch (SQLException e) {
            e.printStackTrace();
            return null;
        }
    }
}

測試

測試之前不要忘了加讀寫許可權

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
package com.liuw.ormlite;

import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;

import com.liuw.ormlite.bean.Childs;
import com.liuw.ormlite.bean.Parents;
import com.liuw.ormlite.dao.ParentDao;
import com.liuw.ormlite.dao.ChildDao;

import java.util.List;

public class MainActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initData();
    }

    private void initData() {
        ParentDao parentDao = new ParentDao(getApplicationContext());
        ChildDao childDao = new ChildDao(getApplicationContext());

        Parents p1 = new Parents("001", "曹建華", "於曉紅");
        parentDao.addParent(p1);

        Childs s1 = new Childs("豬小明", "男", "15");
        s1.setParents(p1);
        childDao.addChild(s1);

        Parents p2 = new Parents("002", "餘正華", "謀女郎");
        parentDao.addParent(p2);

        Childs s2 = new Childs("閏土", "男", "20");
        s2.setParents(p2);
        childDao.addChild(s2);

        //id自增長預設從1開始
        Childs student1 = childDao.getChild(1);
        if (student1 != null) {
            //結果:Childs{id=1, sname='豬小明', sgender='男', sage='15', parents=Parents{id=1,fid='null' fname='null', mname='null'}}
            Log.i("liuw", student1.toString());
        }

        Childs student2 = childDao.getChildAndParent(2);
        if (student2 != null) {
            //結果:Childs{id=2, sname='閏土', sgender='男', sage='20', parents=Parents{id=2,fid='002' fname='餘正華', mname='謀女郎'}}
            Log.i("liuw", student2.toString());
        }

        List<Childs> students = childDao.getChildByName("閏土");
        if (students != null && students.size() > 0) {
            Log.i("liuw", "資料大小為:"+students.size());
        }

    }
}

注意上面的兩個結果的區別,具體可以看下兩個方法,可以手動重新整理,也可以直接在資料庫的表裡新增foreignAutoRefresh = true來實現;
本來是準備寫一篇多表、多條件之間查詢的,不過模擬資料新增起來有點麻煩,這裡先介紹兩篇文章做參考吧
複雜條件查詢
ormlite引數及方法介紹