本文参考了阿呆的GreenDao3.2的简单使用一文: https://www.cnblogs.com/wjtaigwh/p/6394288.html
这段时间准备一直在准备一些老项目的重构需要用到的技术点,其中一项技术要掉便是数据库的使用,查阅了相关资料,熟悉了GreenDao数据的使用要点,现在简单的说说:
1、GreenDao的有点比如响应速度快、依赖包小等在此不多说,听说过这套数据库方案的伙伴们应该都知道。
2、我们在此说说他的另外几个优点:集成方便、使用简单。
一、集成GreenDao数据库:
1、在工程App的gradle下加入:apply plugin: 'org.greenrobot.greendao';
2、在工程App的gradle下的dependencies添加依赖:compile 'org.greenrobot:greendao:3.2.0';
3、在在工程App的gradle下的android{}里面添加GreenDao数据库的版本号:
greendao {
//版本号,升级时可配置
schemaVersion 1
daoPackage 'com.haoyue.greendao'
targetGenDir 'src/main/java'
}
其中schemaVersion 是必须添加的,用于以后数据库的迭代更新;daoPackage 和targetGenDir 是候选项,作用是指定生成的GreenDao的java文件的存放位置。
App的gradle集成完毕,现在开始集成Moudle下的gradle:
1、在dependencies下添加classpath 'org.greenrobot:greendao-gradle-plugin:3.2.1'
2、在repositories中加入:maven { url "https://maven.google.com" };
Moudle下的gradle整体如下:
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.3.3'
classpath 'org.greenrobot:greendao-gradle-plugin:3.2.1'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
jcenter()
maven { url "https://maven.google.com" }
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
至此,GreenDao的依赖集成完毕。
二、创建我们要保存的对象的Bean文件:
@Entity
public class ShopBean {
public static final int SHOPCART = 0x001;
public static final int COLLECTION = 0x002;
//Id表示主键且主键不能用int;autoincrement=true表示主键Id自增
@org.greenrobot.greendao.annotation.Id(autoincrement = true)
private Long Id;
//商品名称 (unique 表示该属性必须在数据库中是唯一的值)
@Unique
private String name;
//商品价格
private String price;
//已售数量
private int sellNumber;
//图标地址
private String imageUrl;
//商家地址
private String merchantAddress;
//商品列表分类
private int type;
}
这里对ShopBean里面的对象的注解做简要说明:
1、@Entity:将我们的java普通类变为一个能够被greenDAO识别的数据库类型的实体类;
2、@Id 对应数据表中的 Id 字段,是一条数据的唯一标识。
3、@Property(nameInDb = “STUDENTNUM”)表名这个属性对应数据表中的 STUDENTNUM 字段。
4、 @NotNull:使该属性在数据库端成为“NOT NULL”列。 通常使用@NotNull标记原始类型(long,int,short,byte)是有意义的;
5、@Transient:表明这个字段不会被写入数据库,只是作为一个普通的java类字段,用来临时存储数据的,不会被持久化。
6、@Property 可以自定义字段名,注意外键不能使用该属性
7、@Unique 表名该属性在数据库中只能有唯一值
以上7项中,1和2是必须的,不能省略,否则数据库表将会创建失败。其余选项根据需要添加。
三、点击Build中的MakeProject,AndroidStudio会自动帮我们生成变量的Getter和Setter方法以及有参构造方法和无参构造方法,同时还会在我们指定的文件包(src/main/java/com.haoyue.greendao)下生成DaoMaster.java, DaoSession.java, ShopBeanDao.java三个类文件,这三个文件将会帮助我们方便的操作数据库,但并不需要我们对其操作或者更改。
四、编辑操作数据库的Utils文件。
关于这部分,有部分伙伴们是写成几个部分的,一部分是DaoManager文件,用于创建数据库、创建数据库表、包含增删改查的操作以及数据库的升级。另一部分才是操作数据库的Utils文件。这里我将二者写在同一个文件里面。具体如下:
public class GreenDaoUtils {
public static final String SHOP_DB_Name = "ShopBean.db";
public static DaoSession sDaoSession;
public static DaoMaster.DevOpenHelper helper;
public static DaoMaster master;
public static GreenDaoUtils instance;
public static Context sContext;
public static GreenDaoUtils getInstance(){
if(instance == null){
synchronized (GreenDaoUtils.class){
if(instance == null){
instance = new GreenDaoUtils();
}
}
}
return instance;
}
public void init(Context context){
sContext = context;
}
public void setUpdataBase(){
//创建数据库shop.db
helper = new DaoMaster.DevOpenHelper(sContext, SHOP_DB_Name, null);
//获取可写数据库
SQLiteDatabase db = helper.getWritableDatabase();
//获取数据库对象
master = new DaoMaster(db);
//获取dao对象管理者
sDaoSession = master.newSession();
}
//开启打印日志
public void initLogInfo(){
QueryBuilder.LOG_SQL = true;
QueryBuilder.LOG_VALUES = true;
}
//关闭数据库。在onDestroy方法调用。(调用这个方法会抛IllegalStateException异常)
public void closedDb(){
if(helper != null){
helper.close();
helper = null;
}
if(sDaoSession != null){
sDaoSession.clear();
sDaoSession = null;
}
}
/** 插入单个数据
* getShopDao().insert(shop);
* getShopDao().insertOrReplace(shop);
*/
public boolean insertOne(ShopBean shop){
boolean insertFlag = sDaoSession.getShopBeanDao().insert(shop) == -1 ? false : true;
return insertFlag;
}
public boolean insertOrReplaceOne(ShopBean shopBean){
boolean insertOrReplaceFlag = sDaoSession.getShopBeanDao().insertOrReplace(shopBean) == -1 ? false : true;
return insertOrReplaceFlag;
}
/** 插入多个数据
* getShopDao().insertInTx(shopList);
* getShopDao().insertOrReplaceInTx(shopList);
*/
public boolean insertManyData(List<ShopBean> shopList){
boolean insertManyFlag = false;
try{
sDaoSession.getShopBeanDao().insertInTx(shopList);
insertManyFlag = true;
}catch (Exception e){
Log.i("TAG", "insertManyData: e.printStackTrace()" + e);
}
return insertManyFlag;
}
public boolean insertInTxManyData(List<ShopBean> shopList){
boolean insertInTxFlag = false;
try {
sDaoSession.getShopBeanDao().insertOrReplaceInTx(shopList);
insertInTxFlag = true;
}catch (Exception e){
Log.i("TAG", "insertInTxManyData: e.printStackTrace()" + e);
}
return insertInTxFlag;
}
/** 查询全部
* List< Shop> list = getShopDao().loadAll();
* List< Shop> list = getShopDao().queryBuilder().list();
*/
public List<ShopBean> querryAll(){
List<ShopBean> list = new ArrayList<>();
try{
list = sDaoSession.getShopBeanDao().loadAll();
Log.i("TAG", "queryBuilder查询到的数据长度 list.size() ==" + list.size());
}catch (Exception e){
Log.i("TAG", "querryAll: e.printStackTrace()" + e);
}
return list;
}
public List<ShopBean> queryBuilder(){
List<ShopBean> list = new ArrayList<>();
try{
list = sDaoSession.getShopBeanDao().queryBuilder().list();
Log.i("TAG", "queryBuilder查询到的数据长度 list.size() ==" + list.size());
}catch (Exception e){
Log.i("TAG", "queryBuilder: e.printStackTrace()" + e);
}
return list;
}
/** 查询总个数
* .count()
*/
public long querryCount(){
long count = 0;
try{
count = sDaoSession.getShopBeanDao().count();
Log.i("TAG", "querryCount查询到的总个数count ==" + count);
}catch (Exception e){
Log.i("TAG", "querryCount: e.printStackTrace()" + e);
}
return count;
}
/**
* 修改单个数据
* getShopDao().update(shop);
*/
public boolean updateOneData(ShopBean shop){
boolean updateOneFlag = false;
try{
sDaoSession.getShopBeanDao().update(shop);
updateOneFlag = true;
}catch (Exception e){
Log.i("TAG", "updateOneData: e.printStackTrace()" + e);
}
return updateOneFlag;
}
/**
* 修改多个数据
* getShopDao().updateInTx(shopList);
*/
public boolean updateList(List<ShopBean> list){
boolean updateListFlag = false;
try{
sDaoSession.getShopBeanDao().updateInTx(list);
updateListFlag = true;
}catch (Exception e){
Log.i("TAG", "updateList: e.printStackTrace()" + e);
}
return updateListFlag;
}
/**
* 删除单个数据
* getTABUserDao().delete(user);
*/
public boolean deleteOneData(ShopBean shop){
boolean deleteOneFlag = false;
try{
sDaoSession.getShopBeanDao().delete(shop);
deleteOneFlag = true;
}catch (Exception e){
Log.i("TAG", "deleteOneData: e.printStackTrace()" + e);
}
return deleteOneFlag;
}
/**
* 删除多个数据
* getUserDao().deleteInTx(userList);
*/
public boolean deleteDataList(List<ShopBean> list){
boolean deleteDataFlag = false;
try{
sDaoSession.getShopBeanDao().deleteInTx(list);
deleteDataFlag = true;
}catch (Exception e){
Log.i("TAG", "deleteDataList: e.printStackTrace()" + e);
}
return deleteDataFlag;
}
/**
* 删除全部
*/
public boolean deleteAll(){
boolean deleteAllFlag = false;
try{
sDaoSession.getShopBeanDao().deleteAll();
deleteAllFlag = true;
}catch (Exception e){
Log.i("TAG", "deleteAll: e.printStackTrace()" + e);
}
return deleteAllFlag;
}
/**
* 按照Key值删除某一个
*/
public boolean deleteByKey(Long key){
boolean deleteByKeyFlag = false;
try{
sDaoSession.getShopBeanDao().deleteByKey(key);
deleteByKeyFlag = true;
}catch (Exception e){
Log.i("TAG", "deleteByKey: e.printStackTrace()" + e);
}
return deleteByKeyFlag;
}
/**
* 按照Key批量删除
*/
public boolean deleteByKeyList(List<Long> list){
boolean deleteByKeyListFlag = false;
try{
sDaoSession.getShopBeanDao().deleteByKeyInTx(list);
deleteByKeyListFlag = true;
}catch (Exception e){
Log.i("TAG", "deleteByKeyList: e.printStackTrace()" + e);
}
return deleteByKeyListFlag;
}
/**
* 按照Id的范围查找
* @param starPostion
* @param endPosition
* @param ccount
* @return
*/
public List<ShopBean> queryById(int starPostion, int endPosition, int ccount){
List<ShopBean> querryList = sDaoSession.getShopBeanDao().queryBuilder()
.where(ShopBeanDao.Properties.Id.between(starPostion, endPosition))
.limit(ccount).build().list();
return querryList;
}
/**
* 查询某个表是否包含某个id
* @param ID
* @return
*/
public boolean isContainId(Long ID){
QueryBuilder<ShopBean> queryBuilder = sDaoSession.getShopBeanDao().queryBuilder();
queryBuilder.where(ShopBeanDao.Properties.Id.eq(ID));
queryBuilder.buildCount().count();
return queryBuilder.buildCount().count() > 0 ? true : false;
}
/**
* 按照name查找(字符串的查找皆可用这个)
* @param querryChar
* @return
*/
public List<ShopBean> querryByCharacter(String querryChar){
List<ShopBean> querryNameList = sDaoSession.getShopBeanDao().queryBuilder()
.where(ShopBeanDao.Properties.MerchantAddress.eq(querryChar))
// .orderAsc(ShopBeanDao.Properties.SellNumber)//按照***属性排序
.list();
return querryNameList;
}
}
使用的时候,在Activity中,先在onCreate方法里面获取GreenDaoUtils对象:
mDaoUtils = GreenDaoUtils.getInstance();//获取Utils对象
然后依次调用以下方法:
mDaoUtils .init(this);//实例化注册
mDaoUtils .setUpdataBase();//数据库创建
mDaoUtils .initLogInfo();//日志打印开关
然后便可以开始进行数据库的相关操作。
我们先来体验下效果:
1、原始状态:
private void initData() {
mShopBeanList = mDaoUtils.querryAll();
if (mShopBeanList == null || mShopBeanList.size() <= 0) {
mShopBeanList = mDaoUtils.queryBuilder();
if (mShopBeanList == null || mShopBeanList.size() <= 0) {
for (int i = 0; i < 6; i++) {
ShopBean shop = new ShopBean();
shop.setId(null);
shop.setName(name[i]);
shop.setPrice((i + 15) * 133 / 28 + "");
shop.setSellNumber((i + 10) * 359);
shop.setImageUrl(imageUrl[i]);
int mod = i % 2;
shop.setMerchantAddress(address[mod]);
if (mod == 1) {
shop.setType(ShopBean.COLLECTION);
} else if (mod == 0) {
shop.setType(ShopBean.SHOPCART);
}
mShopBeanList.add(shop);
}
}
}
mDaoAdapter = new GreenDaoAdapter(GreenDaoActivity.this, mShopBeanList);
FullyLinearLayoutManager layoutManager = new FullyLinearLayoutManager(GreenDaoActivity.this);
layoutManager.setOrientation(LinearLayoutManager.VERTICAL);
mRvGreenDao.setLayoutManager(layoutManager);
mRvGreenDao.addItemDecoration(new RecycleViewDividerSegmentate(this, LinearLayoutManager.VERTICAL));
mRvGreenDao.setAdapter(mDaoAdapter);
}
2、插入单个数据insertOne和insertOrReplaceOne,二者执行的结果都是一样的:
private void insertOne(){
ShopBean insertOne = new ShopBean();
insertOne.setId(null);
insertOne.setName("btinsertOne");
insertOne.setPrice("¥208");
insertOne.setSellNumber(37958);
insertOne.setImageUrl(imageUrl[6]);
insertOne.setMerchantAddress(address[1]);
insertOne.setType(ShopBean.SHOPCART);
mDaoUtils.insertOne(insertOne);
mShopBeanList = mDaoUtils.querryAll();
mDaoAdapter.refreshData(mShopBeanList);
}
!
private void insertOrReplaceOne(){
ShopBean insertOrReplace = new ShopBean();
insertOrReplace.setId(null);
insertOrReplace.setName("btinsertOrReplaceOne");
insertOrReplace.setPrice("¥208");
insertOrReplace.setSellNumber(37958);
insertOrReplace.setImageUrl(imageUrl[6]);
insertOrReplace.setMerchantAddress(address[1]);
insertOrReplace.setType(ShopBean.SHOPCART);
mShopBeanList = mDaoUtils.querryAll();
mDaoAdapter.refreshData(mShopBeanList);
}
3、批量插入数据insertManyData和insertInTxManyData:
private void insertManyData(){
for (int i = 0; i < 6; i++) {
ShopBean shop = new ShopBean();
shop.setId(null);
shop.setName(address[2] + "**" + name[i]);
shop.setPrice((i + 15) * 1330 + "");
shop.setSellNumber((i + 10) * 3590);
shop.setImageUrl(imageUrl[i]);
int mod = i % 2;
shop.setMerchantAddress(address[2]);
if (mod == 1) {
shop.setType(ShopBean.COLLECTION);
} else if (mod == 0) {
shop.setType(ShopBean.SHOPCART);
}
mShopBeanList.add(shop);
}
mDaoUtils.insertManyData(mShopBeanList);
mShopBeanList = mDaoUtils.querryAll();
mDaoAdapter.refreshData(mShopBeanList);
}
insertManyData方法执行时无效,数据插入失败,insertInTxManyData是可以成功插入数据的。
private void insertInTxManyData(){
for (int i = 0; i < 6; i++) {
ShopBean shop = new ShopBean();
shop.setId(null);
shop.setName(address[2] + "*||||||*" + name[i]);
shop.setPrice((i + 15) * 1330 + "");
shop.setSellNumber((i + 10) * 3590);
shop.setImageUrl(imageUrl[i]);
int mod = i % 2;
shop.setMerchantAddress(address[2]);
if (mod == 1) {
shop.setType(ShopBean.COLLECTION);
} else if (mod == 0) {
shop.setType(ShopBean.SHOPCART);
}
mShopBeanList.add(shop);
}
mDaoUtils.insertInTxManyData(mShopBeanList);
mShopBeanList = mDaoUtils.querryAll();
mDaoAdapter.refreshData(mShopBeanList);
}
4、查询所有数据queryBuilder和querryAll:
Log.i("TAG", "querryAll().size ===" + mDaoUtils.querryAll().size());
Log.i("TAG", "queryBuilder().size ===" + mDaoUtils.queryBuilder().size());
5、查询数据库数据总量querryCount:
Log.i("TAG", "qquerryCount ===" + mDaoUtils.querryCount());
6、更新单条数据updateOneData:
private void updateOneData(){
//获取要更新的数据对象
ShopBean shopBean = mShopBeanList.get(0);
//设置更新的内容
shopBean.setName("秋水浮萍任缥缈");
//更新数据集合
boolean updateOneFlag = mDaoUtils.updateOneData(shopBean);
//获取更新后的所有数据并加载出来
mShopBeanList = mDaoUtils.querryAll();
mDaoAdapter.refreshData(mShopBeanList);
}
7、批量更新数据updateList:
private void updateList(){
//获取要更新的数据对象
ShopBean shopBean1 = mShopBeanList.get(1);
ShopBean shopBean2 = mShopBeanList.get(2);
ShopBean shopBean3 = mShopBeanList.get(3);
//设置更新的内容
shopBean1.setName("俏如来");
shopBean2.setName("宫本总司");
shopBean3.setName("剑无极");
List<ShopBean> updateList = new ArrayList<>();
updateList.add(shopBean1);
updateList.add(shopBean2);
updateList.add(shopBean3);
//更新数据集合
boolean updateListFlag = mDaoUtils.updateList(updateList);
//获取更新后的所有数据并加载出来
mShopBeanList = mDaoUtils.querryAll();
mDaoAdapter.refreshData(mShopBeanList);
}
8、批量删除数据deleteDataList:
private void deleteDataList(){
//获取要删除的数据对象
ShopBean deleteList01 = mShopBeanList.get(6);
ShopBean deleteList02 = mShopBeanList.get(7);
List<ShopBean> deleteList = new ArrayList<>();
deleteList.add(deleteList01);
deleteList.add(deleteList02);
//删除数据集合
boolean deleteLstFlag = mDaoUtils.deleteDataList(deleteList);
//查询删除后剩余的所有数据并加载出来
mShopBeanList = mDaoUtils.querryAll();
mDaoAdapter.refreshData(mShopBeanList);
}
9、删除某一条数据deleteOneData:
private void deleteOneData(){
//获取最后一条数据
ShopBean deleteOne = mShopBeanList.get((int) mDaoUtils.querryCount() - 1);
//删除最后一条数据
boolean deleteOneFlag = mDaoUtils.deleteOneData(deleteOne);
//查询删除后剩余的所有数据并加载出来
mShopBeanList = mDaoUtils.querryAll();
mDaoAdapter.refreshData(mShopBeanList);
}
10、删除所有数据deleteAll:执行该方法后,所有数据将被删除
boolean deleteAllFlag = mDaoUtils.deleteAll();
以下几个方法亲测有效,可以直接使用:
a、按照Id的范围查找
public List<ShopBean> queryById(int starId, int endId, int ccount){
List<ShopBean> querryList = sDaoSession.getShopBeanDao().queryBuilder()
.where(ShopBeanDao.Properties.Id.between(starPostion, endPosition))
.limit(ccount).build().list();
return querryList;
}
其中starId表示查找的起始Id,endId表示查找的结束Id,ccount表示输出多少个。
b、查询某个表是否包含某个id
public boolean isContainId(Long ID){
QueryBuilder<ShopBean> queryBuilder = sDaoSession.getShopBeanDao()
.queryBuilder();
queryBuilder.where(ShopBeanDao.Properties.Id.eq(ID));
queryBuilder.buildCount().count();
return queryBuilder.buildCount().count() > 0 ? true : false;
}
c、按照name查找(字符串的查找皆可用这个)
public List<ShopBean> querryByCharacter(String querryChar){
List<ShopBean> querryNameList = sDaoSession.getShopBeanDao()
.queryBuilder().where(ShopBeanDao.Properties.MerchantAddress
.eq(querryChar))
// .orderAsc(ShopBeanDao.Properties.SellNumber)//按照***属性排序
.list();
return querryNameList;
}
上面注销的部分:按照*属性排序,这个可以按照需要添加,不需要也可以忽略。