GreenDao学习
官网:http://greenrobot.org/greendao/
ORM: object Relationnal Mapping,即关系对象映射,他的思想就是将关系数据库中表的数据映射成对象,以对象的形式呈现,这样开发人员就可以将数据的操作转化为对象的操作,。因此它的目的是方便开发人员以面向对象的思想实现数据库的操作
一、GreenDao是什么?
GreenDAO是一个开源的安卓ORM框架,能够使SQLite数据库的开发再次变得有趣。它减轻开发人员处理低级数据库需求,同时节省开发时间。 SQLite是一个令人敬畏的内嵌的关系数据库,编写SQL和解析查询结果是相当乏味和耗时的任务。通过将Java对象映射到数据库表(称为ORM,“对象/关系映射”),GreenDAO可以将它们从这些映射中释放出来,这样,您可以使用简单的面向对象的API来存储,更新,删除和查询数据库。
简单的讲,GreenDAO 是一个将对象映射到 SQLite 数据库中的轻量且快速的 ORM 解决方案。
二、greenDAO’s Features at a glance(GreenDao优点)
Maximum performance(最优性能): (probably the fastest ORM for Android); our benchmarks are open sourced too
Easy to use(便于使用): powerful APIs covering relations and joins
Minimal(低消耗): memory consumption
Small(空间小): library size (<100KB) to keep your build times low and to avoid the 65k method limit
Database encryption(数据加密): greenDAO supports SQLCipher to keep your user’s data safe
Strong community(强壮的社区): More than 5.000 GitHub stars show there is a strong and active community
三、GreenDao配置
1、添加依赖
①In your root build.gradle file:
buildscript {
repositories {
jcenter()
mavenCentral() // add repository
}
dependencies {
classpath 'com.android.tools.build:gradle:2.3.0'
classpath 'org.greenrobot:greendao-gradle-plugin:3.2.2' // add plugin
}
}
②In your app projects build.gradle file:
apply plugin: 'com.android.application'
apply plugin: 'org.greenrobot.greendao' // apply plugin
greendao {
schemaVersion 1
daoPackage '包名.gen'
targetGenDir 'src/main/java'
}
dependencies {
compile 'org.greenrobot:greendao:3.2.2' // add library
}
schemaVersion:指定数据库schema版本号,迁移等操作会用到;
daoPackage:通过gradle插件生成的数据库相关文件的包名,默认为你的entity所在的包名;
targetGenDir:自定义生成数据库文件的目录,可以将生成的文件放到我们的java目录中,而不是build中,这样就不用额外的设置资源目录了。
2、通过GreenDao3注解的语法来定义我们的一个数据库实体类及其数据库操作方法
@Entity
public class User{
@Id(autoincrement = true)
private Long _id;
private String name;
@NotNull
private String age;
}
这里的几个注解含义:
- @Entity:将我们的java普通类变为一个能够被greenDAO识别的数据库类型的实体类;
- @nameInDb:在数据库中的名字,如不写则为实体中类名;
- @Id:选择一个long / Long属性作为实体ID。 在数据库方面,它是主键。 参数autoincrement是设置ID值自增;
- @NotNull:使该属性在数据库端成为“NOT
NULL”列。 通常使用@NotNull标记原始类型(long,int,short,byte)是有意义的 - @Transient:表明这个字段不会被写入数据库,只是作为一个普通的java类字段,用来临时存储数据的,不会被持久化。
3、通过点击AndroidStudio中的MakeProject,便发现GreenDao为我们的Meizi实体类生成了对应的Getter、Setter方法以及俩个构造函数,同时在我们配置的com.ping.greendao.gen包下生成了三个对应类文件DaoMaster、DaoSession和MeiziDao,之后所有相关的数据库操作都依靠这三个文件了;
DaoMaster:使用greenDAO的切入点。DaoMaster保存数据库对象(SQLiteDatabase)并管理特定模式的DAO类(而不是对象)。 它具有静态方法来创建表或将它们删除。 其内部类OpenHelper和DevOpenHelper是在SQLite数据库中创建模式的SQLiteOpenHelper实现。一个DaoMaster就代表着一个数据库的连接。
DaoSession:管理特定模式的所有可用DAO对象,您可以使用其中一个getter方法获取。 DaoSession还为实体提供了一些通用的持久性方法,如插入,加载,更新,刷新和删除。 DaoSession可以让我们使用一些Entity的基本操作和获取Dao操作类,DaoSession可以创建多个,每一个都是属于同一个数据库连接的。
XxxDAO:数据访问对象(DAO)持续存在并查询实体。 对于每个实体,GreenDAO生成一个DAO。 它比DaoSession有更多的持久化方法,例如:count,loadAll和insertInTx。
4、编写DaoManager,用于创建数据库、创建数据库表、包含增删改查的操作以及数据库的升级
/**
* Created by anwanfei on 2017/8/4.
* 创建数据库、创建数据库表、包含增删改查的操作以及数据库的升级
*/
public class DaoManager {
private static final String TAG = DaoManager.class.getSimpleName();
private static final String DB_NAME = "shipDetails";
private Context context;
//多线程中要被共享的使用volatile关键字修饰
private volatile static DaoManager manager = new DaoManager();
private static DaoMaster sDaoMaster;
private static DaoMaster.DevOpenHelper sHelper;
private static DaoSession sDaoSession;
/**
* 单例模式获得操作数据库对象
*
* @return
*/
public static DaoManager getInstance() {
return manager;
}
public void init(Context context) {
this.context = context;
}
/**
* 判断是否有存在数据库,如果没有则创建
*
* @return
*/
public DaoMaster getDaoMaster() {
if (sDaoMaster == null) {
DaoMaster.DevOpenHelper helper = new DaoMaster.DevOpenHelper(context, DB_NAME, null);
sDaoMaster = new DaoMaster(helper.getWritableDatabase());
}
return sDaoMaster;
}
/**
* 完成对数据库的添加、删除、修改、查询操作,仅仅是一个接口
*
* @return
*/
public DaoSession getDaoSession() {
if (sDaoSession == null) {
if (sDaoMaster == null) {
sDaoMaster = getDaoMaster();
}
sDaoSession = sDaoMaster.newSession();
}
return sDaoSession;
}
/**
* 打开输出日志,默认关闭
*/
public void setDebug() {
QueryBuilder.LOG_SQL = true;
QueryBuilder.LOG_VALUES = true;
}
/**
* 关闭所有的操作,数据库开启后,使用完毕要关闭
*/
public void closeConnection() {
closeHelper();
closeDaoSession();
}
public void closeHelper() {
if (sHelper != null) {
sHelper.close();
sHelper = null;
}
}
public void closeDaoSession() {
if (sDaoSession != null) {
sDaoSession.clear();
sDaoSession = null;
}
}
}
5 、编写XxxDaoUtil,用于完成对某一张数据表的具体操作——ORM操作
/**
* Created by anwanfei on 2017/8/4.
*/
public class ShipDetailsDaoUtil {
private static final String TAG = ShipDetailsDaoUtil.class.getSimpleName();
private DaoManager mManager;
public ShipDetailsDaoUtil(Context context) {
mManager = DaoManager.getInstance();
mManager.init(context);
}
/**
* 完成ShipDetailsBean记录的插入,如果表未创建,先创建ShipDetailsBean表
*
* @param ShipDetailsBean
* @return
*/
public boolean insertShipDetailsBean(ShipDetailsBean ShipDetailsBean) {
boolean flag = false;
flag = mManager.getDaoSession().getShipDetailsBeanDao().insert(ShipDetailsBean) == -1 ? false : true;
Log.i(TAG, "insert ShipDetailsBean :" + flag + "-->" + ShipDetailsBean.toString());
return flag;
}
/**
* 插入多条数据,在子线程操作
*
* @param ShipDetailsBeanList
* @return
*/
public boolean insertMultShipDetailsBean(final List<ShipDetailsBean> ShipDetailsBeanList) {
boolean flag = false;
try {
mManager.getDaoSession().runInTx(new Runnable() {
@Override
public void run() {
for (ShipDetailsBean ShipDetailsBean : ShipDetailsBeanList) {
mManager.getDaoSession().insertOrReplace(ShipDetailsBean);
}
}
});
flag = true;
} catch (Exception e) {
e.printStackTrace();
}
return flag;
}
/**
* 修改一条数据
*
* @param ShipDetailsBean
* @return
*/
public boolean updateShipDetailsBean(ShipDetailsBean ShipDetailsBean) {
boolean flag = false;
try {
mManager.getDaoSession().update(ShipDetailsBean);
flag = true;
} catch (Exception e) {
e.printStackTrace();
}
return flag;
}
/**
* 删除单条记录
*
* @param ShipDetailsBean
* @return
*/
public boolean deleteShipDetailsBean(ShipDetailsBean ShipDetailsBean) {
boolean flag = false;
try {
//按照id删除
mManager.getDaoSession().delete(ShipDetailsBean);
flag = true;
} catch (Exception e) {
e.printStackTrace();
}
return flag;
}
/**
* 删除所有记录
*
* @return
*/
public boolean deleteAll() {
boolean flag = false;
try {
//按照id删除
mManager.getDaoSession().deleteAll(ShipDetailsBean.class);
flag = true;
} catch (Exception e) {
e.printStackTrace();
}
return flag;
}
/**
* 查询所有记录
*
* @return
*/
public List<ShipDetailsBean> queryAllShipDetailsBean() {
return mManager.getDaoSession().loadAll(ShipDetailsBean.class);
}
/**
* 根据主键id查询记录
*
* @param key
* @return
*/
public ShipDetailsBean queryShipDetailsBeanById(long key) {
return mManager.getDaoSession().load(ShipDetailsBean.class, key);
}
/**
* 使用native sql进行查询操作
*/
public List<ShipDetailsBean> queryShipDetailsBeanByNativeSql(String sql, String[] conditions) {
return mManager.getDaoSession().queryRaw(ShipDetailsBean.class, sql, conditions);
}
/**
* 使用queryBuilder进行查询
*
* @return
*/
public List<ShipDetailsBean> queryShipDetailsBeanByQueryBuilder(String id) {
QueryBuilder<ShipDetailsBean> queryBuilder = mManager.getDaoSession().queryBuilder(ShipDetailsBean.class);
return queryBuilder.where(ShipDetailsBeanDao.Properties.ShipName.eq(id)).list();
}
/**
* 模糊查询
*
* @param value
* @return
*/
public List<ShipDetailsBean> getCarsByLike(String value) {
return mManager.getDaoSession().queryBuilder(ShipDetailsBean.class).where(ShipDetailsBeanDao.Properties.ShipName.like("%" + value + "%")).list();
}
}
/**
* 多条件模糊查询
*
* @param value
* @return
*/
public List<ShipDetailsBean> getShipsByLike(String value) {
return mManager.getDaoSession().queryBuilder(ShipDetailsBean.class)
.whereOr(ShipDetailsBeanDao.Properties.ShipName.like("%" + value + "%"), ShipDetailsBeanDao.Properties.Mmsi.like("%" + value + "%")).list();
}
三、代码中调用XXXUtils进行增删改查
①单个插入操作: mUserDaoUtils.insertMeizi(new User(null, "an","28"));
②批量插入操作:
List<User> users= new ArrayList<>();
users.add(new User(null, "an","28"));
users.add(new User(null, "an","28"));
users.addnew User(null, "an","28"));
mUserDaoUtils.insertMultUser(users);
③单个更改操作:(其中原有的数据都不会保存,如果新建的对象有属性没有设置,则会为空,不为空的字段没有设置,则报错)
User user= new User();
user.set_id(1002l);
user.setName("fei");
mUserDaoUtils.updateUser(user);
④删除某条记录操作
User user= new User();
user.set_id(1002l);
mUserDaoUtils.deleteUser(user);
⑤删除所有记录操作
mUserDaoUtils.deleteAll();
⑥查询所有记录
mUserDaoUtils.queryMeiziById(1008l).toString();
⑦根据主键查询记录
List<User> UserList = mUserDaoUtils.queryAllMeizi();
⑧各种条件查询:使用native sql进行条件查询:
String sql = "where _id > ?";
String[] condition = new String[]{"1008"};
List<User> UserList = mUserDaoUtils.queryUsrByNativeSql(sql, condition);
⑨使用queryBuilder进行条件查询
QueryBuilder能够让你在不涉及SQL语句的情况下查询实体。写SQL有几个缺点,首先是易错的,其次是要在运行时才知道有没有问题(假如属性名是pid,你写成了id,也要到运营时才会崩溃),QueryBuilder能够在编译时检查错误(如属性的引用是否错误)。
关于Api:在org.greenrobot.greendao.query包下,QueryBuilder类中查看其方法;构造函数可以传递我们的Xxx实体类型,查询方法有很多逻辑的where方法。where方法中需要设置WhereCondition类型的条件参数,而在org.greenrobot.greendao包下的Property类中,每一种操作符的方法都返回WhereCondition类型。获取Property实例则不需要我们去做,在我们的XxxDao中已经有对应的提供,例如我们这里的MeiziDao.Properties.XXX。
List<User> UserList = mUserDaoUtils.queryMeiziByQueryBuilder(1008);
LazyList懒加载是指一次性查完数据保存在内存中,然后关闭所有连接,再次查询时从内存中获取。一般查询大数据量时用。
三、参考:http://blog.csdn.net/bskfnvjtlyzmv867/article/details/71250101