GreenDao 初体验
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 初体验的更多相关文章
- .NET平台开源项目速览(15)文档数据库RavenDB-介绍与初体验
不知不觉,“.NET平台开源项目速览“系列文章已经15篇了,每一篇都非常受欢迎,可能技术水平不高,但足够入门了.虽然工作很忙,但还是会抽空把自己知道的,已经平时遇到的好的开源项目分享出来.今天就给大家 ...
- Xamarin+Prism开发详解四:简单Mac OS 虚拟机安装方法与Visual Studio for Mac 初体验
Mac OS 虚拟机安装方法 最近把自己的电脑升级了一下SSD固态硬盘,总算是有容量安装Mac 虚拟机了!经过心碎的安装探索,尝试了国内外的各种安装方法,最后在youtube上找到了一个好方法. 简单 ...
- Spring之初体验
Spring之初体验 Spring是一个轻量级的Java Web开发框架,以IoC(Inverse of Control 控制反转)和 ...
- Xamarin.iOS开发初体验
aaarticlea/png;base64,iVBORw0KGgoAAAANSUhEUgAAAKwAAAA+CAIAAAA5/WfHAAAJrklEQVR4nO2c/VdTRxrH+wfdU84pW0
- 【腾讯Bugly干货分享】基于 Webpack & Vue & Vue-Router 的 SPA 初体验
本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/57d13a57132ff21c38110186 导语 最近这几年的前端圈子,由于 ...
- 【Knockout.js 学习体验之旅】(1)ko初体验
前言 什么,你现在还在看knockout.js?这货都已经落后主流一千年了!赶紧去学Angular.React啊,再不赶紧的话,他们也要变out了哦.身旁的90后小伙伴,嘴里还塞着山东的狗不理大蒜包, ...
- 在同一个硬盘上安装多个 Linux 发行版及 Fedora 21 、Fedora 22 初体验
在同一个硬盘上安装多个 Linux 发行版 以前对多个 Linux 发行版的折腾主要是在虚拟机上完成.我的桌面电脑性能比较强大,玩玩虚拟机没啥问题,但是笔记本电脑就不行了.要在我的笔记本电脑上折腾多个 ...
- 百度EChart3初体验
由于项目需要在首页搞一个订单数量的走势图,经过多方查找,体验,感觉ECharts不错,封装的很细,我们只需要看自己需要那种类型的图表,搞定好自己的json数据就OK.至于说如何体现出来,官网的教程很详 ...
- Python导出Excel为Lua/Json/Xml实例教程(二):xlrd初体验
Python导出Excel为Lua/Json/Xml实例教程(二):xlrd初体验 相关链接: Python导出Excel为Lua/Json/Xml实例教程(一):初识Python Python导出E ...
随机推荐
- springboot(九)-log配置
spring项目放到tomcat中运行,我们可以在tomcat的logs文件夹下面生成log文件.那么我们的springboot项目没有放到系统安装的tomcat容器中,怎么设置生成log文件呢? 有 ...
- Emma姐
- 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 ...
- element-ui 使用span-method表格合并后hover样式的处理
在使用element表格合并后,发现鼠标只有移入第一个合并行时,合并的部分会高亮,移入其他行,不会高亮,这样效果看起来不是很好.查看了文档也没有直接的解决方法,就通过现有的方法处理了一下,解决了hov ...
- restsharp 组件调用返回 gbk 编码的api,中文乱码解决方法。(restsharp response 中文乱码 gbk)
最近要调一个restful风格的api 用了 一个开源第三方组件,组件还是蛮好用的, 支持直接按参数定义实体类,然后发起请求之前直接 addobject 的方式就把请求参数给添加进去了, 解码的时候可 ...
- xamarin RunOnUiThread
One of the keys to maintaining a responsive GUI is to do long-running tasks on a background thread s ...
- Git学习系列之一些常用的Git命令收录更新ing
不多说,直接上干货! 前言 对于Git工具,有必要整理和总结一些常用实用的命令. http://p.primeton.com/articles/53cce3a3e138236138000026 ht ...
- MySQL通过SQL语句来直接生成新表
1. 既复制表结构,也复制表数据 mysql> CREATE TABLE tmp_table SELECT * FROM dede_news; 说明:这种方法的缺点就是新表中没有了旧表的prim ...
- 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,则称 ...
- 线上服务器PHP版本编译安装升级全记录
1.将原来的PHP重命名一下 cd /usr/local/bin/ mv php php.2.9 2.安装依赖 yum install gcc gcc-c++ libxml2 libxml2-deve ...