美文网首页数据处理安全
Realm使用入门 (一)

Realm使用入门 (一)

作者: 元亨利贞o | 来源:发表于2016-09-03 01:13 被阅读6642次

    一. 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的):

    introduce

    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

    相关文章

      网友评论

        本文标题:Realm使用入门 (一)

        本文链接:https://www.haomeiwen.com/subject/hahkettx.html