Android几种常用存储数据库的区别,想查看区别的朋友请移步查看
使用GreenDao主要有几大核心的类:
1.DaoMaster
:它保存了sqlitedatabase对象以及操作DAO classes。其提供了一些创建和删除table的静态方法,其内部类OpenHelper和DevOpenHelper实现了SQLiteOpenHelper并创建数据库的框架。
2.DaoSession
:会话层。操作具体的DAO对象,比如各种getter方法。
3.XXXDao
:实际生成的xxDAO类,通常对应具体的java类,比如FoodsBeanDao等。其有更多的权限和方法来操作数据库元素。
4.XXXEntity
:持久的实体对象。通常代表了一个数据库row的标准java properties。
先贴一下初始化代码过后再讲解
//创建数据库foodlist.db"
DaoMaster.DevOpenHelper helper = new DaoMaster.DevOpenHelper(this, "foodlist.db", null);
//获取可写数据库
SQLiteDatabase db = helper.getWritableDatabase();
//获取数据库对象
DaoMaster daoMaster = new DaoMaster(db);
//获取Dao对象管理者
DaoSession daoSession = daoMaster.newSession();
(参考github上的版本号,此处我用的是3.2.2)
在Project的build.gradle文件中
dependencies {
//GreenDao3依赖
classpath 'org.greenrobot:greendao-gradle-plugin:3.2.2'
}
在module的build.gradle文件中
apply plugin: 'com.android.application'
apply plugin: 'org.greenrobot.greendao' // apply plugin
android {
sourceSets {
main {
java.srcDirs = ['src/main/java', 'src/main/java-gen']
}
}
}
greendao {
schemaVersion 1 //数据库版本号
generateTests false //设置为true以自动生成单元测试。
daoPackage 'com.greendao.gen' // 设置DaoMaster、DaoSession、Dao 包名
targetGenDir 'src/main/java-gen' //应存储生成的单元测试的基本目录。默认为 src / androidTest / java。
}
dependencies {
implementation 'org.greenrobot:greendao:3.2.2' // add library
}
注意:此处配置完后先不要运行程序,等把bean类写好后再编译
以为项目中为例,看代码:
@Entity
public class AddFoodEntity {
/**
* foodType : 食物分类1
* foods : [{"foodId":1,"foodName":"食物1","foodType":"食物分类1","foodTag":"钙","foodIngredient":"营养成分","foodEnergy":234,"unit":"100g","foodWeight":0},{"foodId":2,"foodName":"食物2","foodType":"食物分类1","foodTag":"钙","foodIngredient":"营养成分","foodEnergy":234,"unit":"100g","foodWeight":0},{"foodId":3,"foodName":"食物3","foodType":"食物分类1","foodTag":"钙","foodIngredient":"营养成分","foodEnergy":234,"unit":"100g","foodWeight":0},{"foodId":4,"foodName":"食物4","foodType":"食物分类1","foodTag":"钙","foodIngredient":"营养成分","foodEnergy":234,"unit":"100g","foodWeight":0},{"foodId":5,"foodName":"食物5","foodType":"食物分类1","foodTag":"钙","foodIngredient":"营养成分","foodEnergy":234,"unit":"100g","foodWeight":0},{"foodId":6,"foodName":"食物6","foodType":"食物分类1","foodTag":"钙","foodIngredient":"营养成分","foodEnergy":234,"unit":"100g","foodWeight":0},{"foodId":7,"foodName":"食物7","foodType":"食物分类1","foodTag":"钙","foodIngredient":"营养成分","foodEnergy":234,"unit":"100g","foodWeight":0},{"foodId":8,"foodName":"食物8","foodType":"食物分类1","foodTag":"钙","foodIngredient":"营养成分","foodEnergy":234,"unit":"100g","foodWeight":0},{"foodId":9,"foodName":"食物9","foodType":"食物分类1","foodTag":"钙","foodIngredient":"营养成分","foodEnergy":234,"unit":"100g","foodWeight":0},{"foodId":10,"foodName":"食物10","foodType":"食物分类1","foodTag":"钙","foodIngredient":"营养成分","foodEnergy":234,"unit":"100g","foodWeight":0}]
*/
private String foodType;
@Convert(converter = FoodsBeanConverter.class, columnType = String.class)
private List foods;
public String getFoodType() {
return foodType;
}
public void setFoodType(String foodType) {
this.foodType = foodType;
}
public List getFoods() {
return foods;
}
public void setFoods(List foods) {
this.foods = foods;
}
}
注意:此处的bean类跟往常的不相同,在类名上加注解@Entity,除此之外还加了一个@Convert(converter = FoodsBeanConverter.class, columnType = String.class),这是必须要加上的,否则编译的时候会报错。
上面代码的FoodsBeanConverter.class是哪里来的,,这里要自己写一个XXXConverter类,如下代码
public class FoodsBeanConverter implements PropertyConverter,String> {
@Override
public List convertToEntityProperty(String databaseValue) {
if (databaseValue == null) {
return null;
}
JsonArray jsonArray = new JsonParser().parse(databaseValue).getAsJsonArray();
Gson gson = new Gson();
ArrayList userBeanList = new ArrayList<>();
//循环遍历
for (JsonElement user : jsonArray) {
//通过反射 得到UserBean.class
FoodsBean userBean = gson.fromJson(user, FoodsBean.class);
userBeanList.add(userBean);
}
return userBeanList;
// return JSON.parseArray(databaseValue, EmpPointListEntity.class); //如果你是用fastjson解析数据就用这个,上方的是Gson
}
@Override
public String convertToDatabaseValue(List entityProperty) {
return new Gson().toJson(entityProperty);
// return JSON.toJSONString(entityProperty); //fastjson 如果你是用fastjson解析数据就用这个,上方的是Gson
}
}
注意:此处生成的是 Listfoods 集合,这里有人会问,那万一我这里是FoodsBean foods对象呢?那也要写一个对象的Converter实现PropertyConverter接口,,只要记住json里面不管是包裹的list还是Object都要写一个类实现PropertyConverter接口
这里写一个json里包裹的Object实体类,如下代码:
public class FoodsObjectConverter implements PropertyConverter {
@Override
public FoodsBean convertToEntityProperty(String databaseValue) {
// return JSON.parseObject(databaseValue, FoodsBean.class); fastjson
return new Gson().fromJson(databaseValue, FoodsBean.class);
}
@Override
public String convertToDatabaseValue(FoodsBean entityProperty) {
// return JSON.toJSONString(entityProperty); fastjson
return new Gson().toJson(entityProperty, FoodsBean.class);
}
}
可能你们也会问那FoodsBean这个实体类里需要写什么吗?其实这里面不需要写什么,跟往常一样,还是贴一下代码给你们看一下:
public class FoodsBean implements Parcelable{
/**
* foodId : 1
* foodName : 食物1
* foodType : 食物分类1
* foodTag : 钙
* foodIngredient : 营养成分
* foodEnergy : 234
* unit : 100g
* foodWeight : 0
*/
private int foodId;
private String foodName;
private String foodType;
public int getFoodId() {
return foodId;
}
public void setFoodId(int foodId) {
this.foodId = foodId;
}
public String getFoodName() {
return foodName;
}
public void setFoodName(String foodName) {
this.foodName = foodName;
}
public String getFoodType() {
return foodType;
}
public void setFoodType(String foodType) {
this.foodType = foodType;
}
}
就跟往常一样该实现Parcelable接口就实现,做到这一步就可以编译运行程序了,运行程序完成后你就可以注意一下目录结构,发现在build.gradle设置的greendao,就生成你设置的样子。
在Application 中设置添加:
public class MyGDApplication extends Application {
private DaoSession daoSession;
@Override
public void onCreate() {
super.onCreate();
//设置数据库
setGreenDaoBase();
}
private void setGreenDaoBase() {
//创建数据库topnews.db"
DaoMaster.DevOpenHelper helper = new DaoMaster.DevOpenHelper(this, "foodlist.db", null);
//获取可写数据库
SQLiteDatabase db = helper.getWritableDatabase();
//获取数据库对象
DaoMaster daoMaster = new DaoMaster(db);
//获取Dao对象管理者
daoSession = daoMaster.newSession();
}
public DaoSession getDaoSession() {
return daoSession;
}
}
这跟最上面设置的是一样的,在Application里设置完后,要在你想要保存数据的Activity中保存数据和读取数据。
在该Activity中初始化获取DaoSession并进行相关的操作,已经创建好了DaoSession和Bean对象,编译后会自动生成我们的AddFoodEntityDao对象,可通过DaoSession获得:
DaoSession daoSession =BaseApp.instance().getDaoSession();
AddFoodEntityDao foodsDao=daoSession.getAddFoodEntityDao();
当你第一次加载页面请求数据成功时,就保存下来,下次再进页面就不用重复的请求数据了:
public void saveGreenDaoData() {
//foodsDao是获取的数据库操作对象,先把数据库里有的先清除再保存;
foodsDao.deleteAll();
//此处的list是我实例化的 List list=new ArrayList<>();
if(list!=null&&list.size()>0) {
for (int i=0;i
当下次进来后就不需要去请求数据了,此时就读取保存在本地的数据:
public void setGreenDaoNoNetwork(){
// Query notesQuery = foodsDao.queryBuilder().build();
// List dbTopList = notesQuery.list();
List dbTopList = foodsDao.loadAll();
//重新装配数据并刷新
list.clear();
list.addAll(dbTopList);
//这里是我刷新列表用的adapter
adapter.setRefreshData(list.get(0).getFoods());
}
这里我是保存在本地的SharePrefences一个标识判断是否请求或者加载本地数据。到了这里一般的问题都会解决。有很多才接触到GreenDao的朋友,在bean类注解会出现编译不通过,主要是没理解到PropertyConverter接口没加上这段代码,导致编译失败,反正只要json里不管是集合还是对象bean,都要写一个类实现PropertyConverter接口。
GreenDao是通过表的主键和外键来查询的。
一对一查询:是通过 @ToOne(joinProerty = “外键ID”)注解,来声明外表
添加数据时主表的外键要和外表的主键一致 insertOrReplace方法添加表对象
查询通过queryBuilder().where(条件)方法
一对多:是通过 @ToMany(referencedJoinProperty = “外键ID”) 注解 来声明外表 因为是一对多的关系所以是外键表集合(List集合)
添加数据时主表的外键要和外表的主键一致 insertOrReplaceInTx方法添加集合表对象
查询通过queryBuilder().where(条件)方法GreenDao升级方式?
1.新建一个类继承OpenHelper(SQLite的OpenHelper)
2.重写里面的OnUpgrate
3.判断版本是否一致,一致执行原本的步骤,不一致执行版本升级
添加数据: foodsDao.insert();
删除数据: foodsDao.delete();
修改数据: foodsDao.update();
查询数据: foodsDao.loadAll();
条件查询: foodsDao.queryBuilder().where(FoodsBean.Properties.foodName.eq( “食物一” )) .list();
1.当配置完运行程序后,在目录结构中java-gen文件里包的层级是递进的,或者里面的class类出现红色的j,这说明没成功,主要原因是写的bean有问题,上面的写得很清楚,可以重点看一下,最好加上’src/main/java-gen’。
2.如果不能自动生成,那就注意一下代码或者配置是否出错,按照上面的步骤实现,应该就不会错。
3.要使用其他关于数据的操作,得到foodsDao类的实体类就可以操作其他方法。
4.如有不懂得请留言。