編輯:關於Android編程
一、簡介
1.Android ORM介紹
?在平時的開發過程中,大家一定會或多或少地接觸到 SQLite。然而在使用它時,我們往往需要做許多額外的工作,像編寫 SQL 語句與解析查詢結果等。所以,適用於 Android 的ORM 框架也就孕育而生了,現在市面上主流的框架有 OrmLite、SugarORM、Active Android、Realm 與 GreenDAO。下面先介紹下當前流行的5種ORM數據庫框架:
1)OrmLite
?OrmLite不是Android 平台專用的ORM框架,它是Java ORM。支持JDBC連接,Spring以及Android平台。語法中廣泛使用了注解(Annotation)。
2)SugarORM
?SugarORM是Android 平台專用ORM。提供簡單易學的APIs。可以很容易的處理1對1和1對多的關系型數據,並通過3個函數save(), delete() 和 find() (或者 findById()) 來簡化CRUD基本操作。
3)Active Android
?Active Record(活動目錄)是Yii、Rails等框架中對ORM實現的典型命名方式。Active Android 幫助你以面向對象的方式來操作SQLite。
4)Realm
?Realm 是一個將可以使用的Android ORM,基於C++編寫,直接運行在你的設備硬件上(不需要被解釋),因此運行很快。它同時是開源跨平台的,iOS的代碼可以在GitHub找到。
5)GreenDAO
?GreenDAO 是一個將對象映射到 SQLite 數據庫中的輕量且快速的 ORM 解決方案。
2.GreenDao介紹及優點
介紹:
?GreenDAO就是實現Java對象和SQLite Datebase的一個媒介人,簡化了SQLite的操作,而且他的數據庫操作效率非常高。可以幫助Android開發者快速將Java對象映射到SQLite數據庫的表單中的ORM解決方案,通過使用一個簡單的面向對象API,開發者可以對Java對象進行存儲、更新、刪除和查詢。
官網網址:http://greenrobot.org/greendao/features//
優點:
1)最大性能(最快的Android ORM),GreenDAO 性能遠遠高於同類的 ORMLite(可見下圖);
2)簡易API,通過Java工程生成的類中方法全都自動寫好了,可以直接調用;
3)高度優化,GreenDAO 支持 protocol buffer(protobuf) 協議數據的直接存儲,如果你通過 protobuf 協議與服務器交互,將不需要任何的映射;與ORMLite等使用注解方式的ORM框架不同,greenDAO使用Code generation的方式,這也是其性能能大幅提升的原因。
4)最小內存消耗。
二、配置
配置Java工程
1)在Android Studio中選擇File -> New -> New Module -> Java Library建立GreenDAO Generate工程;並且在該工程build.gradlew裡添加以下依賴:
compile 'org.greenrobot:greendao-generator:2.2.0'
2)在新建的Java工程中新建一個Java類,該Java類用於生成項目所需的Bean、DAO等文件,以下是該類需要寫的代碼:
public class ExampleDaoGenerator {
public static void main(String[] args) throws Exception {
// 創建了一個用於添加實體(Bean)的模式(Schema)對象。
// 兩個參數分別代表:數據庫版本號與自動生成代碼的包路徑。
Schema schema = new Schema(1, "com.example.jianglei.greendaotestdemo.db.bean");
// 也可以分別指定生成的 Bean 與 DAO 類所在的目錄
schema.setDefaultJavaPackageDao("com.example.jianglei.greendaotestdemo.db.dao");
//通過次Schema對象添加的所有實體都不會覆蓋自定義的代碼
// schema.enableKeepSectionsByDefault();
// 創建Schema對象後,就可以使用它添加實體(Bean)了。
addUser(schema);
// 最後使用 DAOGenerator 類的 generateAll()方法自動生成代碼,根據自己的情況更改輸出目錄
new DaoGenerator().generateAll(schema,
"D:\\WorkSpace_01\\GreenDaoTestDemo\\app\\src\\main\\java");
}
/**
* @param schema
*/
private static void addUser(Schema schema) {
// 一個實體(類)就關聯到數據庫中的一張表,此處表名為「User」
Entity note = schema.addEntity("User");
// 也可以重新給表命名
// note.setTableName("NODE");
//單獨讓某個實體不覆蓋自定義的代碼
// note.setHasKeepSections(true);
// greenDAO 會自動根據實體類的屬性值來創建表字段,並賦予默認值
note.addIdProperty().notNull().primaryKey();
note.addStringProperty("name").notNull();
// 與在 Java 中使用駝峰命名法不同,默認數據庫中的命名是使用大寫和下劃線來分割單詞的。
note.addIntProperty("age").notNull();
}
}
<喎?/kf/ware/vc/" target="_blank" class="keylink">vcD4NCjxwPjxjb2RlIGNsYXNzPQ=="hljs bash">完成該類的編寫後,點擊Run來執行這個類可以看到:
三、工作原理
四個核心類的功能體系及工作原理如下圖所示:
???
DaoMaster:
?一看名字就知道它是Dao中的最大的官了。它保存了sqlitedatebase對象以及操作DAO classes(注意:不是對象)。其提供了一些創建和刪除table的靜態方法,其內部類OpenHelper和DevOpenHelper實現了SQLiteOpenHelper並創建數據庫的框架。
public class DaoMaster extends AbstractDaoMaster {
public static final int SCHEMA_VERSION = 1;
/** Creates underlying database table using DAOs. */
public static void createAllTables(SQLiteDatabase db, boolean ifNotExists) {
UserDao.createTable(db, ifNotExists);
}
/** Drops underlying database table using DAOs. */
public static void dropAllTables(SQLiteDatabase db, boolean ifExists) {
UserDao.dropTable(db, ifExists);
}
public static abstract class OpenHelper extends SQLiteOpenHelper {
public OpenHelper(Context context, String name, CursorFactory factory) {
super(context, name, factory, SCHEMA_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
Log.i("greenDAO", "Creating tables for schema version " + SCHEMA_VERSION);
createAllTables(db, false);
}
}
/** WARNING: Drops all table on Upgrade! Use only during development. */
public static class DevOpenHelper extends OpenHelper {
public DevOpenHelper(Context context, String name, CursorFactory factory) {
super(context, name, factory);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
Log.i("greenDAO", "Upgrading schema from version " + oldVersion + " to " + newVersion + " by dropping all tables");
dropAllTables(db, true);
onCreate(db);
}
}
public DaoMaster(SQLiteDatabase db) {
super(db, SCHEMA_VERSION);
registerDaoClass(UserDao.class);
}
public DaoSession newSession() {
return new DaoSession(db, IdentityScopeType.Session, daoConfigMap);
}
public DaoSession newSession(IdentityScopeType type) {
return new DaoSession(db, type, daoConfigMap);
}
}
?從DaoMaster中我們可以發現,DaoMaster除了具有創建表和刪除表的兩個功能外,還有兩個內部類,分別為OpenHelper和DevOpenHelper,而DevOpenHelper繼承自OpenHelper,而OpenHelper繼承自SQLiteOpenHelper,而重寫的onCreate()方法中調用了createAllTables(db,false);方法來創建數據表,而createAllTables()方法中是通過調用UserDao靜態方法來創建表的UserDao.createTable(db, ifNotExists);我們點進這個方法中去看個究竟:
/** Creates the underlying database table. */
public static void createTable(SQLiteDatabase db, boolean ifNotExists) {
String constraint = ifNotExists? "IF NOT EXISTS ": "";
db.execSQL("CREATE TABLE " + constraint + "\"USER\" (" + //
"\"_id\" INTEGER PRIMARY KEY NOT NULL ," + // 0: id
"\"NAME\" TEXT NOT NULL ," + // 1: name
"\"AGE\" INTEGER NOT NULL );"); // 2: age
}
?發現它內部就是通過sql語句來創建表的,只不過GreenDAO幫我們封裝好了,而且你會發現刪除表其實也一樣:
/** Drops the underlying database table. */
public static void dropTable(SQLiteDatabase db, boolean ifExists) {
String sql = "DROP TABLE " + (ifExists ? "IF EXISTS " : "") + "\"USER\"";
db.execSQL(sql);
}
?在DevOpenHelper類中實現了onUpgrade()方法,就是更新數據庫的方法,它在更新數據表的時候會把以前的數據表刪除後再重新創建,所以這個你必須注意,當我們在利用GreenDAO更新數據表的時候,如果你想以前表中的數據保存下來的話,我們必須自己封裝一個方法。接下來就是newSession()方法了,這個當然就是得到DaoSession實例了,關於DaoSession實例,GreenDAO官方建議不要重新創建新的實例,保持一個單例的引用即可。
?接下來就是看DaoMaster的父類AbstractDaoMaster的源碼了,它的源碼如下:
public abstract class AbstractDaoMaster {
protected final SQLiteDatabase db;
protected final int schemaVersion;
protected final Map>, DaoConfig> daoConfigMap;
public AbstractDaoMaster(SQLiteDatabase db, int schemaVersion) {
this.db = db;
this.schemaVersion = schemaVersion;
daoConfigMap = new HashMap>, DaoConfig>();
}
protected void registerDaoClass(Class> daoClass) {
DaoConfig daoConfig = new DaoConfig(db, daoClass);
daoConfigMap.put(daoClass, daoConfig);
}
public int getSchemaVersion() {
return schemaVersion;
}
/** Gets the SQLiteDatabase for custom database access. Not needed for greenDAO entities. */
public SQLiteDatabase getDatabase() {
return db;
}
public abstract AbstractDaoSession newSession();
public abstract AbstractDaoSession newSession(IdentityScopeType type);
}
?看這個類的代碼,最重要的就是這一行了:
protected final Map>, DaoConfig> daoConfigMap;
?這裡定義了一個Map集合,Key是繼承自AbstractDao類的字節碼對象,Value則為DaoConfig對象,而往這個Map集合中put數據是通過這個方法registerDaoClass(),代碼在上面可以看到。Map的功能就是為每一個EntityDao字節碼對象建立與之對應的db數據庫的映射關系,從而管理所有的EntityDao類。
再回到DaoMaster,可以看到DaoMaster類的構造方法中調用了registerDaoClass(),把EntityDao類和相應的數據庫db建立關聯。
DaoSession:
?操作具體的DAO對象(注意:是對象)。
?從上面可知DaoSession對象是通過master.newSession();創建的。我們看看DaoSession源碼,發現它也有一個抽象的父類AbstractDaoSession,我們來看看DaoSession的源碼:
public class DaoSession extends AbstractDaoSession {
private final DaoConfig userDaoConfig;
private final UserDao userDao;
public DaoSession(SQLiteDatabase db, IdentityScopeType type, Map>, DaoConfig>
daoConfigMap) {
super(db);
userDaoConfig = daoConfigMap.get(UserDao.class).clone();
userDaoConfig.initIdentityScope(type);
userDao = new UserDao(userDaoConfig, this);
registerDao(User.class, userDao);
}
public void clear() {
userDaoConfig.getIdentityScope().clear();
}
public UserDao getUserDao() {
return userDao;
}
}
?最主要的一個方法就是通過getUserDao()來得到UserDao實例,而創建一個UserDao對象正是在DaoSession的構造方法中:
userDao = new UserDao(userDaoConfig, this);
?這個正是從在DaoMaster創建的Map集合中取出key為UserDao.class的DaoConfig對象,剛剛就說了Map集合中保存了UserDao類對應的數據庫db的關系映射,而這個DaoConfig對象正是管理了對應的db對象。然後把這個DaoConfig傳給UserDao(userDaoConfig, this),所以這就說明了我們使用UserDao對象來進行數據庫上的CRUD操作而對應的數據庫也會變化的原因,這個過程實際上就是在間接操作數據庫。
?下面來就是看看它的父類AbstractDaoSession:
public class AbstractDaoSession {
private final SQLiteDatabase db;
private final Map, AbstractDao> entityToDao;
public AbstractDaoSession(SQLiteDatabase db) {
this.db = db;
this.entityToDao = new HashMap, AbstractDao>();
}
protected void registerDao(Class entityClass, AbstractDao dao) {
entityToDao.put(entityClass, dao);
}
/** Convenient call for {@link AbstractDao#insert(Object)}. */
public long insert(T entity) {
@SuppressWarnings("unchecked")
AbstractDao dao = (AbstractDao) getDao(entity.getClass());
return dao.insert(entity);
}
/** Convenient call for {@link AbstractDao#insertOrReplace(Object)}. */
public long insertOrReplace(T entity) {
@SuppressWarnings("unchecked")
AbstractDao dao = (AbstractDao) getDao(entity.getClass());
return dao.insertOrReplace(entity);
}
/** Convenient call for {@link AbstractDao#refresh(Object)}. */
public void refresh(T entity) {
@SuppressWarnings("unchecked")
AbstractDao dao = (AbstractDao) getDao(entity.getClass());
dao.refresh(entity);
}
/** Convenient call for {@link AbstractDao#update(Object)}. */
public void update(T entity) {
@SuppressWarnings("unchecked")
AbstractDao dao = (AbstractDao) getDao(entity.getClass());
dao.update(entity);
}
/** Convenient call for {@link AbstractDao#delete(Object)}. */
public void delete(T entity) {
@SuppressWarnings("unchecked")
AbstractDao dao = (AbstractDao) getDao(entity.getClass());
dao.delete(entity);
}
/** Convenient call for {@link AbstractDao#deleteAll()}. */
public void deleteAll(Class entityClass) {
@SuppressWarnings("unchecked")
AbstractDao dao = (AbstractDao) getDao(entityClass);
dao.deleteAll();
}
/** Convenient call for {@link AbstractDao#load(Object)}. */
public T load(Class entityClass, K key) {
@SuppressWarnings("unchecked")
AbstractDao dao = (AbstractDao) getDao(entityClass);
return dao.load(key);
}
/** Convenient call for {@link AbstractDao#loadAll()}. */
public List loadAll(Class entityClass) {
@SuppressWarnings("unchecked")
AbstractDao dao = (AbstractDao) getDao(entityClass);
return dao.loadAll();
}
/** Convenient call for {@link AbstractDao#queryRaw(String, String...)}. */
public List queryRaw(Class entityClass, String where, String... selectionArgs) {
@SuppressWarnings("unchecked")
AbstractDao dao = (AbstractDao) getDao(entityClass);
return dao.queryRaw(where, selectionArgs);
}
/** Convenient call for {@link AbstractDao#queryBuilder()}. */
public QueryBuilder queryBuilder(Class entityClass) {
@SuppressWarnings("unchecked")
AbstractDao dao = (AbstractDao) getDao(entityClass);
return dao.queryBuilder();
}
public AbstractDao getDao(Class entityClass) {
AbstractDao dao = entityToDao.get(entityClass);
if (dao == null) {
throw new DaoException("No DAO registered for " + entityClass);
}
return dao;
}
/**
* Run the given Runnable inside a database transaction. If you except a result, consider callInTx.
*/
public void runInTx(Runnable runnable) {
db.beginTransaction();
try {
runnable.run();
db.setTransactionSuccessful();
} finally {
db.endTransaction();
}
}
/**
* Calls the given Callable inside a database transaction and returns the result of the Callable. If you don't
* except a result, consider runInTx.
*/
public V callInTx(Callable callable) throws Exception {
db.beginTransaction();
try {
V result = callable.call();
db.setTransactionSuccessful();
return result;
} finally {
db.endTransaction();
}
}
/**
* Like {@link #callInTx(Callable)} but does not require Exception handling (rethrows an Exception as a runtime
* DaoException).
*/
public V callInTxNoException(Callable callable) {
db.beginTransaction();
try {
V result;
try {
result = callable.call();
} catch (Exception e) {
throw new DaoException("Callable failed", e);
}
db.setTransactionSuccessful();
return result;
} finally {
db.endTransaction();
}
}
/** Gets the SQLiteDatabase for custom database access. Not needed for greenDAO entities. */
public SQLiteDatabase getDatabase() {
return db;
}
/** Allows to inspect the meta model using DAOs (e.g. querying table names or properties). */
public Collection> getAllDaos() {
return Collections.unmodifiableCollection(entityToDao.values());
}
/**
* Creates a new {@link AsyncSession} to issue asynchronous entity operations. See {@link AsyncSession} for details.
*/
public AsyncSession startAsyncSession() {
return new AsyncSession(this);
}
}
?可以看到它的父類中,大部分方法都是進行CRUD操作的,而事實上我們在進行CRUD操作都是通過UserDao對象來進行的,實際上這兩種做法沒有區別,因為它內部本身就是通過dao對象來進行CRUD操作的,大家看看這些方法的返回值就知道了。
?在DaoSession和UserDao調用CRUD操作中,查詢操作比較特殊,原因是GreenDao在查詢這塊加了緩存 ,GreenDao在查詢時使用了弱引用WeakReference,對已經查詢過的數據,先查詢這個引用而不是查詢數據庫(前提是沒有GC),速度更快。
?這個緩存的代碼是在AbstractQueryData類中,如下:
Q forCurrentThread() {
int threadId = Process.myTid();
if (threadId == 0) {
// Workaround for Robolectric, always returns 0
long id = Thread.currentThread().getId();
if (id < 0 || id > Integer.MAX_VALUE) {
throw new RuntimeException("Cannot handle thread ID: " + id);
}
threadId = (int) id;
}
synchronized (queriesForThreads) {
WeakReference queryRef = queriesForThreads.get(threadId);
Q query = queryRef != null ? queryRef.get() : null;
if (query == null) {
gc();
query = createQuery();
queriesForThreads.put(threadId, new WeakReference(query));
} else {
System.arraycopy(initialValues, 0, query.parameters, 0, initialValues.length);
}
return query;
}
}
UserDao:
?實際生成的UserDao類,通常對應具體的java類,其有更多的權限和方法來操作數據庫元素。
先看看UserDao類的源碼:
public class UserDao extends AbstractDao {
public static final String TABLENAME = "USER";
/**
* Properties of entity User.
* Can be used for QueryBuilder and for referencing column names.
*/
public static class Properties {
public final static Property Id = new Property(0, Long.class, "id", true, "_id");
public final static Property Name = new Property(1, String.class, "name", false, "NAME");
public final static Property Age = new Property(2, int.class, "age", false, "AGE");
}
public UserDao(DaoConfig config) {
super(config);
}
public UserDao(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 + "\"USER\" (" + //
"\"_id\" INTEGER PRIMARY KEY ," + // 0: id
"\"NAME\" TEXT NOT NULL ," + // 1: name
"\"AGE\" INTEGER NOT NULL );"); // 2: age
}
/** Drops the underlying database table. */
public static void dropTable(SQLiteDatabase db, boolean ifExists) {
String sql = "DROP TABLE " + (ifExists ? "IF EXISTS " : "") + "\"USER\"";
db.execSQL(sql);
}
/** @inheritdoc */
@Override
protected void bindValues(SQLiteStatement stmt, User entity) {
stmt.clearBindings();
Long id = entity.getId();
if (id != null) {
stmt.bindLong(1, id);
}
stmt.bindString(2, entity.getName());
stmt.bindLong(3, entity.getAge());
}
/** @inheritdoc */
@Override
public Long readKey(Cursor cursor, int offset) {
return cursor.isNull(offset + 0) ? null : cursor.getLong(offset + 0);
}
/** @inheritdoc */
@Override
public User readEntity(Cursor cursor, int offset) {
User entity = new User( //
cursor.isNull(offset + 0) ? null : cursor.getLong(offset + 0), // id
cursor.getString(offset + 1), // name
cursor.getInt(offset + 2) // age
);
return entity;
}
/** @inheritdoc */
@Override
public void readEntity(Cursor cursor, User entity, int offset) {
entity.setId(cursor.isNull(offset + 0) ? null : cursor.getLong(offset + 0));
entity.setName(cursor.getString(offset + 1));
entity.setAge(cursor.getInt(offset + 2));
}
/** @inheritdoc */
@Override
protected Long updateKeyAfterInsert(User entity, long rowId) {
entity.setId(rowId);
return rowId;
}
/** @inheritdoc */
@Override
public Long getKey(User entity) {
if(entity != null) {
return entity.getId();
} else {
return null;
}
}
/** @inheritdoc */
@Override
protected boolean isEntityUpdateable() {
return true;
}
}
?除了之前講的createTable和dropTable方法以外,比較重要的就是bindValues()這個方法,它是用來綁定實體的屬性名和表中的字段名的;Property是用來得到這個屬性對應表中的列名、是否為主鍵等值,這個為查詢、更新等提供了條件。UserDao的父類AbstractDao源碼中主要是一些CRUD方法和其它的一些方法,這裡就不再多作介紹了。
User:
?對於實體類,這沒什麼可講的,就是一個Bean,一個實體類對應一張表,實體類裡面有對應各個字段的getter和setter方法。通常代表了一個數據庫row的標准java properties。
四、項目使用
?前面很大篇幅講了些工作原理的分析,下面就到了項目使用階段,相信只要理解上面的工作原理,大家使用起來就非常順手了,而且GreenDao封裝了很多簡易的CRDU方法。
基本使用
?我們首先來看看使用GreenDAO的基本步驟:
// 生成數據庫文件,名為user-db
DaoMaster.DevOpenHelper helper = new DaoMaster.DevOpenHelper(this, "students-db", null);
SQLiteDatabase db = helper.getWritableDatabase();
// 建立特定模式下的所有的DAO對象和數據庫db對象的映射
DaoMaster master = new DaoMaster(db);
// 管理特定模式下的所有DAO對象,並提供一些通用的CRUD持久化方法
DaoSession session = master.newSession();
// 得到指定的UserDao對象
UserDao dao = session.getUserDao();
dao.insert(student);
//...
?GreenDao不僅數據庫創建幫我們寫好,也提供了很多CRDU方法,大家可以獲取dao對象後通過”.”這個看到有很多方法供使用,這些都是基本用法,下面介紹一些常用的:
/*
增加:
dao.insert(Student entity);//添加一個
dao.insertInTx(Student...entity);//批量添加
刪除:
dao.deleteByKey(Long key);//根據主鍵刪除
dao.deleteByKeyInTx(Long...keys);//批量刪除
dao.delete(Student entity);//根據實體刪除
dao.deleteInTx(Student... entities);//
批量刪除
dao.deleteAll();//全部刪除
修改:
dao.update(Student entity);//根據實體更新
dao.updateInTx(Student...entities);//批量更新
查找:
Query query = dao.queryBuilder().where(StudentDao.Properties.Name.eq(content)).build();
List list = query.list();//或者利用sql語言查詢
Query query = dao.queryBuilder().where( new StringCondition("_ID IN "+"(SELECT _ID FROM USER WHERE AGE = 20)").build()
*/
封裝使用
?好了,上面講了基本用法,但是想想,我們項目裡,不可能用到數據庫的地方就初始化這麼一大堆吧,而且咱封裝的數據庫方法也不想暴露給使用者,那就要要自己封裝了,下面是我自己研究封裝了一個Helper類,大家可以看看:
/**
* Created by jianglei on 2016/6/30.
*/
public class GreenDaoHelper {
private static final String NB_NAME = "demo";
private static GreenDaoHelper mGreenDaoInstance;
private static Context mApplicationContext;
private DaoMaster.DevOpenHelper mDaoHelper;
private DaoMaster mDaoMaster;
private DaoSession mDaoSession;
private GreenDaoHelper(Context context) {
mDaoHelper = new DaoMaster.DevOpenHelper(context, NB_NAME, null);
mDaoMaster = new DaoMaster(mDaoHelper.getWritableDatabase());
mDaoSession = mDaoMaster.newSession();
}
public static void initGreenDao(Context context) {
mApplicationContext = context;
getInstance();
}
public static GreenDaoHelper getInstance() {
if (mGreenDaoInstance == null) {
synInit(mApplicationContext);
}
return mGreenDaoInstance;
}
private synchronized static void synInit(Context context) {
if (mGreenDaoInstance == null) {
mGreenDaoInstance = new GreenDaoHelper(context);
}
}
/**
* 單條插入表
*
* @param value 傳入bean
*/
@SuppressWarnings("unchecked")
public void singleInsert(T value) {
AbstractDao dao = null;
try {
mDaoSession.insert(value);
dao = mDaoSession.getDao(value.getClass());
} catch (Exception e) {
e.printStackTrace();
}
if (dao != null) {
dao.insert(value);
} else {
throw new IllegalArgumentException("The argument you pass is incorrect!!!");
}
}
/**
* 多條插入表
*
* @param values 傳入bean的list
*/
@SuppressWarnings("unchecked")
public void multiInsert(T values) {
List
?大家可以看到,我在封裝的時候,只需要傳入實體類就行了,那這裡又是怎麼知道它自己的Dao呢,其實這個就要回到前面講AbstractDaoSession的時候,大家可以看到裡面定義了一個Map和一個registerDao方法:
/*AbstractDaoSession*/
private final Map, AbstractDao> entityToDao;
protected void registerDao(Class entityClass, AbstractDao dao) {
entityToDao.put(entityClass, dao);
}
/*DaoMaster*/
public DaoMaster(SQLiteDatabase db) {
super(db, SCHEMA_VERSION);
registerDaoClass(UserDao.class);
}
?而在DaoMaster的構造函數的時候注冊了User的Dao,我就可以通過bean.getClass()獲取到它是哪個實體類clazz,然後通過DaoSession的mDaoSession.getDao(clazz)獲取它的Dao,這樣獲取Dao之後就通過它去CRDU操作,其他的方法我都寫了注釋,大家可以自己看咯。
?在項目中使用:
?1)Application中初始化:
GreenDaoHelper.initGreenDao(this);
?2)需要使用數據庫的地方調用:
GreenDaoHelper.getInstance().(CRDU方法);
?好了,到這裡,GreenDao從java項目配置、四大核心類的分析以及項目中使用就這樣介紹完畢了
這兩天無意間看到一園友的博文實現Path2.0中絢麗的的旋轉菜單,感覺效果不錯,但是發現作者沒有處理線程安全的問題,所以在這裡我修正了下,並且改善下部分功能。今天發布這篇
React-Native Android 與 IOS 共用代碼React-Native 開發的App, 所有組件iOS & Android 共用, 共享一份代
直接看代碼,注釋都寫清楚了復制代碼 代碼如下:public class MainActivity extends Activity { private Imag
在默認情況下,在android下默認只打印info級別的日志信息,所以在默認情況只能打印ormlite中創建數據庫表的語句,而對於數據的插入和查詢等sql語句是不會打印出