Android ORM框架之LiteOrm的使用心得

    以前一直在使用SQLite,無心中發現LiteOrm,看了下基本使用,感受很方便並且效率也挺高的,特別是級聯查詢上,很面向對象。java

    LiteOrm並非OrmLite,沒有文檔僅能查看GitHub上的samples。不過在數據庫框架的使用方法上比較類似。 android

    二者之間的比較:Android數據庫框架:greenDAO vs LiteOrmgit

    GitHub地址:https://github.com/litesuits/android-lite-orm 
    LiteSuits 官網: http://litesuits.com/?form=gormgithub

 

1、建立數據庫    

/*
1. 建立config信息
*/
DataBaseConfig config = new DataBaseConfig(mContext);
//數據庫名,可設置存儲路徑。默認在內部存儲位置databases文件夾下
//"liteorm.db"是數據庫名稱,名稱裏包含路徑符號"/"則將數據庫創建到該路徑下,可使用sd卡路徑。 不包含則在系統默認路徑下建立DB文件。        
config.dbName = DB_NAME_PATH + File.separator + "liteorm.db";
config.debugged = true; //是否打Log
config.dbVersion = 1; // database Version
config.onUpdateListener = null; //升級

/**
*2. 生成實例對象
*/
//級聯操做
liteOrm = LiteOrm.newCascadeInstance(config);
//獨立操做
liteOrm = LiteOrm.newSingleInstance(config);

LiteOrm有兩種獲取實例的方法:算法

    獨立操做:使用 LiteOrm 的 single 實例,可與 cascade 方式平滑切換,性能高,僅處理該對象數據,其關係、和關聯對象忽略;
    級聯操做:使用 LiteOrm 的 cascade 實例,可與 single 方式平滑切換,全遞歸,該對象數據,及其關係、和關聯對象都被處理;sql

    這兩種獲取方式根據項目需求而定,若是級聯操做比較多的話,就可使用cascadeInstance,而其又能夠和獨立操做任意切換:數據庫

LiteOrm db = LiteOrm.newCascadeInstance(this, "cascade.db");
db.cascade().save(user);//級聯操做:保存[當前對象],以及該對象全部的[關聯對象]以及它們的[映射關係]。
db.single().save(user);//非級聯操做:僅保存[當前對象],高效率。

2、註解

    基礎註解

  • @Table("test_model") 表名
  • @PrimaryKey(AssignType.AUTO_INCREMENT) 主鍵自增加
  • @PrimaryKey(AssignType.BY_MYSELF) 本身設置主鍵
  • @Ignore 忽略該字段,不存入數據庫
  • @Column("login") 指定列名
  • @Collate("NOCASE") 大小寫無關

    關係映射:

  • @Mapping(Relation.ManyToMany) 多對多
  • @Mapping(Relation.OneToMany) 一對多
  • @Mapping(Relation.OneToOne) 一對一
  • @Mapping(Relation.ManyToOne) 多對一
  • @MapCollection(ConcurrentLinkedQueue.class) 指定約束對象的集合類型

    約束相關:

  • @NotNull 非空約束
  • @Default("true") 默認約束
  • @Check("index > 0 ") check約束
  • @Unique 惟一約束
  • @UniqueCombine() 聯合惟一約束

    約束衝突:

    ON CONFLICT 子句不是一個單獨的 SQL 命令。 它能夠出如今不少其它的 SQL 命令中,是一個非標準的子句。ON CONFLICT 子句指定一個用於解決約束衝突的算法。 有五種選擇(具體解釋請看文末參考連接,copy過來也沒啥意思): 
@Conflict(Strategy.ROLLBACK) 
@Conflict(Strategy.ABORT) 
@Conflict(Strategy.FAIL) 
@Conflict(Strategy.IGNORE) 
@Conflict(Strategy.REPLACE)app

從註解也能夠看出來該框架確實比較全面,它的查詢某些語法徹底和SQL語句同樣,能夠複習一下SQL語句。框架

3、建表

    僅須要創建實體類添加相應的註解就能夠了,是否是很方便。less

4、CRUD操做

1.保存    

// 僅插入數據
Person man= new Person("name",23);
liteOrm.insert(man);
// 保存單個實例
Person person = new Person("name",23);
liteOrm.save(person); 
// 保存一個List
List<Person> list = new ArrayList<>();
liteOrm.save(list);

2.修改

book.setIndex(1988);
book.setAuthor("hehe");
liteOrm.update(book);

     更新指定列

// 把全部書的author強制批量改成liter
HashMap<String, Object> bookIdMap = new HashMap<String, Object>();
bookIdMap.put(Book.COL_AUTHOR, "liter");
liteOrm.update(bookList, new ColumnsValue(bookIdMap), ConflictAlgorithm.Fail);
// 僅 author 這一列更新爲該對象的最新值。
//liteOrm.update(bookList, new ColumnsValue(new String[]{Book.COL_AUTHOR}, null), ConflictAlgorithm.Fail);

3.查詢

    在寫查詢語句時,必定要銘記sql語句:

SELECT 列
FROM 表
WHERE 條件
GROUP BY 分組條件
HAVING 分組後條件
ORDER BY 排序
LIMIT (x,y)

     讀取所有數據

// 讀取所有數據
List<Person> list = liteOrm.query(Person.class);

    查詢操做裏面這個 ? 必不可少,是否是和寫sql很像,? 是個佔位符。同時SQL並不區分大小寫,但關鍵字建議大寫。

    聚合函數count查詢

//聚合函數count查詢,好像只有這一個
long nums = liteOrm.queryCount(Address.class); //查詢有多少行

    查詢  根據ID

Student student = liteOrm.queryById(student1.getId(), Student.class);
OrmLog.i(TAG, student);

    查詢  模糊

//模糊查詢
QueryBuilder<Address> qb = new QueryBuilder<Address>(Address.class).where("address LIKE ?", new String[]{"%山%"});
liteOrm.query(qb);

    查詢  與或非等

qb = new QueryBuilder<Address>(Address.class)        
.whereEquals("city", "南京")
.whereAppendAnd() 
.whereEquals("address", "香港路");
liteOrm.query(qb);

    查詢 任意

List<Book> books = liteOrm.query(new QueryBuilder<Book>(Book.class)
        .columns(new String[]{"id", "author", Book.COL_INDEX})
        .distinct(true)
        .whereGreaterThan("id", 0)
        .whereAppendAnd()
        .whereLessThan("id", 10000)
        .limit(6, 9)
        .appendOrderAscBy(Book.COL_INDEX));
OrmLog.i(TAG, books);

    查詢  本身拼SQL語句

QueryBuilder<Address> qb = new QueryBuilder<Address>(Address.class)        
.columns(new String[]{Address.COL_ADDRESS})    //查詢列
.appendOrderAscBy(Address.COL_ADDRESS)        //升序
.appendOrderDescBy(Address.COL_ID)       //當第一列相同時使用該列降序排序
.distinct(true)        //去重
.where(Address.COL_ADDRESS + "=?", new String[]{"香港路"}); //where條件
liteOrm.query(qb);

4.刪除

    刪除 實體

// 刪除 student-0
liteOrm.delete(student0);

    刪除 指定數量

// 按id升序,刪除[2, size-1],結果:僅保留第一個和最後一個
// 最後一個參數可爲null,默認按 id 升序排列
liteOrm.delete(Book.class, 2, bookList.size() - 1, "id");

    刪除 使用WhereBuilder

// 刪除 student-1
liteOrm.delete(new WhereBuilder(Student.class)
        .where(Person.COL_NAME + " LIKE ?", new String[]{"%1%"})
        .and()
        .greaterThan("id", 0)
        .and()
        .lessThan("id", 10000));

    刪除所有

// 連同其關聯的Person,Person關聯的其餘對象一帶刪除
liteOrm.deleteAll(Person.class);

    刪除數據庫文件

liteOrm.deleteDatabase();
// 順帶測試:而後重建一個新庫
liteOrm.openOrCreateDatabase();

5、級聯操做

    爲何說面向對象呢。就是僅僅須要在JavaBean裏聲明對象間關係,並用註解標識就OK了。舉個例子:

@Table("school")
public class School{
  @Mapping(Relation.OneToMany)
  public ArrayList<Classes> classesList; //一個學校有多個教室
}

@Table("class")
public class Classes  {        
  @Mapping(Relation.OneToOne)   
  public Teacher teacher; //一個教室有一個老師,假設
}

@Table("teacher")
public class Teacher {   
  @Mapping(Relation.ManyToMany)    
  @MapCollection(ConcurrentLinkedQueue.class)   
  private Queue<Student> studentLinkedQueue; //一個老師多個學生,一個學生多個老師,多對多關係
}

@Table("student")
public class Student  {    
  @Mapping(Relation.ManyToMany)    
  private Teacher[] teachersArray;//一個老師多個學生,一個學生多個老師,多對多關係
}

就這樣聲明,你在Java裏建立完對象後使用save()方法保存後,數據庫中各類關聯表就建好了,徹底不用本身設置主鍵、外鍵什麼的。是否是很方便?不過前提是你要使用LiteOrm.newCascadeInstance(config)這個實例。

6、封裝

public enum UOrm implements SQLiteHelper.OnUpdateListener {
  INSTANCE;
  private LiteOrm mLiteOrm;
  UOrm() {
    DataBaseConfig config = new DataBaseConfig(MyApplcation.mContext);
    config.dbName = DB_NAME_PATH + File.separator + DB_NAME;
    config.dbVersion = 1;
    config.onUpdateListener = this;
    config.debugged = BuildConfig.DEBUG;
    //可替換爲 newCascadeInstance支持級聯操做
    mLiteOrm = LiteOrm.newSingleInstance(config);
  }

  @Override public void onUpdate(SQLiteDatabase sqLiteDatabase, int i, int i1) {
  }

  public void save(Object o) {
    if (o == null) {
      return;
    }
    mLiteOrm.save(o);
  }

  public <T> void save(List<T> collection) {
    if (CommonUtil.isEmpty(collection)) {
      return;
    }
    mLiteOrm.save(collection);
  }

  public <T> void delete(Class<T> tClass) {
    if (tClass == null) {
      return;
    }
    mLiteOrm.delete(tClass);
  }

  public <T> List<T> queryAll(Class<T> tClass) {
    if (tClass == null) {
      return null;
    }
    return mLiteOrm.query(tClass);
  }
}

使用時只用這樣調用:

UOrm.INSTANCE.save(modelA);

7、約束衝突

    什麼是sql約束?好比@NotNull,@Unique,@Check等。不知足這些約束就會產生衝突,解決約束衝突的算法。有五個選擇:ROLLBACK、ABORT、FAIL、IGNORE和REPLACE,缺省方案是ABORT,它並非標準的SQL語言

ROLLBACK
    當發生約束衝突,當即ROLLBACK,即結束當前事務處理,命令停止並返回SQLITE_CONSTRAINT代碼。若當前無活動事務(除了每一條命令建立的默認事務之外),則該算法與ABORT相同。

ABORT
    當發生約束衝突,命令收回已經引發的改變並停止返回SQLITE_CONSTRAINT。但因爲不執行ROLLBACK,因此前面的命令產生的改變將予以保留。缺省採用這一行爲。

FAIL
    當發生約束衝突,命令停止返回SQLITE_CONSTRAINT。但遇到衝突以前的全部改變將被保留。例如,若一條UPDATE語句在100行遇到衝突100th,前99行的改變將被保留,而對100行或之後的改變將不會發生。

IGNORE
    當發生約束衝突,發生衝突的行將不會被插入或改變。但命令將照常執行。在衝突行以前或以後的行將被正常的插入和改變,且不返回錯誤信息。

REPLACE     當發生UNIQUE約束衝突,先存在的,致使衝突的行在更改或插入發生衝突的行以前被刪除。這樣,更改和插入老是被執行。命令照常執行且不返回錯誤信息。當發生NOT NULL約束衝突,致使衝突的NULL值會被字段缺省值取代。若字段完好省值,執行ABORT算法。當衝突應對策略爲知足約束而刪除行時,它不會調用刪除觸發器。但在新版中這一特性可能被改變。INSERT或UPDATE的OR子句定義的算法會覆蓋CREATE TABLE所定義的。ABORT算法將在沒有定義任何算法時缺省使用。

相關文章
相關標籤/搜索