安卓-ObjectBox數(shù)據(jù)庫筆記1:gradle配置和常用增刪改查

(安卓)ObjectBox數(shù)據(jù)庫筆記

[TOC]

1.Gradle設(shè)置

1.1 啟用mavenCentral

根工程里的build.gradle

repositories { 
    mavenCentral()
}

1.2 根build.gradle文件里添加 (project level)

buildscript {
    ext.objectboxVersion = '2.9.1'
    dependencies {
        classpath "io.objectbox:objectbox-gradle-plugin:$objectboxVersion"
    }
}

1.3 app 里的 build.gradle 添加 (module level)

apply plugin: 'com.android.application'
apply plugin: 'kotlin-android' // Only for Kotlin projects.
apply plugin: 'kotlin-kapt' // Only for Kotlin projects.
apply plugin: 'io.objectbox' // Apply last.  after applying Android plugin

1.4 添加依賴

dependencies {
    implementation "io.objectbox:objectbox-java:$objectboxVersion"
    implementation "io.objectbox:objectbox-android:$objectboxVersion"
}

1.5 配置 支持增量注釋處理

android {
    defaultConfig {
        javaCompileOptions {
            annotationProcessorOptions {
                arguments = [ "objectbox.incremental" : "true" ]
           }
       }
    }
}

1.6 Objectbox使用流程

1.6.1 定義實體類,然后 Build > Make Project

如果gradle配置正確,將會在app\build\generated\ap_generated_sources\debug\out下生成相應(yīng)的文件,例如MyObjectBox等。

同時,會自動生成 app/objectbox-models/default.json文件,請把這一個文件加入版本控制,不要刪除。不要手動修改里面的內(nèi)容。

1.6.2 創(chuàng)建 BoxStore

在Application里初始化BoxStore后,可以使用BoxStore對數(shù)據(jù)表進(jìn)行增刪改查操作。

public class ObjectBox {
    private static BoxStore boxStore;
    public static void init(Context context) {
        boxStore = MyObjectBox.builder()
            .androidContext(context.getApplicationContext())
            .build();
    }
    public static BoxStore get() { return boxStore; }
}

2.實體類相關(guān)注解

@Entity
public class User {
    @Id 
    public long id;
    public String name;
    //如果字段是私有的,則必須有一個標(biāo)準(zhǔn)的getters方法。
     private String name2;
     public String getName2() {
        return this.name;
    }

}
@Entity

注解到class上,代表是一個數(shù)據(jù)庫表,實體也必須有一個無參數(shù)的構(gòu)造函數(shù)

@Id :

注解到成員屬性上,代表是自增id,必須是long型(java kotlin 里是long型 dart里是int型),@Id 注解的成員屬性不能是私有的。默認(rèn)情況下,ID屬性是惟一的,并且有索引。向表里新增數(shù)據(jù)時,如果不指定id,則新對象的id由ObjectBox分配

@Index

注解到成員屬性上,代表索引,可以在查詢時,提高性能。@Index目前不支持String[], byte[], float和double。查詢時,如果是字符串,則使用區(qū)分大小寫的條件

StringIdEntity entity = box.query() .equal(StringIdEntity_.uid, uid, StringOrder.CASE_SENSITIVE) .build().findUnique()
@Transient

注解到成員屬性上,代表這一個屬性不被持久化到表里。java里的靜態(tài)屬性也不會持久化到表里。

@NameInDb("username")

指定相應(yīng)成員屬性在數(shù)據(jù)表里對應(yīng)的數(shù)據(jù)庫字段。使成員屬性名和數(shù)據(jù)庫名可以不一樣。

@Unique

唯一約束,如果put時,將要向表里增加的記錄和表里已經(jīng)有一個表記錄的字段值相同,則會拋異常UniqueViolationException

try {
    box.put(new User("Sam Flynn"));
} catch (UniqueViolationException e) {
    // A User with that name already exists.
}

3.Objectbox數(shù)據(jù)的增刪改查

3.1 增 put

notesBox = ObjectBox.get().boxFor(Note.class);

private void addNote() {
    ...
    Note note = new Note();
    note.setText(noteText);
    note.setComment(comment);
    note.setDate(new Date());
    notesBox.put(note);
    Log.d(App.TAG, "Inserted new note, ID: " + note.getId());
    ...
}

3.2刪除 remove

notesBox.remove(note);
Log.d(App.TAG, "Deleted note, ID: " + note.getId());

//關(guān)系表查詢時,會查出關(guān)聯(lián)的數(shù)據(jù),但是刪除時,關(guān)聯(lián)的數(shù)據(jù)并不會直接刪除。

3.3改

直接使用put ,但是id值不能為null
note.setText("This note has changed.");
notesBox.put(note);

3.4查

Query<User> query = userBox.query().equal(User_.firstName, "Joe").build();
List<User> joes = query.find();
query.close();

常用的查詢條件:

equal:值相等

greater:大于

startsWith:以xx為開始

3.4.1 多條件查詢 and or

// equal AND (less OR oneOf)
Query<User> query = box.query(
User_.firstName.equal("Joe")
.and(User_.age.less(12)
.or(User_.stamp.oneOf(new long[]{1012}))))
.order(User_.age)
.build();

3.4.2 Ordering 排序

還可以將標(biāo)志傳遞給order()以按降序排序、區(qū)分大小寫排序或特別處理空值。例如,要對上面的結(jié)果進(jìn)行降序和區(qū)分大小寫的排序

.order(User_.lastName, QueryBuilder.DESCENDING | QueryBuilder.CASE_SENSITIVE)

3.4.3 debugFlags

要查看ObjectBox實際執(zhí)行了什么查詢語句

// Set the LOG_QUERY_PARAMETERS debug flag
BoxStore store = MyObjectBox.builder()
.debugFlags(DebugFlags.LOG_QUERY_PARAMETERS)
.build();
// Execute a query
query.find();

//控制臺可以看到以下輸出
Parameters for query #2:
(firstName ==(i) "Joe"
 AND age < 12)

3.4.4 find操作查詢

// return all entities matching the query
List<User> joes = query.find();

// return only the first result or null if none
User joe = query.findFirst();

// return the only result or null if none, throw if more than one result 如果有多個結(jié)果,它會拋出一個異常。
User joe = query.findUnique();

3.4.5復(fù)用query和查詢參數(shù)。

如果您經(jīng)常運行相同的查詢,您應(yīng)該緩存query對象并重用它。要使Query更具可重用性,您甚至可以在構(gòu)建Query之后更改所添加的每個條件的值或查詢參數(shù),

相關(guān)方法setParameter

// build a query
Query<User> query = userBox.query().equal(User_.firstName, "").build();

// change firstName parameter to "Joe", get results
List<User> joes = query.setParameter(User_.firstName, "Joe").find();
...
// change firstName parameter to "Jake", get results
List<User> jakes = query.setParameter(User_.firstName, "Jake").find();

3.4.6 分頁相關(guān),Limit, Offset, and Pagination

// offset by 10, limit to at most 5 results
//下標(biāo)從0開始,包含開始下標(biāo)。
List<User> joes = query.find(10, 5);

3.4.7 延遲加載 Lazy loading results

為了避免立即加載查詢結(jié)果,query提供了findLazy()和findLazyCached(),它們返回查詢結(jié)果的LazyList。

LazyList是一個線程安全的、不可修改的列表,它只在實體被訪問時才惰性地讀取實體。根據(jù)調(diào)用的find方法,懶列表是否會被緩存。緩存的惰性列表存儲以前訪問過的對象,以避免多次加載實體。列表的一些特性僅限于緩存列表(例如需要整個列表的特性)

3.4.8 查詢結(jié)果作為一個流返回 Query results stream

暫只支持dart

Query<User> query = userBox.query().build();
Stream<User stream = query.stream();
await stream.forEach((User user) => print(user));
query.close();

3.4.9只查詢某一列的值。PropertyQuery

返回的屬性值數(shù)組沒有任何特定的順序,即使您在構(gòu)建查詢時指定了順序。

String[] emails = userBox.query().build()
.property(User_.email)
.findStrings();

// or use .findString() to return just the first result

默認(rèn)情況下,不返回空值。但是,如果一個屬性為空,你可以指定一個替換值來返回:

String[] emails = userBox.query().build()
.property(User_.email)
.nullValue("unknown")
.findStrings();

3.5.0 去重查詢 Distinct and unique results

PropertyQuery pq = userBox.query().build().property(User_.firstName);

// returns ['joe'] because by default, the case of strings is ignored.
String[] names = pq.distinct().findStrings();

// returns ['Joe', 'joe', 'JOE']
String[] names = pq.distinct(StringOrder.CASE_SENSITIVE).findStrings();

// the query can be configured to throw there is more than one value
String[] names = pq.unique().findStrings();

3.5.1 聚合值 Aggregating values

屬性查詢(JavaDoc和Dart API文檔)還提供了聚合函數(shù)來直接計算所有發(fā)現(xiàn)值的最小值、最大值、平均值、總和和計數(shù):

min() / minDouble():在匹配查詢的所有對象上查找給定屬性的最小值。

max() / maxDouble():找到最大值

sum() / sumDouble():計算所有值的和。注意:非雙精度版本檢測溢出并在這種情況下拋出異常。

avg():計算所有值的平均值(總是雙精度)。

count():返回結(jié)果的數(shù)量。這比查找和獲取結(jié)果數(shù)組的長度要快??梢耘cdistinct()組合使用,只計算不同值的數(shù)量。

3.5.2 關(guān)聯(lián)表查詢 links Add query conditions for related entities (links)

在創(chuàng)建實體之間的關(guān)系之后,您可能希望為只存在于相關(guān)實體中的屬性添加查詢條件。在SQL中,這可以使用join來解決。但由于ObjectBox不是一個SQL數(shù)據(jù)庫,我們構(gòu)建了一些非常類似的東西:links。鏈接基于關(guān)系

假設(shè)有一個Person可以與多個Address實體相關(guān)聯(lián): ToMany 一對多關(guān)系

@Entity
public class Person {
    @Id long id;
    String name;
    ToMany<Address> addresses;
}

@Entity
public class Address {
    @Id long id;
    String street;
    String zip;
}

獲取具有特定名稱且也居住在特定街道上的Person,我們需要查詢Person的關(guān)聯(lián)Address實體,為此,使用查詢構(gòu)建器的link()方法來說明應(yīng)該查詢地址關(guān)系。然后為Address添加一個條件。

// get all Person objects named "Elmo"...
QueryBuilder<Person> builder = personBox
    .query().equal(Person_.name, "Elmo");

// ...which have an address on "Sesame Street"
builder.link(Person_.addresses).equal(Address_.street, "Sesame Street");

List<Person> elmosOnSesameStreet = builder.build().find();

如果我們想要一個Address列表而不是Person列表,該怎么辦?

// get all Address objects with street "Sesame Street"...
QueryBuilder<Address> builder = addressBox.query()
.equal(Address_.street, "Sesame Street");

// ...which are linked from a Person named "Elmo"
builder.backlink(Person_.addresses).equal(Person_.name, "Elmo");

List<Address> sesameStreetsWithElmo = builder.build().find();

3.5.3 立即預(yù)取關(guān)聯(lián)查詢里的所有數(shù)據(jù) Eager Loading of Relations

Only Java/Kotlin

默認(rèn)情況下,關(guān)聯(lián)是惰性加載的:當(dāng)您第一次訪問ToOne或ToMany屬性時,它將執(zhí)行數(shù)據(jù)庫查找以獲取其數(shù)據(jù)。在每次后續(xù)訪問時,它將使用該數(shù)據(jù)的緩存版本。

List<Customer> customers = customerBox.query().build().find();

// Customer has a ToMany called orders.
// First access: this will cause a database lookup.
Order order = customers.get(0).orders.get(0);

雖然初始查找速度很快,但您可能希望在返回查詢結(jié)果之前預(yù)取ToOne或ToMany值。為此調(diào)用QueryBuilder。在構(gòu)建查詢時使用eager方法,并傳遞與ToOne和ToMany屬性關(guān)聯(lián)的RelationInfo對象來預(yù)取:

List<Customer> customers = customerBox.query()
.eager(Customer_.orders) // Customer has a ToMany called orders.
.build()
.find();

// First access: this will cause a database lookup.
Order order = customers.get(0).orders.get(0);

只適用于深復(fù)制。

3.5.4 查詢過濾器 Query filters

當(dāng)您尋找需要匹配復(fù)雜條件的對象時(這些條件不能用QueryBuilder類完全表示),查詢過濾器就發(fā)揮作用了。過濾器是用Java編寫的,因此可以表達(dá)任何復(fù)雜性。不用說,與基于java的過濾器相比,可以更有效地匹配數(shù)據(jù)庫條件。因此,當(dāng)你將兩者一起使用時,你將得到最好的結(jié)果:

1.使用標(biāo)準(zhǔn)數(shù)據(jù)庫條件將結(jié)果縮小到合理的數(shù)量

2.現(xiàn)在,使用QueryFilter Java接口對這些候選者進(jìn)行篩選,以確定最終結(jié)果

// Reduce object count to reasonable value.
songBox.query().equal(Song_.bandId, bandId)

// Filter is performed on candidate objects.
.filter((song) -> song.starCount * 2 > song.downloads);
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容