一. Realm是一个更好的手机平台上的数据库, 它是一个易用、更快、非常先进文件数据库,底层使用JNI实现. 支持多种编程环境, 如: Java、Object-C、React Native、Swift、Xamarin。
Realm的官网: https://realm.io
github地址: https://github.com/realm
realm-java库的文档: https://realm.io/docs/java/latest/
下面是其官网的截图 (官网做的非常简洁漂亮,富有设计感. 说实话, 我就是被这个漂亮的网页吸引了, 才使用Realm的):
Realm的特性:
features
二. 使用
虽说Realm看起来如此美好, 但第一次使用Realm的过程那是相等痛苦.
下面说说Realm的简单用法:
- 在module的build.gradle文件中添加如下配置 (与realm无关的配置省略)
buildscript {
repositories {
jcenter()
}
dependencies {
//1. 添加realm插件
classpath "io.realm:realm-gradle-plugin:1.2.0"
}
}
//2. 应用realm插件
apply plugin: 'realm-android'
dependencies {
//3. 添加realm库
compile 'io.realm:realm-android-library:1.2.0'
}
-
初始化Realm
public void init(Context appContext, long dbVersion) {
mConfig = new RealmConfiguration.Builder(appContext)
.name("app.realm") //指定realm的文件名称, 会在/data/data/package-name/files/目录下面生成app.realm文件
.encryptionKey(new byte[64]) //base64加密key
.schemaVersion(dbVersion) //realm版本
.build();
mRealm = Realm.getInstance(mConfig);
}
```
-
CURD操作
Realm规定所有改动操作必须在事务中进行, 即改动操作必须在Realm的beginTransaction()
和commitTransaction()
方法之间进行 或者在executeTransaction方法的参数的回调中执行. 改动操作有: createObject/copyXxx/insert/deleteXxx 等**添加操作: **
public Movie add(Movie movie) {
//如果创建一个新对象, PrimaryKey的值为默认值(整型0), 那么第二次添加数据时, 使用
//Realm.createObject()/Realm.copyToRealm()/Realm.insert()都会抛出下面的异常,
//因为第一次插入的数据的PrimaryKey就是0, 而PrimaryKey是不能重复的
/*
io.realm.exceptions.RealmPrimaryKeyConstraintException: Value already exists: 0
at io.realm.internal.Table.throwDuplicatePrimaryKeyException(Table.java:727)
at io.realm.internal.Table.addEmptyRow(Table.java:414)
at io.realm.Realm.createObject(Realm.java:681)
*/
//方式一
mRealm.beginTransaction();
//必须设置新的PrimaryKey
movie.setId(generateNewPrimaryKey()); // TODO: 16/9/2 为了获取新的PrimaryKey进行了一次查询, 有待优化
mRealm.insert(movie);
mRealm.commitTransaction();
//方式二
// mRealm.executeTransaction(realm -> {
// //必须设置新的PrimaryKey
// movie.setId(generateNewPrimaryKey()); // TODO: 16/9/2 为了获取新的PrimaryKey进行了一次查询, 有待优化
// realm.insert(movie);
// });
return movie;
}
//获取最大的PrimaryKey并加一
private long generateNewPrimaryKey() {
long primaryKey = 0;
RealmResults<Movie> results = mRealm.where(Movie.class).findAll();
if(results != null && results.size() > 0) {
Movie last = results.last();
primaryKey = last.getId() + 1;
}
return primaryKey;
}
更新操作
public Movie update(Movie movie) {
mRealm.beginTransaction();
//如果操作的对象没有PrimaryKey, 会报错: java.lang.IllegalArgumentException: A RealmObject with no @PrimaryKey cannot be updated: class com.stone.hostproject.db.model.Movie
Movie dbMovie = mRealm.copyToRealmOrUpdate(movie);
mRealm.commitTransaction();
return dbMovie;
}
public Movie updateById(long id, Movie newMovie) {
//查询
Movie dbMovie = mRealm.where(Movie.class)
.equalTo("id", id)
.findFirst();
//更新字段
dbMovie.setName(newMovie.getName());
dbMovie.setDirectors(newMovie.getDirectors());
dbMovie.setCasts(newMovie.getCasts());
//更新到realm中
mRealm.beginTransaction();
mRealm.copyToRealmOrUpdate(dbMovie);
mRealm.commitTransaction();
return dbMovie;
}
查询操作
public List<Movie> load() {
//异步查询
// mRealm.where(Movie.class).
// findAllAsync()
// .asObservable()
// .observeOn(AndroidSchedulers.mainThread())
// .subscribe(results -> {
// });
//条件查询
// RealmResults<Movie> results1 = mRealm.where(Movie.class)
// .greaterThan("year", 2000)
// .findAllSorted("year", Sort.DESCENDING); //Sort by year, in descending order
//同步查询所有数据
return mRealm.where(Movie.class).findAll();
}
删除操作
public void delete(Movie movie) {
if(movie.getId() < 0) {
throw new IllegalArgumentException("非法参数: Movie的id不正确");
}
//managed, 直接删除
if(movie.isValid()) {
mRealm.beginTransaction();
movie.deleteFromRealm();
mRealm.commitTransaction();
return;
}
//unmanaged: 先查询, 再删除
deleteById(movie.getId());
}
public void deleteById(long id) {
//查询
Movie dbMovie = mRealm.where(Movie.class)
.equalTo("id", id)
.findFirst();
//删除
mRealm.beginTransaction();
dbMovie.deleteFromRealm();
mRealm.commitTransaction();
}
==========================================
Movie.java文件如下
import io.realm.RealmObject;
import io.realm.annotations.PrimaryKey;
public class Movie extends RealmObject {
//id字段作为主键 (int/long类型的默认值为0, 如果realm已经存在了一个id为0的数据, 那么调用
//Realm.createObject()/Realm.copyToRealm()/Realm.insert()的时候会冲突, 因为PrimaryKey是惟一的, 不允许重复
@PrimaryKey
private long id; //由于上述原因, id必须手动设置, 且不能与realm中已存在的PrimaryKey相同
private String image;
private String name;
private String directors;
private String casts;
//如果有带参数的构造方法, 那么无参构造方法必须显式提供
public Movie() {
}
public Movie(String image, String name, String directors, String casts) {
this.image = image;
this.name = name;
this.directors = directors;
this.casts = casts;
}
public Movie(long id, String image, String name, String directors, String casts) {
this.id = id;
this.image = image;
this.name = name;
this.directors = directors;
this.casts = casts;
}
public String getImage() {
return image;
}
public void setImage(String image) {
this.image = image;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDirectors() {
return directors;
}
public void setDirectors(String directors) {
this.directors = directors;
}
public String getCasts() {
return casts;
}
public void setCasts(String casts) {
this.casts = casts;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
}
下面是一个CURD操作的完整类(DbManager.java)
import android.app.Application;
import android.content.Context;
import java.util.List;
import io.realm.Realm;
import io.realm.RealmConfiguration;
import io.realm.RealmResults;
public final class DbManager {
private RealmConfiguration mConfig;
private Realm mRealm;
private DbManager() {}
private static class InstanceHolder {
private static final DbManager INSTANCE = new DbManager();
}
public static DbManager get() {
return InstanceHolder.INSTANCE;
}
/**
* 初始化Realm, 建议在{@link Application#onCreate()}方法中调用
* @param appContext
* @param dbVersion
*/
public void init(Context appContext, long dbVersion) {
mConfig = new RealmConfiguration.Builder(appContext)
.name("app.realm")
.encryptionKey(new byte[64])
.schemaVersion(dbVersion)
.deleteRealmIfMigrationNeeded()
.build();
mRealm = Realm.getInstance(mConfig);
}
/**
* 退出应用的时候调用
*/
public void destroy() {
if (mRealm != null) {
if(!mRealm.isClosed()) {
mRealm.close();
}
mRealm = null;
}
}
/**
* @param movie 要添加的对象
* @return 返回realm中的对象
*/
public Movie add(Movie movie) {
//如果创建一个新对象, PrimaryKey的值为默认值(整型0), 那么第二次添加数据时, 使用
//Realm.createObject()/Realm.copyToRealm()/Realm.insert()都会抛出下面的异常,
//因为第一次插入的数据的PrimaryKey就是0, 而PrimaryKey是不能重复的
/*
io.realm.exceptions.RealmPrimaryKeyConstraintException: Value already exists: 0
at io.realm.internal.Table.throwDuplicatePrimaryKeyException(Table.java:727)
at io.realm.internal.Table.addEmptyRow(Table.java:414)
at io.realm.Realm.createObject(Realm.java:681)
*/
//方式一
// mRealm.beginTransaction();
// //必须设置新的PrimaryKey
// movie.setId(generateNewPrimaryKey()); // TODO: 16/9/2 为了获取新的PrimaryKey进行了一次查询, 有待优化
// mRealm.insert(movie);
// mRealm.commitTransaction();
// //方式二
mRealm.executeTransaction(realm -> {
//必须设置新的PrimaryKey
movie.setId(generateNewPrimaryKey()); // TODO: 16/9/2 为了获取新的PrimaryKey进行了一次查询, 有待优化
realm.insert(movie);
});
return movie;
}
//获取最大的PrimaryKey并加一
private long generateNewPrimaryKey() {
long primaryKey = 0;
//必须排序, 否则last可能不是PrimaryKey最大的数据. findAll()查询出来的数据是乱序的
RealmResults<Movie> results = mRealm.where(Movie.class).findAllSorted("id", Sort.ASCENDING);
if(results != null && results.size() > 0) {
Movie last = results.last(); //根据id顺序排序后, last()取得的对象就是PrimaryKey的值最大的数据
primaryKey = last.getId() + 1;
}
return primaryKey;
}
/**
*
* @param movie movie的id, 必须有realm中的对象的id (@PrimaryKey标志的字段)
* @return 返回更改后的realm中的对象
*/
public Movie update(Movie movie) {
mRealm.beginTransaction();
//如果RealmObject对象没有primaryKey, 会报错: java.lang.IllegalArgumentException: A RealmObject with no @PrimaryKey cannot be updated: class com.stone.hostproject.db.model.Movie
Movie dbMovie = mRealm.copyToRealmOrUpdate(movie);
mRealm.commitTransaction();
return dbMovie;
}
public Movie updateById(long id, Movie newMovie) {
//查询
Movie dbMovie = mRealm.where(Movie.class)
.equalTo("id", id)
.findFirst();
//更新字段
dbMovie.setName(newMovie.getName());
dbMovie.setDirectors(newMovie.getDirectors());
dbMovie.setCasts(newMovie.getCasts());
//复制到realm中
mRealm.beginTransaction();
mRealm.copyToRealmOrUpdate(dbMovie);
mRealm.commitTransaction();
return dbMovie;
}
public void delete(Movie movie) {
if(movie.getId() < 0) {
throw new IllegalArgumentException("非法参数: Movie的id不正确");
}
//managed, 直接删除
if(movie.isValid()) {
mRealm.beginTransaction();
movie.deleteFromRealm();
mRealm.commitTransaction();
return;
}
//unmanaged: 先查询, 再删除
deleteById(movie.getId());
}
public void deleteById(long id) {
//查询
Movie dbMovie = mRealm.where(Movie.class)
.equalTo("id", id)
.findFirst();
//删除
mRealm.beginTransaction();
dbMovie.deleteFromRealm();
mRealm.commitTransaction();
}
public List<Movie> load() {
//异步查询
// mRealm.where(Movie.class).
// findAllAsync()
// .asObservable()
// .observeOn(AndroidSchedulers.mainThread())
// .subscribe(results -> {
// });
//条件查询
// RealmResults<Movie> results1 = mRealm.where(Movie.class)
// .greaterThan("year", 2000)
// .findAllSorted("year", Sort.DESCENDING); //Sort by year, in descending order
//同步查询所有数据(根据id倒序排序, 最后添加的在ListView的顶部)
return mRealm.where(Movie.class).findAllSorted("id", Sort.DESCENDING);
}
}
references:
https://realm.io
https://realm.io/docs/java/latest/
https://github.com/realm/realm-java
网友评论