GreenDao 使用

环境搭建(android studio)

project的build.gradle

buildscript {

    repositories {
google()
jcenter()
//maven 仓库
mavenCentral()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.1.2'
//GreenDao 的插件
classpath 'org.greenrobot:greendao-gradle-plugin:3.2.2'
}
} allprojects {
repositories {
google()
jcenter()
}
} task clean(type: Delete) {
delete rootProject.buildDir
}

app的build.gradle

apply plugin: 'com.android.application'
//使用GreenDao 的插件
apply plugin: 'org.greenrobot.greendao' android {
compileSdkVersion 27
defaultConfig {
applicationId "com.test.greendao"
minSdkVersion 23
targetSdkVersion 27
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
} //添加自动生成代码的部分,在构建工程部分使用
greendao{
//设置数据库的版本
schemaVersion 1
//设置DaoMaster,DaoSession,Dao包名,
daoPackage 'com.test.greendao.dao'
targetGenDir 'src/main/java'
} dependencies {
implementation fileTree(include: ['*.jar'], dir: 'libs')
implementation 'com.android.support:appcompat-v7:27.1.1'
implementation 'com.android.support.constraint:constraint-layout:1.1.1'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
//GreenDao 依赖
implementation 'org.greenrobot:greendao:3.2.2'
//GreenDao 自动生成代码的依赖,没有使用到
//implementation 'org.greenrobot:greendao-generator:3.2.2'
}

编写自己的实体类

//使用Entity注解标识这个实体类和数据库表的关系
@Entity
public class Student {
//使用Id注解标识这个字段在数据库表结构中是主键,自增的
@Id
private Long id;
private String name;
private String email;
private Integer age;
}

构建工程

选择Build->Make Project,会自动生成一些类,比如我们当前项目中的实体类是Student,那么会生成如下的类
DaoMaster
DaoSession
StudentDao
并将Student类中的get,set方法进行补全,并生成2个构造方法
生成类的配置在app的build.gradle文件中的greendao的任务中进行了配置

使用生成的类操作数据库

配置全局的DaoMaster,DaoSession等信息

创建DbManager类来管理数据库相关的类,DaoMaster,DaoSession,xxxDao等

public class DbManager {
//是否加密,当前没有处理加密
private static final boolean ENCRYPTED = true;
//数据库名
private static final String DB_NAME = "test.db";
private static DbManager dbManager;
private static DaoMaster.DevOpenHelper helper;
private static DaoMaster daoMaster;
private static DaoSession daoSession;
private Context mContext; private DbManager(Context context){
this.mContext =context;
//初始化数据库信息
helper = new DaoMaster.DevOpenHelper(context,DB_NAME);
getDaoMaster(mContext);
getDaoSession(mContext);
} public static DbManager getInstance(Context context){
if(null == dbManager){
synchronized (DbManager.class){
if(null == dbManager){
dbManager = new DbManager(context);
}
}
}
return dbManager;
} public static SQLiteDatabase getReadableDatabase(Context context){
if(null == helper){
getInstance(context);
}
return helper.getReadableDatabase();
} public static SQLiteDatabase getWritableDatabase(Context context){
if(null == helper){
getInstance(context);
}
return helper.getWritableDatabase();
} public static DaoMaster getDaoMaster(Context context) {
if(null == daoMaster){
synchronized (DbManager.class){
if(null == daoMaster){
daoMaster = new DaoMaster(getWritableDatabase(context));
//数据库升级,降级操作使用下面的方法
//MyOpenHelper helper = new MyOpenHelper(context,DB_NAME);
//daoMaster = new DaoMaster(helper.getWritableDb());
}
}
}
return daoMaster;
} public static DaoSession getDaoSession(Context context) {
if(null == daoSession){
synchronized (DbManager.class){
daoSession = getDaoMaster(context).newSession();
}
}
return daoSession;
} }

数据库的升级降级操作

数据库升级的原理

创建临时表
将原始表中数据转移到临时表中
删除原始表
创建新表
将临时表中数据转移到新表中
删除临时表

需要的类

MigrationHelper

public class MigrationHelper {
private static final String CONVERSION_CLASS_NOT_FOUND_EXCEPTION = "MIGRATION HELPER - CLASS DOESN'T MATCH WITH THE CURRENT PARAMETERS";
private static MigrationHelper instance; public static MigrationHelper getInstance() {
if (instance == null) {
instance = new MigrationHelper();
}
return instance;
} public void migrate(Database db, Class<? extends AbstractDao<?, ?>>... daoClasses) { generateTempTables(db, daoClasses);
DaoMaster.dropAllTables(db, true);
DaoMaster.createAllTables(db, false);
restoreData(db, daoClasses);
} /**
* 生成临时列表
*
* @param db
* @param daoClasses
*/
private void generateTempTables(Database db, Class<? extends AbstractDao<?, ?>>... daoClasses) {
for (int i = 0; i < daoClasses.length; i++) {
DaoConfig daoConfig = new DaoConfig(db, daoClasses[i]); String divider = "";
String tableName = daoConfig.tablename;
String tempTableName = daoConfig.tablename.concat("_TEMP");
ArrayList<String> properties = new ArrayList<>(); StringBuilder createTableStringBuilder = new StringBuilder(); createTableStringBuilder.append("CREATE TABLE ").append(tempTableName).append(" ("); for (int j = 0; j < daoConfig.properties.length; j++) {
String columnName = daoConfig.properties[j].columnName; if (getColumns(db, tableName).contains(columnName)) {
properties.add(columnName); String type = null; try {
type = getTypeByClass(daoConfig.properties[j].type);
} catch (Exception exception) {
exception.printStackTrace();
} createTableStringBuilder.append(divider).append(columnName).append(" ").append(type); if (daoConfig.properties[j].primaryKey) {
createTableStringBuilder.append(" PRIMARY KEY");
} divider = ",";
}
}
createTableStringBuilder.append(");"); db.execSQL(createTableStringBuilder.toString()); StringBuilder insertTableStringBuilder = new StringBuilder(); insertTableStringBuilder.append("INSERT INTO ").append(tempTableName).append(" (");
insertTableStringBuilder.append(TextUtils.join(",", properties));
insertTableStringBuilder.append(") SELECT ");
insertTableStringBuilder.append(TextUtils.join(",", properties));
insertTableStringBuilder.append(" FROM ").append(tableName).append(";"); db.execSQL(insertTableStringBuilder.toString()); }
} /**
* 存储新的数据库表 以及数据
*
* @param db
* @param daoClasses
*/
private void restoreData(Database db, Class<? extends AbstractDao<?, ?>>... daoClasses) {
for (int i = 0; i < daoClasses.length; i++) {
DaoConfig daoConfig = new DaoConfig(db, daoClasses[i]);
String tableName = daoConfig.tablename;
String tempTableName = daoConfig.tablename.concat("_TEMP");
ArrayList<String> properties = new ArrayList(); for (int j = 0; j < daoConfig.properties.length; j++) {
String columnName = daoConfig.properties[j].columnName; if (getColumns(db, tempTableName).contains(columnName)) {
properties.add(columnName);
}
} StringBuilder insertTableStringBuilder = new StringBuilder(); insertTableStringBuilder.append("INSERT INTO ").append(tableName).append(" (");
insertTableStringBuilder.append(TextUtils.join(",", properties));
insertTableStringBuilder.append(") SELECT ");
insertTableStringBuilder.append(TextUtils.join(",", properties));
insertTableStringBuilder.append(" FROM ").append(tempTableName).append(";"); StringBuilder dropTableStringBuilder = new StringBuilder();
dropTableStringBuilder.append("DROP TABLE ").append(tempTableName);
db.execSQL(insertTableStringBuilder.toString());
db.execSQL(dropTableStringBuilder.toString());
}
} private String getTypeByClass(Class<?> type) throws Exception {
if (type.equals(String.class)) {
return "TEXT";
}
if (type.equals(Long.class) || type.equals(Integer.class) || type.equals(long.class)) {
return "INTEGER";
}
if (type.equals(Boolean.class)) {
return "BOOLEAN";
} Exception exception = new Exception(CONVERSION_CLASS_NOT_FOUND_EXCEPTION.concat(" - Class: ").concat(type.toString()));
exception.printStackTrace();
throw exception;
} private List<String> getColumns(Database db, String tableName) {
List<String> columns = new ArrayList<>();
Cursor cursor = null;
try {
cursor = db.rawQuery("SELECT * FROM " + tableName + " limit 1", null);
if (cursor != null) {
columns = new ArrayList<>(Arrays.asList(cursor.getColumnNames()));
}
} catch (Exception e) {
Log.v(tableName, e.getMessage(), e);
e.printStackTrace();
} finally {
if (cursor != null)
cursor.close();
}
return columns;
}
}

MyOpenHelper继承自DaoMaster.OpenHelper

public class MyOpenHelper extends DaoMaster.OpenHelper {
public MyOpenHelper(Context context, String name) {
super(context, name);
} @Override
public void onUpgrade(Database db, int oldVersion, int newVersion) {
super.onUpgrade(db, oldVersion, newVersion);
//操作数据库的更新 有几个表升级都可以传入到下面
Log.i("version", oldVersion + "---先前和更新之后的版本---" + newVersion);
if (oldVersion < newVersion) {
Log.i("version", oldVersion + "---先前和更新之后的版本---" + newVersion);
MigrationHelper.getInstance().migrate(db, StudentDao.class);
//更改过的实体类(新增的不用加) 更新UserDao文件 可以添加多个 XXDao.class 文件
//MigrationHelper.getInstance().migrate(db, UserDao.class,XXDao.class);
}
//MigrationHelper.getInstance().migrate(db,StudentDao.class);
}
}

小坑

运行时,操作数据库会报这个错

org.greenrobot.greendao.database.DatabaseOpenHelper$EncryptedHelper>: java.lang.NoClassDefFoundError: Failed resolution of: Lnet/sqlcipher/database/SQLiteOpenHelper;

实际是缺少了加密的组件依赖,并不影响实际的运行,为了消除错误信息,在app的build.gradle文件中加入如下代码

implementation 'net.zetetic:android-database-sqlcipher:3.5.2'

GreenDao 初体验的更多相关文章

  1. .NET平台开源项目速览(15)文档数据库RavenDB-介绍与初体验

    不知不觉,“.NET平台开源项目速览“系列文章已经15篇了,每一篇都非常受欢迎,可能技术水平不高,但足够入门了.虽然工作很忙,但还是会抽空把自己知道的,已经平时遇到的好的开源项目分享出来.今天就给大家 ...

  2. Xamarin+Prism开发详解四:简单Mac OS 虚拟机安装方法与Visual Studio for Mac 初体验

    Mac OS 虚拟机安装方法 最近把自己的电脑升级了一下SSD固态硬盘,总算是有容量安装Mac 虚拟机了!经过心碎的安装探索,尝试了国内外的各种安装方法,最后在youtube上找到了一个好方法. 简单 ...

  3. Spring之初体验

                                     Spring之初体验 Spring是一个轻量级的Java Web开发框架,以IoC(Inverse of Control 控制反转)和 ...

  4. Xamarin.iOS开发初体验

    aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAKwAAAA+CAIAAAA5/WfHAAAJrklEQVR4nO2c/VdTRxrH+wfdU84pW0

  5. 【腾讯Bugly干货分享】基于 Webpack & Vue & Vue-Router 的 SPA 初体验

    本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/57d13a57132ff21c38110186 导语 最近这几年的前端圈子,由于 ...

  6. 【Knockout.js 学习体验之旅】(1)ko初体验

    前言 什么,你现在还在看knockout.js?这货都已经落后主流一千年了!赶紧去学Angular.React啊,再不赶紧的话,他们也要变out了哦.身旁的90后小伙伴,嘴里还塞着山东的狗不理大蒜包, ...

  7. 在同一个硬盘上安装多个 Linux 发行版及 Fedora 21 、Fedora 22 初体验

    在同一个硬盘上安装多个 Linux 发行版 以前对多个 Linux 发行版的折腾主要是在虚拟机上完成.我的桌面电脑性能比较强大,玩玩虚拟机没啥问题,但是笔记本电脑就不行了.要在我的笔记本电脑上折腾多个 ...

  8. 百度EChart3初体验

    由于项目需要在首页搞一个订单数量的走势图,经过多方查找,体验,感觉ECharts不错,封装的很细,我们只需要看自己需要那种类型的图表,搞定好自己的json数据就OK.至于说如何体现出来,官网的教程很详 ...

  9. Python导出Excel为Lua/Json/Xml实例教程(二):xlrd初体验

    Python导出Excel为Lua/Json/Xml实例教程(二):xlrd初体验 相关链接: Python导出Excel为Lua/Json/Xml实例教程(一):初识Python Python导出E ...

随机推荐

  1. springboot(九)-log配置

    spring项目放到tomcat中运行,我们可以在tomcat的logs文件夹下面生成log文件.那么我们的springboot项目没有放到系统安装的tomcat容器中,怎么设置生成log文件呢? 有 ...

  2. Emma姐

  3. Which mb sdconnect c4 worth the money?

    MB SD connect C4 with laptop v2018.5 Version avaiable now ,It is ready to work after you get it ,wor ...

  4. element-ui 使用span-method表格合并后hover样式的处理

    在使用element表格合并后,发现鼠标只有移入第一个合并行时,合并的部分会高亮,移入其他行,不会高亮,这样效果看起来不是很好.查看了文档也没有直接的解决方法,就通过现有的方法处理了一下,解决了hov ...

  5. restsharp 组件调用返回 gbk 编码的api,中文乱码解决方法。(restsharp response 中文乱码 gbk)

    最近要调一个restful风格的api 用了 一个开源第三方组件,组件还是蛮好用的, 支持直接按参数定义实体类,然后发起请求之前直接 addobject 的方式就把请求参数给添加进去了, 解码的时候可 ...

  6. xamarin RunOnUiThread

    One of the keys to maintaining a responsive GUI is to do long-running tasks on a background thread s ...

  7. Git学习系列之一些常用的Git命令收录更新ing

    不多说,直接上干货!  前言 对于Git工具,有必要整理和总结一些常用实用的命令. http://p.primeton.com/articles/53cce3a3e138236138000026 ht ...

  8. MySQL通过SQL语句来直接生成新表

    1. 既复制表结构,也复制表数据 mysql> CREATE TABLE tmp_table SELECT * FROM dede_news; 说明:这种方法的缺点就是新表中没有了旧表的prim ...

  9. bzoj 4540: [Hnoi2016]序列

    Description 给定长度为n的序列:a1,a2,-,an,记为a[1:n].类似地,a[l:r](1≤l≤r≤N)是指序列:al,al+1,-,ar- 1,ar.若1≤l≤s≤t≤r≤n,则称 ...

  10. 线上服务器PHP版本编译安装升级全记录

    1.将原来的PHP重命名一下 cd /usr/local/bin/ mv php php.2.9 2.安装依赖 yum install gcc gcc-c++ libxml2 libxml2-deve ...