Android greenDAO3x数据库框架使用小结
来源:互联网 发布:剑三捏脸数据成男下载 编辑:程序博客网 时间:2024/05/21 17:19
https://github.com/greenrobot/greenDAO
导入工程
在Project目录的build.gradle文件中添加
buildscript { repositories { mavenCentral() } dependencies { classpath 'org.greenrobot:greendao-gradle-plugin:3.2.0' }}
在Module目录中的build.gradle文件中添加
apply plugin: 'org.greenrobot.greendao'dependencies { compile 'org.greenrobot:greendao:3.2.0'}
完成上述动作后,接着给项目配置自动生成创建db代码文件的相关参数。
在Module中配置build.gradle参数
defaultConfig { applicationId "demo.app.android.greendao3xdemo" versionCode 1 }greendao { schemaVersion 1 daoPackage 'demo.app.android.greendao3xdemo.db' targetGenDir 'src/main/java'}
greenDAO 2.x需要创建一个java项目来自动生成表对应的实体类,而3.x可以通过注解的方式来自动生成对应的实体类。
到目前为止,2.x和3.x的生成方式各有优缺点。3.x自动生成的实体类使用起来比2.x便捷,2.x的可以定制内容不同的数据库(多Schema)
不过个人感觉3.x还是比2.x好用很多
一般常见应用中都有用户模块,那么这里创建一个User类演示
package demo.app.android.greendao3xdemo.db.model;@Entitypublic class User { @Id private Long id; @Property(nameInDb = "USERNAME") private String username;}
@Entity 建立表和实体的对应关系
@Id 建立表主键和类成员变量关系
@Property 建立表字段和类成员变量关系
之后Build Moudle,会自动生成构造方法、get、set等
此刻Moudle中应该会产生类似如下的目录结构
在具体数据的crud之前,应该预先在全局的applicaiton对象中准备好数据库session对象
public class App extends Application { private static App instance; private DaoMaster.OpenHelper dbHelper; private DaoSession dbSession; @Override public void onCreate() { super.onCreate(); instance = this; } public static synchronized App i() { return instance; } public DaoSession getDBSession() { if (dbSession != null) { dbSession.clear(); } if (dbHelper == null) { dbHelper = new DaoMaster.DevOpenHelper(this, "db_user"); DaoMaster daoMaster = new DaoMaster(dbHelper.getWritableDatabase()); dbSession = daoMaster.newSession(); } return dbSession; }}
添加登录界面并且加入登录逻辑(并且将用户保存至数据库)
简单的保存动作
String sUsername = eUsername.getText().toString().trim();UserDao userDao = App.i().getDBSession().getUserDao();User user = new User();user.setId(System.currentTimeMillis());user.setUsername(sUsername);userDao.insertOrReplace(user);
那么实际上,user的数据应用一般会用于各个界面,有必要将user作为成员保留在application对象中
public class App extends Application { public void setCurrUser(User user) { UserDao userDao = getDBSession().getUserDao(); userDao.insertOrReplace(user); currUser = user; // 保存上一次的登录者id至SharedPreferences Utils.spWrite("last_login_user_id", currUser.getId()); } public User getCurrUser() { if (currUser == null) { long lastLoginUserId = Utils.spReadLong("last_login_user_id", 0); if (lastLoginUserId > 0) { UserDao userDao = getDBSession().getUserDao(); currUser = userDao.queryBuilder().where(UserDao.Properties.Id.eq(lastLoginUserId)).unique(); } } return currUser; }}
多用户数据库之间的切换
支持多用户登录在app中也是一种常态。那么在构建数据库的时候使用"一个用户对应一个库的策略方案"会有很多优势。
例如 添加新功能 用户可以创建的日记便签
表NOTE 字段 CONTENT
如果所有用户使用同一个数据库
这里将必然添加新字段USER_ID之类的来建立日记便签与用户之间的关联关系,并且在查询数据的时候都必须添加'WHERE USER_ID = ' 之类的条件。
如果使用"一个用户对应一个库的策略方案",由于这个当前库的数据全部都是该用户的,查询效率提高的同时,代码书写也将简化。
那么就需要在用户切换账号登录的同时,程序里需要切换数据库。
public class App extends Application { private static App instance; private DaoMaster.OpenHelper dbHelper; private DaoSession dbSession; private User currUser; @Override public void onCreate() { super.onCreate(); instance = this; } public static synchronized App i() { return instance; } public DaoSession getCurrDBSession() { getCurrUser(); return getDBSession(currUser.getId()); } private DaoSession getDBSession(long id) { if (dbSession != null) { dbSession.clear(); } if (dbHelper != null && (currUser == null || currUser.getId() != id)) { dbHelper.close(); dbHelper = null; } if (dbHelper == null) { dbHelper = new DaoMaster.DevOpenHelper(this, "db_user_" + id); DaoMaster daoMaster = new DaoMaster(dbHelper.getWritableDatabase()); dbSession = daoMaster.newSession(); } return dbSession; } public void setCurrUser(User user) { if (user == null) { if (dbSession != null) { dbSession.clear(); } if (dbHelper != null) { dbHelper.close(); dbHelper = null; } currUser = null; Utils.spWrite("last_login_user_id", 0); } else { UserDao userDao = getDBSession(user.getId()).getUserDao(); userDao.insertOrReplace(user); currUser = user; // 保存上一次的登录者id至SharedPreferences Utils.spWrite("last_login_user_id", currUser.getId()); } } public User getCurrUser() { if (currUser == null) { long lastLoginUserId = Utils.spReadLong("last_login_user_id", 0); if (lastLoginUserId > 0) { UserDao userDao = getDBSession(lastLoginUserId).getUserDao(); currUser = userDao.queryBuilder().where(UserDao.Properties.Id.eq(lastLoginUserId)).unique(); } } return currUser; }}
之后只需要在登录或者切换的时候调用
App.i().setCurrUser()
在全局任意位置需要获得User信息的时候调用
App.i().getCurrUser()
数据库版本升级
版本发布上架后,下一个版本需要添加新功能给用户设置头像
那么首先
@Entitypublic class User { @Id private Long id; @Property(nameInDb = "USERNAME") private String username; @Property(nameInDb = "AVATAR") private String avatar;}
defaultConfig { applicationId "demo.app.android.greendao3xdemo" versionCode 2 }greendao { schemaVersion 2 daoPackage 'demo.app.android.greendao3xdemo.db' targetGenDir 'src/main/java'}
重新Build项目
将这里的schemaVersion改为2后在dbHelper.getWritableDatabase()时刻满足一定条件下会触发onUpgrade方法。此时可以重写OpenHelper#onUpgrade方法更新数据库结构等
以上使用了DaoMaster.DevOpenHelper,而其中逻辑实现为
dropAllTables(db, true); onCreate(db);这样的话,之前版本数据都会丢失。
创建支持升级的OpenHelper
package demo.app.android.greendao3xdemo.db.upgrade;public class UpgradeableOpenHelper extends DaoMaster.OpenHelper { public UpgradeableOpenHelper(Context context, String name) { super(context, name); } @Override public void onUpgrade(Database db, int oldVersion, int newVersion) { Utils.logd("greenDAO Upgrading schema from version %d to %d", oldVersion, newVersion); if (oldVersion == 1 && newVersion == 2) { final long alterDate = System.currentTimeMillis(); // step 1 将表名改为临时表 db.execSQL("ALTER TABLE \"USER\" RENAME TO \"_USER_old_" + alterDate + "\""); // step 2 创建新表 UserDao.createTable(db, false); // step 3 导入数据 final String oldC = "_id, USERNAME"; final String newC = oldC; db.execSQL("INSERT INTO \"USER\" (" + newC + ") SELECT " + oldC + " FROM \"_USER_old_" + alterDate + "\""); // step 4 删除临时表 db.execSQL("DROP TABLE \"_USER_old_" + alterDate + "\""); } }}
if (dbHelper == null) { dbHelper = new UpgradeableOpenHelper(this, "db_user_" + id); DaoMaster daoMaster = new DaoMaster(dbHelper.getWritableDatabase()); dbSession = daoMaster.newSession(); }
随着应用日渐更新,必然的之后将会出现版本3,4,5...
那么这里有必要对UpgradeableOpenHelper的代码进一步优化
public class UpgradeableOpenHelper extends DaoMaster.OpenHelper { public UpgradeableOpenHelper(Context context, String name) { super(context, name); } @Override public void onUpgrade(Database db, int oldVersion, int newVersion) { Utils.logd("greenDAO Upgrading schema from version %d to %d", oldVersion, newVersion); for (int i = oldVersion; i < newVersion; i++) { try { AbstractDBMigratorHelper migratorHelper = (AbstractDBMigratorHelper) Class.forName( AbstractDBMigratorHelper.UPGRADE_PACKAGE_NAME + ".DBMigrationHelper" + (i + 1)).newInstance(); if (migratorHelper != null) { migratorHelper.onUpgrade(db); } } catch (Exception e) { e.printStackTrace(); Utils.loge("greenDAO Could not migrate from schema from schema: %d to %d", i, i + 1); break; } } }}
package demo.app.android.greendao3xdemo.db.upgrade;import org.greenrobot.greendao.database.Database;import java.util.Date;public abstract class AbstractDBMigratorHelper { public static final String UPGRADE_PACKAGE_NAME = "demo.app.android.greendao3xdemo.db.upgrade"; public abstract void onUpgrade(Database db); public static final void createTemporaryTable(Database db, String tableName, Date createDate) { final String ALTER_TABLE_RENAME = "ALTER TABLE \"%s\" RENAME TO \"_%s_old_%ts\""; db.execSQL(String.format(ALTER_TABLE_RENAME, tableName, tableName, createDate)); } public static final void dataTransferFromTemporary(Database db, String tableName, Date tempDate, String oldC, String newC) { final String DATA_TRANSFER = "INSERT INTO \"%s\" (%s) SELECT %s FROM \"_%s_old_%ts\""; db.execSQL(String.format(DATA_TRANSFER, tableName, newC, oldC, tableName, tempDate)); } public static final void dropTemporaryTable(Database db, String tableName, Date createDate) { final String DROP_TABLE = "DROP TABLE \"_%s_old_%ts\""; db.execSQL(String.format(DROP_TABLE, tableName, createDate)); }}
利用Class.forName("").newInstance()和递归机制 将数据库迭代升级的逻辑转移至DBMigrationHelper中
例如刚才的version1升级到version2的逻辑可以简化为
public class DBMigrationHelper2 extends AbstractDBMigratorHelper { @Override public void onUpgrade(Database db) { Date alterDate = new Date(); // step 1 将表名改为临时表 createTemporaryTable(db, UserDao.TABLENAME, alterDate); // step 2 创建新表 UserDao.createTable(db, false); // step 3 导入数据 final String oldC = "_id, USERNAME"; final String newC = oldC; dataTransferFromTemporary(db, UserDao.TABLENAME, alterDate, oldC, newC); // step 4 删除临时表 dropTemporaryTable(db, UserDao.TABLENAME, alterDate); }}
数据库内容加密
http://greenrobot.org/greendao/documentation/database-encryption/
混淆规则 引用自‘http://www.jianshu.com/p/cb4d346d7e2a’
### greenDAO 3-keepclassmembers class * extends org.greenrobot.greendao.AbstractDao {public static java.lang.String TABLENAME;}-keep class **$Properties# If you do not use SQLCipher:-dontwarn org.greenrobot.greendao.database.**# If you do not use RxJava:-dontwarn rx.**### greenDAO 2-keepclassmembers class * extends de.greenrobot.dao.AbstractDao {public static java.lang.String TABLENAME;}-keep class **$Properties
-keep class com.cn.daqi.otv.db.*{ *; } (实体类所在的包)
- Android greenDAO3x数据库框架使用小结
- Android 数据库使用小结
- Android数据库(SQLiteDatabase)使用小结
- Android数据库(SQLiteDatabase)使用小结
- Android数据库(SQLiteDatabase)使用小结 .
- Android SQLite数据库使用小结
- Android 数据库SQLite使用小结
- Android下拉刷新框架PullToRefresh使用小结
- 【Android 】Litepal 数据库框架使用
- Android GreenDao数据库框架使用
- Android数据库框架DbFlow使用
- Android 数据库框架 LiteOrm使用
- Android SQLite数据库的使用小结
- android-pulltorefesh快速开发框架的使用小结
- Android 数据库框架ormlite 使用精要
- Android 数据库框架ormlite 使用精要
- android 数据库操作使用ormlite框架1
- Android 数据库框架ormlite 使用精要
- ubuntu 安装eclipse
- 设计模式-----工厂模式
- 排序算法(二) 冒泡排序
- 一般现在常见的网站攻击方式 及预防
- 使用Java原生API编写发送HTTP_POST请求的工具类
- Android greenDAO3x数据库框架使用小结
- 六、python笔记之常用操作符
- Linux系统不能读取NTFS格式磁盘的解决方案
- 空指针和未初始化的指针的区别
- js正则表达式例子
- spring boot 不使用parent
- android studio应用签名步骤详解
- profile介绍
- js实现商品加减及统计