茂名網(wǎng)站建設(shè)培訓(xùn)行業(yè)關(guān)鍵詞分類
??一
前言:以前沒用框架寫Andorid的Sqlite的時(shí)候就是用SQLiteDatabase ,SQLiteOpenHelper ,SQL語句等一些東西,特別在寫SQL語句來進(jìn)行
數(shù)據(jù)庫(kù)操作的時(shí)候是一件很繁瑣的事情,有時(shí)候沒有錯(cuò)誤提示的,很難找到錯(cuò)誤的地方,即費(fèi)力又花時(shí)間。
? ? ? ? ? ? ? ? 現(xiàn)在使用greenDao就可以避免那些繁瑣的SQL文了,極大的簡(jiǎn)化了對(duì)Sqlite的操作。
? ? greenDao官方網(wǎng)址是:http://greendao-orm.com/
? ? greenDao官方demo下載地址:GitHub - greenrobot/greenDAO: greenDAO is a light & fast ORM solution for Android that maps objects to SQLite databases.
官方Demo里共有六個(gè)工程目錄,分別為:
(1).DaoCore:庫(kù)目錄,即jar文件greendao-1.3.0-beta-1.jar的代碼;
(2).DaoExample:android范例工程;
(3).DaoExampleGenerator:DaoExample工程的DAO類構(gòu)造器,java工程;
(4).DaoGenerator:DAO類構(gòu)造器,java工程;
(5).DaoTest、PerformanceTestOrmLite:其他測(cè)試相關(guān)的工程
?二
? ??對(duì)greendDao進(jìn)行一個(gè)簡(jiǎn)單的介紹:
? ? ? ? ?greenDao是一個(gè)用于幫助Android開發(fā)者操作SQLite的一個(gè)開源項(xiàng)目,SQLite是一個(gè)極其重要的嵌入關(guān)系型數(shù)據(jù)庫(kù),然而開發(fā)這個(gè)需要完成一些比較傳統(tǒng)的工作,寫sql和解析查詢結(jié)果是一件很繁瑣的任務(wù)。
greenDao將會(huì)為你工作:他講java的Object和數(shù)據(jù)庫(kù)的表進(jìn)行了映射(常被稱為ORM),這個(gè)方法可以讓你用一些簡(jiǎn)單的面向?qū)ο驛PI來完成存儲(chǔ),更新,刪除和查詢等,節(jié)約時(shí)間讓你專注于實(shí)際比較重要的問題上
? ??greenDao主要的設(shè)計(jì)目的:
- 最高性能(可能是最快的ORM為Andorid)
- 簡(jiǎn)單易用的APIs
- 高度優(yōu)化Andorid
- 最小的內(nèi)存占用
- 小的librry size,可以專注于實(shí)際問題
三
官方demo的介紹:
(一) DAO類構(gòu)造(實(shí)體 + 數(shù)據(jù)庫(kù)的一些初始化的操作代碼)
首先要新建一個(gè)java工程(?這個(gè)工程就是以后用來生成數(shù)據(jù)庫(kù)表和對(duì)應(yīng)實(shí)體的工程了)來生成DAO類文件,這個(gè)工程需要導(dǎo)入greendao-generator-1.3.1和freemarker-2.3.22這兩個(gè)jar包要下對(duì),版本號(hào)不一定是要
我這個(gè)的。
01.package de.greenrobot.daogenerator.gentest;
02.import de.greenrobot.daogenerator.DaoGenerator;
03.import de.greenrobot.daogenerator.Entity;
04.import de.greenrobot.daogenerator.Property;
05.import de.greenrobot.daogenerator.Schema;
06.import de.greenrobot.daogenerator.ToMany;
07./**
08.* Generates entities and DAOs for the example project DaoExample.
09.*
10.* Run it as a Java application (not Android).
11.*
12.* @author Markus
13.*/
14.public class ExampleDaoGenerator
15.{
16.
17.public static void main(String[] args) throws Exception
18.{
19.Schema schema = new Schema(3, "de.greenrobot.daoexample");
20.
21.addNote(schema);
22.addCustomerOrder(schema);
23.
24.new DaoGenerator().generateAll(schema, "../DaoExample/src-gen");
25.}
26.
27.private static void addNote(Schema schema)
28.{
29.Entity note = schema.addEntity("Note");
30.note.addIdProperty();
31.note.addStringProperty("text").notNull();
32.note.addStringProperty("comment");
33.note.addDateProperty("date");
34.}
35.
36.private static void addCustomerOrder(Schema schema)
37.{
38.Entity customer = schema.addEntity("Customer");
39.customer.addIdProperty();
40.customer.addStringProperty("name").notNull();
41.
42.Entity order = schema.addEntity("Order");
43.order.setTableName("ORDERS");
44.order.addIdProperty();
45.Property orderDate = order.addDateProperty("date").getProperty();
46.Property customerId = order.addLongProperty("customerId").notNull().getProperty();
47.order.addToOne(customer, customerId);
48.
49.ToMany customerToOrders = customer.addToMany(order, customerId);
50.customerToOrders.setName("orders");
51.customerToOrders.orderAsc(orderDate);
52.}
53.
54.}
?
對(duì)上面的代碼做一些解釋:
Schema schema =?
new
?Schema(
3
,?
"de.greenrobot.daoexample"
); ? 3 ---- 自己寫的數(shù)據(jù)庫(kù)版本號(hào) ? ??de.greenrobot.daoexample --- 包的所在地址 ?這些都可以不改的
? addNote(schema) 方法執(zhí)行后 就在 Android工程DaoExample中的src-gen文件中創(chuàng)建了一個(gè)Note實(shí)體,其中屬性有text , comment , date 和NoteDao 其實(shí)就是對(duì)數(shù)據(jù)庫(kù)的一些操作的
??addCustomerOrder(schema)作用和addNote(schema)類似,只不過是多了表之間的關(guān)系(一對(duì)一 和 一對(duì)多)
方法(建表 ,查詢等)和sql文都在這里面。
new DaoGenerator().generateAll(schema, "../DaoExample/src-gen"); 指定生成的路徑其中src-gen這個(gè)目錄名需要在運(yùn)行前手動(dòng)創(chuàng)建,否則會(huì)報(bào)錯(cuò)。運(yùn)行后出現(xiàn)以下的提示說明DAO文件自動(dòng)生成成功了,刷新一下DaoExample項(xiàng)目即可看到運(yùn)行后可以看到,DaoExample項(xiàng)目src-gen下面自動(dòng)生成了8個(gè)文件,3個(gè)實(shí)體對(duì)象,3個(gè)dao,1個(gè)DaoMaster,1個(gè)DaoSession.
?DaoExample
基于greenDao的android工程,他需要導(dǎo)入greendao-1.3.0-beta-1.jar
以后想在創(chuàng)建表和實(shí)體,就可以直接在這個(gè)工程里面添加方法就行了,以前的方法不能修改***
Note就是一個(gè)實(shí)體,代碼就不貼出來了
看看NoteDao的代碼:
public class NoteDao extends AbstractDao<Note, Long> {public static final String TABLENAME = "NOTE";public static class Properties {public final static Property Id = new Property(0, Long.class, "id", true, "_id");public final static Property Text = new Property(1, String.class, "text", false, "TEXT");public final static Property Comment = new Property(2, String.class, "comment", false, "COMMENT");public final static Property Date = new Property(3, java.util.Date.class, "date", false, "DATE");};public NoteDao(DaoConfig config) {super(config);}public NoteDao(DaoConfig config, DaoSession daoSession) {super(config, daoSession);}/** Creates the underlying database table. */public static void createTable(SQLiteDatabase db, boolean ifNotExists) {String constraint = ifNotExists? "IF NOT EXISTS ": "";db.execSQL("CREATE TABLE " + constraint + "'NOTE' (" + //"'_id' INTEGER PRIMARY KEY ," + // 0: id"'TEXT' TEXT NOT NULL ," + // 1: text"'COMMENT' TEXT," + // 2: comment"'DATE' INTEGER);"); // 3: date}/** Drops the underlying database table. */public static void dropTable(SQLiteDatabase db, boolean ifExists) {String sql = "DROP TABLE " + (ifExists ? "IF EXISTS " : "") + "'NOTE'";db.execSQL(sql);}/** @inheritdoc */@Overrideprotected void bindValues(SQLiteStatement stmt, Note entity) {stmt.clearBindings();Long id = entity.getId();if (id != null) {stmt.bindLong(1, id);}stmt.bindString(2, entity.getText());String comment = entity.getComment();if (comment != null) {stmt.bindString(3, comment);}java.util.Date date = entity.getDate();if (date != null) {stmt.bindLong(4, date.getTime());}}/** @inheritdoc */@Overridepublic Long readKey(Cursor cursor, int offset) {return cursor.isNull(offset + 0) ? null : cursor.getLong(offset + 0);} /** @inheritdoc */@Overridepublic Note readEntity(Cursor cursor, int offset) {Note entity = new Note( //cursor.isNull(offset + 0) ? null : cursor.getLong(offset + 0), // idcursor.getString(offset + 1), // textcursor.isNull(offset + 2) ? null : cursor.getString(offset + 2), // commentcursor.isNull(offset + 3) ? null : new java.util.Date(cursor.getLong(offset + 3)) // date);return entity;}/** @inheritdoc */@Overridepublic void readEntity(Cursor cursor, Note entity, int offset) {entity.setId(cursor.isNull(offset + 0) ? null : cursor.getLong(offset + 0));entity.setText(cursor.getString(offset + 1));entity.setComment(cursor.isNull(offset + 2) ? null : cursor.getString(offset + 2));entity.setDate(cursor.isNull(offset + 3) ? null : new java.util.Date(cursor.getLong(offset + 3)));}/** @inheritdoc */@Overrideprotected Long updateKeyAfterInsert(Note entity, long rowId) {entity.setId(rowId);return rowId;}/** @inheritdoc */@Overridepublic Long getKey(Note entity) {if(entity != null) {return entity.getId();} else {return null;}}/** @inheritdoc */@Override protected boolean isEntityUpdateable() {return true;}}
從代碼中可以看到,就和以前直接操作sqlite是想類似的。
四
一些常用方法進(jìn)行介紹( 摘至網(wǎng)絡(luò)):
1.創(chuàng)建一個(gè)實(shí)體類
Entity note = schema.addEntity("Note");
默認(rèn)表名就是類名,也可以自定義表名
dao.setTableName("NoteList");
greenDAO會(huì)自動(dòng)根據(jù)實(shí)體類屬性創(chuàng)建表字段,并賦予默認(rèn)值。例如在數(shù)據(jù)庫(kù)方面的表名和列名都來源于實(shí)體類名和屬性名。默認(rèn)的數(shù)據(jù)庫(kù)名稱是大寫 使用下劃線分隔單詞,而不是在Java中使用的駝峰式大小寫風(fēng)格。例如,一個(gè)名為“CREATIONDATE”屬性將成為一個(gè)數(shù)據(jù)庫(kù)列 “CREATION_DATE”。
設(shè)置一個(gè)自增長(zhǎng)ID列為主鍵:
dao.addIdProperty().primaryKey().autoincrement();
設(shè)置其他各種類型的屬性:
dao.addIntProperty("cityId");dao.addStringProperty("infoType").notNull();//非null字段dao.addDoubleProperty("Id");
在生成的實(shí)體類中,int類型為自動(dòng)轉(zhuǎn)為long類型。
如果在編譯過程中出現(xiàn)以下錯(cuò)誤,那么有可能是主鍵的類型錯(cuò)誤所致:
1.
java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
在使用greenDAO時(shí),一個(gè)實(shí)體類只能對(duì)應(yīng)一個(gè)表,目前沒法做到一個(gè)表對(duì)應(yīng)多個(gè)實(shí)體類,或者多個(gè)表共用一種對(duì)象類型。后續(xù)的升級(jí)也不會(huì)針對(duì)這一點(diǎn)進(jìn)行擴(kuò)展。
(二)表的增刪改查
增刪改查相當(dāng)方便,完全的面向?qū)ο?#xff0c;不需要涉及到任何的sql語言。
1.查詢
范例1:查詢某個(gè)表是否包含某個(gè)id:
public boolean isSaved(int ID){QueryBuilder<SaveList> qb = saveListDao.queryBuilder();qb.where(Properties.Id.eq(ID));qb.buildCount().count();return qb.buildCount().count() > 0 ? true : false;}
范例2:獲取整個(gè)表的數(shù)據(jù)集合,一句代碼就搞定!
public List<PhotoGalleryDB> getPhotoGallery(){return photoGalleryDao.loadAll();// 獲取圖片相冊(cè)}
范例3:通過一個(gè)字段值查找對(duì)應(yīng)的另一個(gè)字段值(為簡(jiǎn)便直接使用下面方法,也許有更簡(jiǎn)單的方法,尚未嘗試)
01.
/** 通過圖片id查找其目錄id */public int getTypeId(int picId){QueryBuilder<PhotoGalleryDB> qb = photoGalleryDao.queryBuilder();qb.where(Properties.Id.eq(picId));if (qb.list().size() > 0){return qb.list().get(0).getTypeId();}else{return -1;}}
范例4:查找所有第一姓名是“Joe”并且以lastname排序。
List joes = userDao.queryBuilder()where(Properties.FirstName.eq("Joe"))orderAsc(Properties.LastName)list();
范例5:多重條件查詢
(1)獲取id為cityId并且infotype為HBContant.CITYINFO_SL的數(shù)據(jù)集合:????????????????
public List<CityInfoDB> getSupportingList(int cityId){QueryBuilder<CityInfoDB> qb = cityInfoDao.queryBuilder();qb.where(qb.and(Properties.CityId.eq(cityId),Properties.InfoType.eq(HBContant.CITYINFO_SL)));qb.orderAsc(Properties.Id);// 排序依據(jù)return qb.list();}
(2)獲取firstname為“Joe”并且出生于1970年10月以后的所有user集合:
QueryBuilder qb = userDao.queryBuilder();qb.where(Properties.FirstName.eq("Joe"),qb.or(Properties.YearOfBirth.gt(1970),qb.and(Properties.YearOfBirth.eq(1970), Properties.MonthOfBirth.ge(10))));List youngJoes = qb.list();
范例6:獲取某列對(duì)象
picJsonDao.loadByRowId(picId);
2.增添/插入、修改
插入數(shù)據(jù)更加簡(jiǎn)單,也是只要一句代碼便能搞定!
public void addToPhotoTable(Photo p){photoDao.insert(p);}
插入時(shí)需要new一個(gè)新的對(duì)象,范例如下:
DevOpenHelper helper = new DaoMaster.DevOpenHelper(this, "notes-db", null);db = helper.getWritableDatabase();daoMaster = new DaoMaster(db);daoSession = daoMaster.newSession();noteDao = daoSession.getNoteDao();Note note = new Note(null, noteText, comment, new Date());noteDao.insert(note);
修改更新:
1.
photoDao.insertOrReplace(photo);
2.
photoDao.insertInTx(photo);
這里可定有疑問的:例如update table SET age =20 WHERE name = "張三" 這樣一個(gè)語句在greenDao中怎么執(zhí)行的,
始終記住一句話,greenDao 對(duì)對(duì)象的增,刪,改,查 就是對(duì)數(shù)據(jù)庫(kù)的增,刪,改,查
String updateName = content.getText().toString().trim();QueryBuilder qb2 = studentDao.queryBuilder();qb2.where(Properties.Name.eq("張三"));List<Student> update = qb2.list();String newName = content.getText().toString().trim();for (Student student222 : update) {student222.setAge(20);studentDao.insertOrReplaceInTx(student222);}
被查詢出的對(duì)象被修改后,在替換原來自己的對(duì)象就可以了
3.刪除:
(1)清空表格數(shù)據(jù)
/** 清空相冊(cè)圖片列表的數(shù)據(jù) */public void clearPhoto(){photoDao.deleteAll();}
(2)刪除某個(gè)對(duì)象
public void deleteCityInfo(int cityId){QueryBuilder<DBCityInfo> qb = cityInfoDao.queryBuilder();DeleteQuery<DBCityInfo> bd = qb.where(Properties.CityId.eq(cityId)).buildDelete();bd.executeDeleteWithoutDetachingEntities();}
參考:https://github.com/greenrobot/greenDAO/issues/34
http://my.oschina.net/cheneywangc/blog/196354
由上可見,使用greenDAO進(jìn)行數(shù)據(jù)庫(kù)的增刪改查時(shí)及其方便,而且性能極佳。