Android-數(shù)據(jù)庫-ORM框架

一.ORM介紹

對(duì)象關(guān)系映射Object Relational Mapping, 用于實(shí)現(xiàn)面向?qū)ο缶幊汤锊煌到y(tǒng)數(shù)據(jù)之間轉(zhuǎn)換!
面向?qū)ο笫菑鸟詈?聚合/封裝的基礎(chǔ)上發(fā)展, 關(guān)系數(shù)據(jù)庫是從數(shù)學(xué)理論發(fā)展而來;
兩套理論存在顯著的區(qū)別, ORM對(duì)象關(guān)系映射就是為了解決它們之間的差異!

直白地說,ORM建立對(duì)象和數(shù)據(jù)庫表的對(duì)應(yīng)關(guān)系,方便程序員直接用對(duì)象操作數(shù)據(jù)庫!

二.Java的ORM框架

Hibernate, iBatis, DbUtils,OrmLite等等

三.Android的ORM框架

OrmLite JDBC和Android的輕量級(jí)ORM java包
SugarORM 用超級(jí)簡(jiǎn)單的方法處理Android數(shù)據(jù)庫
GreenDAO 一種輕快地將對(duì)象映射到SQLite數(shù)據(jù)庫的ORM解決方案
ActiveAndroid 以活動(dòng)記錄方式為Android SQLite提供持久化
SQLBrite SQLiteOpenHelper 和ContentResolver的輕量級(jí)包裝
Realm是一個(gè)跨平臺(tái)移動(dòng)數(shù)據(jù)庫引擎,支持iOS、OS X(Objective-C和Swift)以及Android。
核心數(shù)據(jù)引擎C++打造,并不是建立在SQLite之上的ORM!

xUtils3, 源于afinal(已不再維護(hù)更新),都是國(guó)產(chǎn)框架,方便小巧工具集
包含了orm, http(s), image, view注解, 但依然很輕量級(jí)(246K), 并且特性強(qiáng)大, 方便擴(kuò)展
擁有更加靈活的ORM, 和greenDao一致的性能

四.xUtils3-ORM框架使用步驟

Android ORM框架繁多,走馬觀花看了大部分框架用法,還是覺得xUtils3比較方便使用!
xUtils3源碼和sample:https://github.com/wyouflf/xUtils3

吐槽一下:xUtils3在ORM框架這塊文檔說明和代碼注釋實(shí)在太少了!
好在ORM源碼不復(fù)雜,走一走流程就可以大概看懂!

1.在Application全局初始化

@Override
public void onCreate() {
    super.onCreate();
    x.Ext.init(this);
    x.Ext.setDebug(BuildConfig.DEBUG); //是否輸出debug日志,影響性能
    ...
}

2.創(chuàng)建實(shí)體類(與數(shù)據(jù)庫表映射)


@Table(name = "child") // 使用注解@Table @Column聲明表列
public class Child {
    @Column(name = "id", isId = true)
    private int id;

    @Column(name = "name")
    private String name;

    @Column(name = "email")
    private String email;

    @Column(name = "parentId" /*, property = "UNIQUE"http://如果是一對(duì)一加上唯一約束*/)
    private long parentId; // 外鍵表id

    // 被忽略,不存入數(shù)據(jù)庫
    private String willIgnore;

    @Column(name = "text")
    private String text;

    public long getParentId() {
        return parentId;
    }

    public void setParentId(long parentId) {
        this.parentId = parentId;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public String getWillIgnore() {
        return willIgnore;
    }

    public void setWillIgnore(String willIgnore) {
        this.willIgnore = willIgnore;
    }

    public String getText() {
        return text;
    }

    public void setText(String text) {
        this.text = text;
    }
}

3.增刪改查CRUD


DbManager.DaoConfig daoConfig = new DbManager.DaoConfig()
        .setDbName("test.db")
        // 不設(shè)置dbDir時(shí), 默認(rèn)存儲(chǔ)在app私有目錄.
        .setDbDir(new File("/sdcard")) // "sdcard"的寫法并非最佳實(shí)踐, 這里為了簡(jiǎn)單, 先這樣寫了.
        .setDbVersion(2)
        .setDbOpenListener(new DbManager.DbOpenListener() {
            @Override
            public void onDbOpened(DbManager db) {
                // 開啟WAL, 對(duì)寫入加速提升巨大
                db.getDatabase().enableWriteAheadLogging();
            }
        })
        .setDbUpgradeListener(new DbManager.DbUpgradeListener() {
            @Override
            public void onUpgrade(DbManager db, int oldVersion, int newVersion) {
                // TODO: ...
                // db.addColumn(...);
                // db.dropTable(...);
                // ...
                // or
                // db.dropDb();
            }
        });
        
private void testDb() throws DbException {
    DbManager db = x.getDb(daoConfig );
    // 1.插入(沒有表,會(huì)創(chuàng)建)——————————————————————————
    // 1.1插入一條
    Child child = new Child();
    child.setName("childname");
    db.save(child);
    // 1.2插入多條
    List<Child> childList = new ArrayList<>();
    childList.add(child);
    childList.add(child);
    db.save(childList);

    // 2.查找——————————————————————————
    // 2.1不用select()篩選列,返回結(jié)果Child類 或List<Child>
    Child child2 = db.selector(Child.class).where("id", "=", new String[]{"1"}).findFirst();
    List<Child> childList2 = db.selector(Child.class).where("id", "between", new String[]{"1", "5"}).findAll();
    // 2.2使用select()篩選列,返回結(jié)果DbModel 或List<DbModel>
    DbModel dbModel = db.selector(Parent.class).select("name").findFirst();
    List<DbModel> dbModels = db.selector(Parent.class).select("name").findAll();
    // 2.3使用原生sql查詢語句,多表內(nèi)連接查詢
    Cursor cursor = db.execQuery("select name from child, parent where parent.id = child.id");

    // 3.修改——————————————————————————
    child.setName("xxx");
    child.setEmail("xxx@qq.com");
    db.update(child);// 根據(jù)child的id更新
    db.update(Child.class, WhereBuilder.b("name", "=", "childname"),
            new KeyValue("name", "xxx"));

    // 4.刪除——————————————————————————
    db.delete(child);// 根據(jù)child的id刪除
    db.delete(Child.class, WhereBuilder.b("name", "=", "xxx"));
}

// 性能測(cè)試————————————————————————————
private void testDb2() {
    tv_db_result.setText("wait...");
    x.task().run(new Runnable() {
        @Override
        public void run() {
            // 后臺(tái)線程
            DbManager db = x.getDb(daoConfig);
            String result = "";
            int count = 10000;
            long start;
            List<Parent> parentList = new ArrayList<>();
            for (int i = 0; i < count; i++) {
                Parent parent = new Parent();
                parent.setAdmin(true);
                parent.setDate(new java.sql.Date(1234));
                parent.setTime(new Date());
                parent.setEmail(i + "_@qq.com");
                parentList.add(parent);
            }

            // 批量插入————————————————————————————
            start = System.currentTimeMillis();
            try {
                db.save(parentList);
            } catch (DbException ex) {
                ex.printStackTrace();
            }
            result += "批量插入" + count + "條數(shù)據(jù):" + (System.currentTimeMillis() - start) + "ms\n";

            // 循環(huán)插入————————————————————————————
            start = System.currentTimeMillis();
            for (Parent parent : parentList) {
                try {
                    db.save(parent);
                } catch (DbException ex) {
                    ex.printStackTrace();
                }
            }
            result += "循環(huán)插入" + count + "條數(shù)據(jù):" + (System.currentTimeMillis() - start) + "ms\n";
            count *= 2;

            // 查找————————————————————————————
            start = System.currentTimeMillis();
            try {
                parentList = db.selector(Parent.class).limit(count).findAll();
            } catch (DbException ex) {
                ex.printStackTrace();
            }
            result += "查找" + count + "條數(shù)據(jù):" + (System.currentTimeMillis() - start) + "ms\n";

            // 刪除————————————————————————————
            start = System.currentTimeMillis();
            try {
                db.delete(parentList);
            } catch (DbException ex) {
                ex.printStackTrace();
            }
            result += "刪除" + count + "條數(shù)據(jù):" + (System.currentTimeMillis() - start) + "ms\n";

            final String finalResult = result;
            x.task().post(new Runnable() {
                @Override
                public void run() {
                    // UI線程
                    tv_db_result.setText(finalResult);
                }
            });
        }
    });
}

簡(jiǎn)書: http://www.lxweimin.com/p/ad04259ed980
CSDN博客: http://blog.csdn.net/qq_32115439/article/details/72034554
GitHub博客:http://lioil.win/2017/05/14/Android_ORM.html
Coding博客:http://c.lioil.win/2017/05/14/Android_ORM.html

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

推薦閱讀更多精彩內(nèi)容