天天看點

Android官方ORM資料庫Room技術解決方案簡介(一)

是時候該忘記Android SQLite了!Android官方ORM資料庫Room技術解決方案簡介(一)

Android的Romm是Android官方整合出來的一攬子ORM資料庫解決方案。Android Room和曆史上的ORM資料庫如Android ORMLite(見附錄文章1,2),Android greenDao等等,有諸多相同的設計思想和理念,但Android Room同時吸收衆家ORM資料庫之長,有自己新的創新和改進。我将分開寫若幹篇文章,逐點介紹Android官方的ORM資料庫技術解決方案:Room。

(一)使用Android Room,首先要在gradle添加引用,我是基于room的version 1.0.0:

implementation 'android.arch.persistence.room:runtime:1.0.0'
    annotationProcessor 'android.arch.persistence.room:compiler:1.0.0'           

(二)和其他ORM資料庫相似,Android Room需要先建立資料庫表和Java對象的模型,User.java:

package zhangphil.demo;

import android.arch.persistence.room.ColumnInfo;
import android.arch.persistence.room.Entity;
import android.arch.persistence.room.PrimaryKey;

/**
 * Created by Phil on 2017/11/22.
 */

@Entity(tableName = "user_table")
public class User {
    @PrimaryKey(autoGenerate = true)
    public int id;

    @ColumnInfo(name = "userName")
    public String name;

    @ColumnInfo(name = "userAge")
    public int age;

    @ColumnInfo(name = "updateTime")
    public long updateTime;
}
           

注解@Entity告訴Android Room,該User類将是一個資料庫中的表。tableName如果開發者不自定義,那麼Android系統預設将使用類名作為資料庫中的表名。本例中的User,指定了表名為“user_table”,開發者可以根據自己情況自命名。

@PrimaryKey标注該字段是表中的主鍵,可根據該主鍵進行資料庫的基本增删改查等等這些操作。當設定autoGenerate = true後,該主鍵将自增長。@ColumnInfo注解後面跟着的name,标明定義的Java變量将作為表中的一列。比如User中的

@ColumnInfo(name = "userName")
    public String name;           

那麼資料庫中表的一列userName中存儲的資料就是name。

(三)建構針對User的Dao。UserDao.java:

package zhangphil.demo;

import android.arch.persistence.room.Dao;
import android.arch.persistence.room.Delete;
import android.arch.persistence.room.Insert;
import android.arch.persistence.room.OnConflictStrategy;
import android.arch.persistence.room.Query;
import android.arch.persistence.room.Update;

import java.util.List;

/**
 * Created by Phil on 2017/11/22.
 */

@Dao
public interface UserDao {
    /**
     * 查詢
     *
     * @return
     */
    @Query("SELECT * FROM user_table")
    public List<User> getAllUsers();

    /**
     * 添加
     *
     * @param users
     */
    @Insert(onConflict = OnConflictStrategy.REPLACE)
    public void insertUser(User... users);

    /**
     * 更新
     *
     * @param users
     */
    @Update
    public void updateUser(User... users);

    /**
     * 删除
     *
     * @param users
     */
    @Delete
    public void deleteUser(User... users);
}
           

@Dao注解标明該Java類是一個Android Room中的Dao對象。Android Room中的Dao,可以以接口interface形式定義。Android Room中的查詢以SQL标準語句定義。比如在UserDao中的定義的:

/**
     * 查詢
     *
     * @return
     */
    @Query("SELECT * FROM user_table")
    public List<User> getAllUsers();
           

該SQL語句将從我之前建立的資料塊表“user_table”中,查詢出所有的内容,然後傳回一個集合。其他關于資料庫的操作如增加(@Insert),删除(@Delete),修改(更新,@Update),均以注解标明。這些基本操作可以按照User中定義的@PrimaryKey主鍵操作。

(四)構造資料庫。

這一步在Android Room技術中基本上是規範化的代碼,寫法比較規矩,建立UserDatabase.java:

package zhangphil.demo;

import android.arch.persistence.room.Database;
import android.arch.persistence.room.RoomDatabase;

/**
 * Created by Phil on 2017/11/22.
 */

@Database(entities = {User.class}, version = 1)
public abstract  class UserDatabase  extends RoomDatabase {
    public abstract UserDao getUserDao();
}
           

UserDatabase最重要的功能是提供給開發者各種Dao。開發者獲得Dao後,就可以像操作基本Java對象執行個體一樣操作Android Room資料中資料。

最終的代碼結構如圖:

(五)在MainActivity.java中測試我寫的Android Room。注意涉及到資料庫操作,要放到背景線程中運作。MainActivity.java:

package zhangphil.demo;

import android.arch.persistence.room.Room;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;

import java.util.List;

public class MainActivity extends AppCompatActivity {

    private String TAG = "輸出";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        new Thread(new Runnable() {
            @Override
            public void run() {
                databaseOperation();
            }
        }).start();
    }

    private void databaseOperation() {
        UserDatabase mUserDatabase = Room.databaseBuilder(getApplicationContext(), UserDatabase.class, "users").build();
        UserDao mUserDao = mUserDatabase.getUserDao();

        //寫資料庫
        Log.d(TAG, "開始寫入資料...");
        writeDatabase(mUserDao, "張三", 18);
        writeDatabase(mUserDao, "李四", 19);
        Log.d(TAG, "寫入資料庫完畢.");

        //讀資料庫
        Log.d(TAG, "第1次讀資料庫");
        readDatabase(mUserDao);

        //更新資料庫
        updateUser(mUserDao);

        //讀資料庫
        Log.d(TAG, "第2次讀資料庫");
        readDatabase(mUserDao);

        //删除資料,根據主鍵id
        deleteUser(mUserDao, 1);

        //讀資料庫
        Log.d(TAG, "第3次讀資料庫");
        readDatabase(mUserDao);

        Log.d(TAG, "========================");
        Log.d(TAG, "本輪資料庫操作事務全部結束");
        Log.d(TAG, "========================");
    }

    private void readDatabase(UserDao dao) {
        Log.d(TAG, "讀資料庫...");
        List<User> users = dao.getAllUsers();
        for (User u : users) {
            Log.d(TAG, u.id + "," + u.name + "," + u.age + "," + u.updateTime);
        }
        Log.d(TAG, "讀資料庫完畢.");
    }

    private void writeDatabase(UserDao dao, String name, int age) {
        User user = new User();
        user.name = name;
        user.age = age;
        user.updateTime = System.currentTimeMillis();
        dao.insertUser(user);
    }

    private void updateUser(UserDao dao) {
        Log.d(TAG, "更新資料庫...");
        User u = new User();
        u.id = 2;
        u.name = "趙五";
        u.age = 20;
        u.updateTime = System.currentTimeMillis();
        dao.updateUser(u);
        Log.d(TAG, "更新資料庫完畢.");
    }

    private void deleteUser(UserDao dao, int id) {
        Log.d(TAG, "删除資料庫...");
        User u = new User();
        u.id = id;
        dao.deleteUser(u);
        Log.d(TAG, "删除資料庫完畢.");
    }
}
           

MainActivity.java實作基本的功能,在資料庫中添加寫入兩條資料條目。然後在第一次讀資料庫操作中,從資料中讀出來觀察是否已經寫進去。

接着更新資料庫,根據User的PrimaryKey主鍵id更新,我把資料庫中主鍵id為2的資料行更新。再次第2次讀資料庫,驗證我的更新操作是否成功。

然後再根據主鍵删除id=1的資料庫資料行,第3次讀資料庫,驗證資料庫删除的操作。代碼運作後的logcat輸出:

11-23 10:49:22.631 19616-19641/zhangphil.demo D/輸出: 開始寫入資料...
11-23 10:49:22.688 19616-19641/zhangphil.demo D/輸出: 寫入資料庫完畢.
11-23 10:49:22.688 19616-19641/zhangphil.demo D/輸出: 第1次讀資料庫
11-23 10:49:22.688 19616-19641/zhangphil.demo D/輸出: 讀資料庫...
11-23 10:49:22.689 19616-19641/zhangphil.demo D/輸出: 1,張三,18,1511405362631
11-23 10:49:22.689 19616-19641/zhangphil.demo D/輸出: 2,李四,19,1511405362674
11-23 10:49:22.689 19616-19641/zhangphil.demo D/輸出: 讀資料庫完畢.
11-23 10:49:22.689 19616-19641/zhangphil.demo D/輸出: 更新資料庫...
11-23 10:49:22.692 19616-19641/zhangphil.demo D/輸出: 更新資料庫完畢.
11-23 10:49:22.692 19616-19641/zhangphil.demo D/輸出: 第2次讀資料庫
11-23 10:49:22.692 19616-19641/zhangphil.demo D/輸出: 讀資料庫...
11-23 10:49:22.693 19616-19641/zhangphil.demo D/輸出: 1,張三,18,1511405362631
11-23 10:49:22.693 19616-19641/zhangphil.demo D/輸出: 2,趙五,20,1511405362689
11-23 10:49:22.693 19616-19641/zhangphil.demo D/輸出: 讀資料庫完畢.
11-23 10:49:22.693 19616-19641/zhangphil.demo D/輸出: 删除資料庫...
11-23 10:49:22.696 19616-19641/zhangphil.demo D/輸出: 删除資料庫完畢.
11-23 10:49:22.696 19616-19641/zhangphil.demo D/輸出: 第3次讀資料庫
11-23 10:49:22.696 19616-19641/zhangphil.demo D/輸出: 讀資料庫...
11-23 10:49:22.698 19616-19641/zhangphil.demo D/輸出: 2,趙五,20,1511405362689
11-23 10:49:22.698 19616-19641/zhangphil.demo D/輸出: 讀資料庫完畢.
11-23 10:49:22.698 19616-19641/zhangphil.demo D/輸出: ========================
11-23 10:49:22.698 19616-19641/zhangphil.demo D/輸出: 本輪資料庫操作事務全部結束
11-23 10:49:22.699 19616-19641/zhangphil.demo D/輸出: ========================
           

附錄:

1,《Android ORMLite資料庫簡介》連結:http://blog.csdn.net/zhangphil/article/details/46878075 

2,《Android ORMLite ForeignCollection關聯外部集合》連結:http://blog.csdn.net/zhangphil/article/details/46891021