安卓-ObjectBox数据库笔记1:gradle配置和常用增删改查

(安卓)ObjectBox数据库笔记

[TOC]

1.Gradle设置

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下生成相应的文件,例如MyObjectBox等。

同时,会自动生成 app/objectbox-models/default.json文件,请把这一个文件加入版本控制,不要删除。不要手动修改里面的内容。

1.6.2 创建 BoxStore

在Application里初始化BoxStore后,可以使用BoxStore对数据表进行增删改查操作。

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.实体类相关注解

@Entity
public class User {
    @Id 
    public long id;
    public String name;
    //如果字段是私有的,则必须有一个标准的getters方法。
     private String name2;
     public String getName2() {
        return this.name;
    }

}
@Entity

注解到class上,代表是一个数据库表,实体也必须有一个无参数的构造函数

@Id :

注解到成员属性上,代表是自增id,必须是long型(java kotlin 里是long型 dart里是int型),@Id 注解的成员属性不能是私有的。默认情况下,ID属性是惟一的,并且有索引。向表里新增数据时,如果不指定id,则新对象的id由ObjectBox分配

@Index

注解到成员属性上,代表索引,可以在查询时,提高性能。@Index目前不支持String[], byte[], float和double。查询时,如果是字符串,则使用区分大小写的条件

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

注解到成员属性上,代表这一个属性不被持久化到表里。java里的静态属性也不会持久化到表里。

@NameInDb("username")

指定相应成员属性在数据表里对应的数据库字段。使成员属性名和数据库名可以不一样。

@Unique

唯一约束,如果put时,将要向表里增加的记录和表里已经有一个表记录的字段值相同,则会抛异常UniqueViolationException

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

3.Objectbox数据的增删改查

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());

//关系表查询时,会查出关联的数据,但是删除时,关联的数据并不会直接删除。

3.3改

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

3.4查

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

常用的查询条件:

equal:值相等

greater:大于

startsWith:以xx为开始

3.4.1 多条件查询 and or

// equal AND (less OR oneOf)
Query 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 排序

还可以将标志传递给order()以按降序排序、区分大小写排序或特别处理空值。例如,要对上面的结果进行降序和区分大小写的排序

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

3.4.3 debugFlags

要查看ObjectBox实际执行了什么查询语句

// 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 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 如果有多个结果,它会抛出一个异常。
User joe = query.findUnique();

3.4.5复用query和查询参数。

如果您经常运行相同的查询,您应该缓存query对象并重用它。要使Query更具可重用性,您甚至可以在构建Query之后更改所添加的每个条件的值或查询参数,

相关方法setParameter

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

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

3.4.6 分页相关,Limit, Offset, and Pagination

// offset by 10, limit to at most 5 results
//下标从0开始,包含开始下标。
List joes = query.find(10, 5);

3.4.7 延迟加载 Lazy loading results

为了避免立即加载查询结果,query提供了findLazy()和findLazyCached(),它们返回查询结果的LazyList。

LazyList是一个线程安全的、不可修改的列表,它只在实体被访问时才惰性地读取实体。根据调用的find方法,懒列表是否会被缓存。缓存的惰性列表存储以前访问过的对象,以避免多次加载实体。列表的一些特性仅限于缓存列表(例如需要整个列表的特性)

3.4.8 查询结果作为一个流返回 Query results stream

暂只支持dart

Query query = userBox.query().build();
Stream print(user));
query.close();

3.4.9只查询某一列的值。PropertyQuery

返回的属性值数组没有任何特定的顺序,即使您在构建查询时指定了顺序。

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

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

默认情况下,不返回空值。但是,如果一个属性为空,你可以指定一个替换值来返回:

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文档)还提供了聚合函数来直接计算所有发现值的最小值、最大值、平均值、总和和计数:

min() / minDouble():在匹配查询的所有对象上查找给定属性的最小值。

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

sum() / sumDouble():计算所有值的和。注意:非双精度版本检测溢出并在这种情况下抛出异常。

avg():计算所有值的平均值(总是双精度)。

count():返回结果的数量。这比查找和获取结果数组的长度要快。可以与distinct()组合使用,只计算不同值的数量。

3.5.2 关联表查询 links Add query conditions for related entities (links)

在创建实体之间的关系之后,您可能希望为只存在于相关实体中的属性添加查询条件。在SQL中,这可以使用join来解决。但由于ObjectBox不是一个SQL数据库,我们构建了一些非常类似的东西:links。链接基于关系

假设有一个Person可以与多个Address实体相关联: ToMany 一对多关系

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

获取具有特定名称且也居住在特定街道上的Person,我们需要查询Person的关联Address实体,为此,使用查询构建器的link()方法来说明应该查询地址关系。然后为Address添加一个条件。

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

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

List elmosOnSesameStreet = builder.build().find();

如果我们想要一个Address列表而不是Person列表,该怎么办?

// get all Address objects with street "Sesame Street"...
QueryBuilder
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
sesameStreetsWithElmo = builder.build().find();

3.5.3 立即预取关联查询里的所有数据 Eager Loading of Relations

Only Java/Kotlin

默认情况下,关联是惰性加载的:当您第一次访问ToOne或ToMany属性时,它将执行数据库查找以获取其数据。在每次后续访问时,它将使用该数据的缓存版本。

List 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);

虽然初始查找速度很快,但您可能希望在返回查询结果之前预取ToOne或ToMany值。为此调用QueryBuilder。在构建查询时使用eager方法,并传递与ToOne和ToMany属性关联的RelationInfo对象来预取:

List 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);

只适用于深复制。

3.5.4 查询过滤器 Query filters

当您寻找需要匹配复杂条件的对象时(这些条件不能用QueryBuilder类完全表示),查询过滤器就发挥作用了。过滤器是用Java编写的,因此可以表达任何复杂性。不用说,与基于java的过滤器相比,可以更有效地匹配数据库条件。因此,当你将两者一起使用时,你将得到最好的结果:

1.使用标准数据库条件将结果缩小到合理的数量

2.现在,使用QueryFilter Java接口对这些候选者进行筛选,以确定最终结果

// 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);

你可能感兴趣的:(安卓-ObjectBox数据库笔记1:gradle配置和常用增删改查)