你還在為數(shù)據(jù)庫(kù)建表時(shí)那復(fù)雜而冗長(zhǎng)的SQL語(yǔ)句煩惱么?
你還在為數(shù)據(jù)庫(kù)存儲(chǔ)時(shí)那頻繁的put content values而感到焦躁么照激?
你還在為在數(shù)據(jù)庫(kù)操作中只因?yàn)镾QL語(yǔ)句中寫錯(cuò)了一個(gè)字母而找了半天bug
而感到沮喪么霎冯?
快用GreenDao吧铃拇,解決以上各種疑難雜癥,從此告別SQL語(yǔ)句沈撞。
回顧SQLiteDatabaseHelper
1.表的創(chuàng)建
如果你的數(shù)據(jù)庫(kù)當(dāng)中有20個(gè)數(shù)據(jù)模型慷荔,你要將以下面這段東西寫20遍,還不帶重樣的- -缠俺。
If you type a wrong letter显晶,loses the whole game
@Override
public void onCreate(SQLiteDatabase db) {
StringBuilder sb2 = new StringBuilder();
sb2.append("CREATE TABLE "+ TABLE_NAME+ "(")
.append("_id INTEGER PRIMARY KEY AUTOINCREMENT,")
.append("it TEXT,")
.append("is TEXT,")
.append("too TEXT,")
.append("painful TEXT,")
.append("do INTEGER,")
.append("you TEXT,")
.append("think BIGINT,")
.append("so INTEGER")
.append(");");
db.execSQL(sb2.toString());
}
2.數(shù)據(jù)庫(kù)的存儲(chǔ)操作
//以寫入模式獲取數(shù)據(jù)存儲(chǔ)庫(kù)
SQLiteDatabase db = mDbHelper.getWritableDatabase();
//創(chuàng)建一個(gè)新的值映射,其中列名稱是鍵
values.put(FeedEntry.COLUMN_NAME_TITLE, title);
values.put(FeedEntry.COLUMN_NAME_SUBTITLE, subtitle);
//插入新行壹士,返回新行的主鍵值
long newRowId = db.insert(FeedEntry.TABLE_NAME, null, values);
3.數(shù)據(jù)庫(kù)的查詢
SQLiteDatabase db = mDbHelper.getReadableDatabase();
// 指定數(shù)據(jù)庫(kù)中的哪些列
String[] projection = {FeedEntry._ID, FeedEntry.COLUMN_NAME_TITLE, FeedEntry.COLUMN_NAME_SUBTITLE };
// 過濾title值為 'My Title'的數(shù)據(jù)
String selection = FeedEntry.COLUMN_NAME_TITLE + " = ?";
String[] selectionArgs = { "My Title" };
// 制定返回結(jié)果的排列順序
String sortOrder = FeedEntry.COLUMN_NAME_SUBTITLE + " DESC";
Cursor c = db.query(FeedEntry.TABLE_NAME, // 你要查詢的表
projection, // 要返回的列
selection, //定義的數(shù)據(jù)過濾規(guī)則
selectionArgs, // 過濾后返回的參數(shù)
null, // 不對(duì)行進(jìn)行分組
null, //不按照行分的組過濾數(shù)據(jù)
sortOrder // 定義的排序規(guī)則 );
cursor.moveToFirst();
long itemId = cursor.getLong(cursor.getColumnIndexOrThrow(FeedEntry._ID));
4.數(shù)據(jù)庫(kù)的刪除
// 定義查詢位置
String selection = FeedEntry.COLUMN_NAME_TITLE + " LIKE ?";
// 制定要?jiǎng)h除的參數(shù)(既title = 'MyTitle')
String[] selectionArgs = { "MyTitle" };
// 對(duì)應(yīng)的刪除操作
db.delete(FeedEntry.TABLE_NAME, selection, selectionArgs)
5.數(shù)據(jù)庫(kù)的更新
SQLiteDatabase db = mDbHelper.getReadableDatabase();
// 定義要更新的值
ContentValues values = new ContentValues();
values.put(FeedEntry.COLUMN_NAME_TITLE, title);
//根據(jù)過濾調(diào)制定制要更新的列
String selection = FeedEntry.COLUMN_NAME_TITLE + " LIKE ?";
String[] selectionArgs = { "MyTitle" };
int count = db.update(FeedReaderDbHelper.FeedEntry.TABLE_NAME,values, selection,selectionArgs);
當(dāng)然你也可以直接通過SQL語(yǔ)句進(jìn)行相關(guān)操作
SQLiteDatabase db = mDbHelper.getReadableDatabase();
db.getReadableDatabase().execSQL(your sql?); //執(zhí)行增刪改查的SQL語(yǔ)句
GreenDao是什么磷雇?
一言以蔽之,greenDAO就是一個(gè)開源的Android ORM(對(duì)象關(guān)系映射)框架躏救,使SQLite數(shù)據(jù)庫(kù)的開發(fā)變得簡(jiǎn)單唯笙,便捷。而且在性能上greenDao也做了很大的優(yōu)化落剪。該文章主要是介紹如何使用greenDao睁本。(畢竟該發(fā)揮拿來主義的時(shí)候就要發(fā)揮- -)
GreenDao的使用
1.Android Studio中的配置
① app目錄下build.grandle的配置
dependencies依賴:
dependencies {
compile 'org.greenrobot:greendao:3.1.0'
}
在android的根下添加:
android {
greendao{
schemaVersion 1 //控制數(shù)據(jù)庫(kù)版本尿庐,若數(shù)據(jù)庫(kù)結(jié)構(gòu)發(fā)生改變忠怖,更改此處版本號(hào)
targetGenDir 'src/main/java'
}
}
并在最上方添加對(duì)應(yīng)的plugin
apply plugin: 'org.greenrobot.greendao'
② 工程根目錄下目錄下build.grandle的配置
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.2.0'
classpath 'org.greenrobot:greendao-gradle-plugin:3.1.0'
}
}
2.創(chuàng)建一張新的表
1.首先你要先創(chuàng)建一個(gè)新的類。并未類的屬性標(biāo)上對(duì)應(yīng)的注解
@Entity代表你所要?jiǎng)?chuàng)建表的實(shí)體
@Id表示數(shù)據(jù)庫(kù)的主鍵
@Property表示該實(shí)體里對(duì)應(yīng)的屬性(也就是字段)
@Entity
public class Singer {
@Id
private Long id; //主鍵
@Property
private String name;
@Property
private String sex;
@Property
private String country;
}
2.自動(dòng)生成對(duì)應(yīng)的DaoSession和DaoMater文件
之后雙擊 Build 一欄下的 Make Moudle app
編譯完成后你會(huì)發(fā)現(xiàn)你的項(xiàng)目結(jié)構(gòu)發(fā)生了如下變化:
我們回發(fā)現(xiàn)Studio自動(dòng)幫我們生成了DaoMaster抄瑟,DaoSession和Singer的實(shí)體操作類SingerDao凡泣。
3.GreenDao是如何工作的?
(此處只是簡(jiǎn)單的介紹一下GreenDao的工作原理皮假,以及粗略的剖析一下源碼鞋拟,沒興趣的哥(姐)們兒直接可直接忽略此小節(jié))
這里先簡(jiǎn)單的介紹一下這三個(gè)東西。
*** - DaoMaster***
greenDAO的入口點(diǎn)惹资。 DaoMaster保存數(shù)據(jù)庫(kù)對(duì)象(SQLiteDatabase)并管理特定模式的DAO類(而不是對(duì)象)贺纲。它有靜態(tài)方法來創(chuàng)建表或刪除它們。它的內(nèi)部類OpenHelper和DevOpenHelper的底層依舊由SQLiteOpenHelper實(shí)現(xiàn)褪测,在SQLite數(shù)據(jù)庫(kù)中創(chuàng)建數(shù)據(jù)庫(kù)猴誊,具體可以查看DaoMaster的源碼潦刃。以下貼出部分源碼。
/**DaoMaster源碼**********************************/
public class DaoMaster extends AbstractDaoMaster {
//此處為數(shù)據(jù)庫(kù)版本號(hào)
public static final int SCHEMA_VERSION = 1;
//此處也可自己定義一個(gè)類去繼承OpenHelper
public static class DevOpenHelper extends OpenHelper {
public DevOpenHelper(Context context, String name, CursorFactory factory) {
super(context, name, factory);
}
}
public static abstract class OpenHelper extends DatabaseOpenHelper {
public OpenHelper(Context context, String name, CursorFactory factory) {
super(context, name, factory, SCHEMA_VERSION);
}
}
}
/*DatabaseOpenHelper 源碼***********************************/
public abstract class DatabaseOpenHelper extends SQLiteOpenHelper{
public DatabaseOpenHelper(Context context, String name, CursorFactory factory, int version) {
super(context, name, factory, version);
this.context = context;
this.name = name;
this.version = version;
}
}
-DaoSession
管理特定模式的所有可用DAO對(duì)象懈叹,您可以使用其中一個(gè)getter方法獲取它們乖杠。 DaoSession還為實(shí)體提供了一些通用的持久性方法,如插入澄成,加載胧洒,更新,刷新和刪除墨状。以下為DaoSession源碼
public class DaoSession extends AbstractDaoSession {
private final DaoConfig singerDaoConfig;
private final SingerDao singerDao;
public DaoSession(Database db, IdentityScopeType type, Map<Class<? extends AbstractDao<?, ?>>, DaoConfig>
daoConfigMap) {
super(db);
singerDaoConfig = daoConfigMap.get(SingerDao.class).clone();
singerDaoConfig.initIdentityScope(type);
//創(chuàng)建對(duì)應(yīng)的DAO對(duì)象
singerDao = new SingerDao(singerDaoConfig, this);
//將DAO對(duì)象與Singer綁定起來
registerDao(Singer.class, singerDao);
}
/**獲取對(duì)應(yīng)的DAO對(duì)象*/
public SingerDao getSingerDao() {
return singerDao;
}
}
-SingerDao
這個(gè)我想不必過多介紹卫漫,相信接觸過數(shù)據(jù)庫(kù)操作的各位親們都不會(huì)對(duì)它陌生,接下來讓我們簡(jiǎn)單的看以它的部分代碼肾砂。
public class SingerDao extends AbstractDao<Singer, Long> {
public static void createTable(Database db, boolean ifNotExists) {
String constraint = ifNotExists? "IF NOT EXISTS ": "";
db.execSQL("CREATE TABLE " + constraint + "\"SINGER\" (" + //
"\"_id\" INTEGER PRIMARY KEY ," + // 0: id
"\"NAME\" TEXT," + // 1: name
"\"SEX\" TEXT," + // 2: sex
"\"COUNTRY\" TEXT);"); // 3: country
}
}
我們會(huì)發(fā)現(xiàn)在這個(gè)類已經(jīng)幫我們把表創(chuàng)建好了汛兜,關(guān)鍵是不需要你寫一句SQL語(yǔ)句,你要想創(chuàng)建20張表的話只要寫上20個(gè)數(shù)據(jù)模型并標(biāo)上對(duì)應(yīng)的屬性值就可以了通今。這里會(huì)被DaoMaster調(diào)用粥谬。
public class DaoMaster extends AbstractDaoMaster {
public static void createAllTables(Database db, boolean ifNotExists) {
//此處調(diào)用
SingerDao.createTable(db, ifNotExists);
}
}
那他又是如何實(shí)現(xiàn)增刪改查的呢?我們這里已增加數(shù)據(jù)為例,其余同理辫塌,可查看源碼:
從SingerDao的源碼我們可以看到它是繼承自AbstractDao漏策。我們來粗略的看一下內(nèi)部進(jìn)行了怎樣實(shí)現(xiàn)的。
public abstract class AbstractDao<T, K> {
public long insert(T entity) {
return executeInsert(entity, statements.getInsertStatement(), true);
}
}
public class TableStatements {
public DatabaseStatement getInsertStatement() {
if (insertStatement == null) {
//sql語(yǔ)句的拼接
String sql = SqlUtils.createSqlInsert("INSERT INTO ", tablename, allColumns);
DatabaseStatement newInsertStatement = db.compileStatement(sql);
synchronized (this) {
if (insertStatement == null) {
insertStatement = newInsertStatement;
}
}
if (insertStatement != newInsertStatement) {
newInsertStatement.close();
}
}
return insertStatement;
}
}
public class SqlUtils {
public static String createSqlInsert(String insertInto, String tablename, String[] columns) {
StringBuilder builder = new StringBuilder(insertInto);
builder.append('"').append(tablename).append('"').append(" (");
appendColumns(builder, columns);
builder.append(") VALUES (");
appendPlaceholders(builder, columns.length);
builder.append(')');
return builder.toString();
}
}
我們會(huì)發(fā)現(xiàn)臼氨,到最后掺喻,他還是將所有的參數(shù)拼成了一句添加的sql。GreenDao的內(nèi)部都已經(jīng)幫你實(shí)現(xiàn)好了储矩。而我們?cè)谕獠恐恍枰?jiǎn)單的調(diào)用一句即可感耙。
singerDao.insert(new Singer(null, "周杰倫", "男", "中國(guó)"));
4.GreenDao的簡(jiǎn)單操作
①在Application中的配置
public class MyApplication extends Application {
public static final String TAG = MyApplication.class.getSimpleName();
private static Context mContext;
public SQLiteDatabase db;
public DaoSession daoSession;
public DaoMaster.DevOpenHelper helper;
public DaoMaster daoMaster;
@Override
public void onCreate() {
super.onCreate();
mContext = getApplicationContext();
setupDatabase();
}
/**數(shù)據(jù)庫(kù)的配置*/
private void setupDatabase() {
//此處的Helper可自定義
helper = new DaoMaster.DevOpenHelper(this, "green_dao_demo.db", null);
db = helper.getWritableDatabase();
// 注意:該數(shù)據(jù)庫(kù)連接屬于 DaoMaster,所以多個(gè) Session 指的是相同的數(shù)據(jù)庫(kù)連接持隧。
daoMaster = new DaoMaster(db);
daoSession = daoMaster.newSession();
}
public static Context getContext() {
return mContext;
}
public DaoSession getDaoSession() {
return daoSession;
}
public SQLiteDatabase getDb() {
return db;
}
}
②獲取Dao對(duì)象
SingerDao singerDao = ((MyApplication) getActivity()
.getApplicationContext())
.getDaoSession()
.getSingerDao();
-添加數(shù)據(jù)
Singer singer = new Singer(null, name, age, country);
singerDao.insert(singer);
-查詢數(shù)據(jù)
public List<Singer> getSingerList(String country) {
if (!TextUtils.isEmpty(country)) {
List<Singer> singers = getSingerDao()
.queryBuilder()
.where(SingerDao.Properties.Country.eq(country)) //判斷條件
.orderDesc() //排序順序
.build()
.list(); //生成對(duì)應(yīng)的list
return singers;
}
return null即硼;
}
-更新數(shù)據(jù)
//通過主鍵更新數(shù)據(jù)
singerDao.update(new Singer(Loing.valueOf(id),name, sex, country));
//常規(guī)更新
singer.setName(name);
singer.setSex(sex);
singer.setCountry(country);
singerDao.update(singer);
-刪除數(shù)據(jù)
//通過主鍵刪除
singerDao.deleteByKey(Long.valueOf(singer.getId()));
//常規(guī)刪除
singerDao.delete(singer);
-批量操作
singerDao.insertInTx(singers); // 批量添加
singerDao.updateInTx(singers); // 批量更新
singerDao.deleteInTx(singers); //批量刪除
項(xiàng)目示例地址
https://github.com/HandGrab/GreenDaoDemo
參考:
GreenDao官網(wǎng):http://greenrobot.org/greendao/
GreenDao部分源碼