GreenDAO是一种Android数据ORM(object/relational mapping)框架,与OrmLite、ActiveOrm、LitePal等数据库相比,单位时间内可以插入、更新和查询更多的数据,而且提供了大量的灵活通用接口。GreenDAO的效率之高主要是因为GreenDAO所采用的实现方式是生成代码而不是使用注解反射之类的手段。
项目gradle配置文件:
在dependcies中添加
classpath 'org.greenrobot:greendao-gradle-plugin:3.1.0'
app Module中的gradle文件中:
添加plugin: 'org.greenrobot.greendao'
到apply plugin: 'com.android.application'
下。
再在android标签中添加:
greendao{
schemaVersion 1
targetGenDir 'src/main/java'
}
在dependencies中添加:
compile 'org.greenrobot:greendao:3.1.0'
至此完成了GreenDAO的配置。
使用GreenDAO首先要创建一个基本的model类,然后再编译让GreenDAO框架去生成对应的数据库操作代码。
下面以一个日记类为例:
@Entity
public class Daily {
@Id(autoincrement = true)
private Long id;
@Property(nameInDb = "title")
private String mTitle;
@Property(nameInDb = "content")
private String mContent;
@Property(nameInDb = "create_time")
private Long mCreateTime;
public Long getMCreateTime() {
return this.mCreateTime;
}
public void setMCreateTime(Long mCreateTime) {
this.mCreateTime = mCreateTime;
}
public String getMContent() {
return this.mContent;
}
public void setMContent(String mContent) {
this.mContent = mContent;
}
public String getMTitle() {
return this.mTitle;
}
public void setMTitle(String mTitle) {
this.mTitle = mTitle;
}
public Long getId() {
return this.id;
}
public void setId(Long id) {
this.id = id;
}
}
其中@Entity,@Property,@Id(autoincrement = true)等是一些GreenDAO的注解。
@Entity代表生成一张表
@Id(autoincrement = true)代表该属性是主键,并且自增长
@Property代表数据库表中的列,括号内的nameInDb代表该列名称。nameInDb可写可不写,不写则该列名称和属性名称相同(表中列名称为大写字母)
接下来使用Android Studio中的Build->Make Project,编译完后会生成对应的DailyDao,DaoMaster,DaoSession等几个类
并且Daily类中也会自动生成构造函数
@Generated(hash = 1714517534)
public Daily(Long id, String mTitle, String mContent, Long mCreateTime) {
this.id = id;
this.mTitle = mTitle;
this.mContent = mContent;
this.mCreateTime = mCreateTime;
}
@Generated(hash = 2135515054)
public Daily() {
}
值得注意的是构造函数上面都有一个hash值,该值在更新数据库表结构的时候要去掉。
使用GreenDao的主要代码如下:
DaoMaster.DevOpenHelper devOpenHelper = new DaoMaster.DevOpenHelper(context, "daily.db");
DaoMaster daoMaster = new DaoMaster(devOpenHelper.getWritableDb());
DaoSession daoSession = daoMaster.newSession();
mDailyDao = daoSession.getDailyDao();
//插入数据
mDailyDao.insert(daily);
//更新数据
mDailyDao.update(daily);
//删除数据
mDailyDao.delete(daily);
//通过id查询数据
mDailyDao.queryBuilder().where(DailyDao.Properties.Id.eq(id)).unique();
//查询所有数据
mDailyDao.queryBuilder().list();
但真正使用框架时我们不要直接调用框架的类,最好的做法是多封装一层。因此写一个数据库Helper类比较好。如下:
import android.content.Context;
import java.util.List;
/**
* Created by xin on 2018/3/26.
*/
public class DatabaseHelper {
private DailyDao mDailyDao;
private static DatabaseHelper sInstance;
private DatabaseHelper(Context context){
DaoMaster.DevOpenHelper devOpenHelper = new DaoMaster.DevOpenHelper(context, "daily.db");
DaoMaster daoMaster = new DaoMaster(devOpenHelper.getWritableDb());
DaoSession daoSession = daoMaster.newSession();
mDailyDao = daoSession.getDailyDao();
}
public static DatabaseHelper getInstance(Context context){
if (sInstance == null){
sInstance = new DatabaseHelper(context);
}
return sInstance;
}
public void insertDaily(Daily daily){
mDailyDao.insert(daily);
}
public void updateDaily(Daily daily){
mDailyDao.update(daily);
}
public void deleteDaily(Daily daily){
mDailyDao.delete(daily);
}
public Daily queryDailyById(int id){
return mDailyDao.queryBuilder().where(DailyDao.Properties.Id.eq(id)).unique();
}
public List listAllDaily(){
return mDailyDao.queryBuilder().list();
}
}
并且注意,该单例类中初始化时传入的Context最好是Application的Context,因为初始化后会被一直持有,如果传入的是Activity的Context,会造成内存泄漏。
但是每次使用都要注意去传入Application的Context,是一件麻烦的事情,不如在初始化时传入就好。
因此修改为如下写法:
public class DatabaseHelper {
private static Context sContext;
private DailyDao mDailyDao;
private static DatabaseHelper sInstance;
private DatabaseHelper(Context context){
DaoMaster.DevOpenHelper devOpenHelper = new DaoMaster.DevOpenHelper(context, "daily.db");
DaoMaster daoMaster = new DaoMaster(devOpenHelper.getWritableDb());
DaoSession daoSession = daoMaster.newSession();
mDailyDao = daoSession.getDailyDao();
}
public static void init(Context context){
if(sInstance == null){
sContext = context;
}
}
public static DatabaseHelper getInstance(){
if (sInstance == null){
sInstance = new DatabaseHelper(sContext);
}
return sInstance;
}
public void insertDaily(Daily daily){
mDailyDao.insert(daily);
}
public void updateDaily(Daily daily){
mDailyDao.update(daily);
}
public void deleteDaily(Daily daily){
mDailyDao.delete(daily);
}
public Daily queryDailyById(long id){
return mDailyDao.queryBuilder().where(DailyDao.Properties.Id.eq(id)).unique();
}
public List listAllDaily(){
return mDailyDao.queryBuilder().list();
}
}
使用时,在自定义的Applicaion类中初始化DatabaseHelper的Context.
public class DailyApp extends Application {
@Override
public void onCreate() {
super.onCreate();
//将ApplicationContext传入到帮助类中
DatabaseHelper.init(this);
DatabaseHelper.getInstance();
}
}
之后再使用DatabaseHelper中的增删改查等方法。
修改表结构,比如添加一个属性。
添加完成后升级数据库操作如下:
去掉Daily类中的构造函数上的@Generated(hash = 2135515054)
等内容。
修改app的gradle中配置的数据库版本:
greendao{
schemaVersion 2
targetGenDir 'src/main/java'
}
比如将1修改为2,这时候再编译项目,就会生成新的对应的类了
注意:GreenDao更新数据库操作默认会删除掉数据库数据
在生成的DaoMaster类中可看到如下代码:
@Override
public void onUpgrade(Database db, int oldVersion, int newVersion) {
Log.i("greenDAO", "Upgrading schema from version " + oldVersion + " to " + newVersion + " by dropping all tables");
dropAllTables(db, true);
onCreate(db);
}
可看到升级数据库操作时会删除所有表格,然后再创建新的表格。如果在开发阶段还不存在问题。但在真正应用上这段逻辑肯定是要自行修改的。