前言:
最近在项目开发中使用到了android 数据库相关的操作,为了提高数据库的操作效率,研究了GreenDao ORM架构,
项目中主要使用了GreenDAO 框架对数据的存储与查询,以及数据库的升级。
下面我将会从GreenDAO 简介到我项目中使用时遇到的问题进行讲解,有什么不对的地方还请指点。
一、greenDAO介绍:
greenDAO为 Android开发者 提供了一种 快速将Java对象映射到SQLite数据库的表单中的ORM解决方案,通过使用一个简单的面向对象API,开发者可以很方便的进行增删改查,从而很大程度的提高了开发效率
二 、GreenDAO 主要的设计目标:
1、性能最大化(对象 数据库之间转换更快速)
2、易于使用的API
3、在android系统上进行了高度优化
4、占用较小内存空间
5、精简包大小
三、GreenDAO 使用
1、下载源码git: 点击打开链接
源码结构:
DAOExample :Android 示例工程
DAOCore :GreenDao 库工程,为greendao.jar 源码
DaoExampleGenerator Dao类构造器案例 后面会详细介绍如何进行表格的创建
DaoGenerator Dao类构造器 核心库
DaoTest 单元测试
2、数据模型的构造以及代码的生成
可以参看DaoExampleGenerator示例工程(java 项目)
ExampleDaoGenerator类源码如下:
/*
* Copyright (C) 2011 Markus Junginger, greenrobot (http://greenrobot.de)
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package de.greenrobot.daogenerator.gentest ;
import de.greenrobot.daogenerator.DaoGenerator ;
import de.greenrobot.daogenerator.Entity ;
import de.greenrobot.daogenerator.Property ;
import de.greenrobot.daogenerator.Schema ;
import de.greenrobot.daogenerator.ToMany ;
/**
* Generates entities and DAOs for the example project DaoExample.
*
* Run it as a Java application (not Android).
*
* @author Markus
*/
public class ExampleDaoGenerator {
public static void main (String[] args) throws Exception {
Schema schema = new Schema( 1, "de.greenrobot.daoexample" ) ;
addNote(schema) ;
addCustomerOrder(schema) ;
new DaoGenerator().generateAll(schema , "../DaoExample/src/main/java" ) ;
}
private static void addNote (Schema schema) {
Entity note = schema.addEntity("Note" ) ;
note.addIdProperty() ;
note.addStringProperty( "text" ).notNull();
note.addStringProperty( "comment" );
note.addDateProperty( "date" );
}
private static void addCustomerOrder (Schema schema) {
Entity customer = schema.addEntity( "Customer") ;
customer.addIdProperty() ;
customer.addStringProperty( "name" ).notNull();
Entity order = schema.addEntity( "Order" );
order.setTableName( "ORDERS" ); // "ORDER" is a reserved keyword
order.addIdProperty() ;
Property orderDate = order.addDateProperty("date" ).getProperty() ;
Property customerId = order.addLongProperty("customerId" ).notNull().getProperty() ;
order.addToOne(customer , customerId);
ToMany customerToOrders = customer.addToMany(order, customerId) ;
customerToOrders.setName( "orders" );
customerToOrders.orderAsc(orderDate) ;
}
}
下面对该类进行讲解:
在Main 方法中
Schema schema = new Schema( 1 , "de.greenrobot.daoexample" ) ;
Schema 第一个参数 数据库版本号;第二个参数为:生成DAO类的包路径
注意:当需要进行数据库升级时,需要修改第一个参数 修改值要大于之前数据库的版本号
1、创建数据库表
Entity note = schema.addEntity("Note" ) ;
创建一个实体类,默认表名为 实体类名称'Note';
自定义表名:
note.setTableName("Note_table");
greenDAO会自动根据实体类属性创建表字段,并赋予默认值。例如在数据库方面的表名和列名都来源于实体类名和属性名。默认的数据库名称是大写使用下划线分隔单词,而不是在Java中使用的驼峰式大小写风格。例如,一个名为"StoreInfo"属性将成为一个数据库列"STORE_INFO"。
2、表的增删改查
使用GreenDao 简化了数据库语句的编写,完全面向对象,增删改查比较方便
实例初始化代码
DevOpenHelper helper = new DaoMaster.DevOpenHelper (this, "notes-db" , null );
db = helper.getWritableDatabase() ;
daoMaster = new DaoMaster( db) ;
daoSession = daoMaster .newSession() ;
noteDao = daoSession .getNoteDao() ;
创建一个数据库名称为“notes-db”的数据库
查询:
/**
* 查询表格中的全部数据
* @return
*/
public List queryAllData (){
return noteDao .queryBuilder().list();
}
/**
* 通过条件过滤查询数据
* @param date
* @return
*/
public List query4Date (Date date){
return noteDao .queryBuilder().where(NoteDao.Properties. Date.eq(date)).list() ;
}
插入:
/**
*向 Note 表格中插入一行数据
*/
public void insertNoteData (){
Note note = new Note() ;
note.setComment( " 测试" ) ;
note.setDate( new Date());
note.setId( 1L );
note.setText( " 测试GreenDao" ) ;
noteDao .insert(note) ;
}
更新:
/**
* 更新 note 表格中的一行数据
*/
public void updateNoteData (){
Note note = new Note() ;
note.setId( 1L );
note.setComment( " 测试更新 ") ;
note.setDate( new Date());
note.setText( "update" );
noteDao .update(note) ;
}
删除:
/**
* 删除一行数据
*/
public void deleteByKey (Long id) {
noteDao .deleteByKey(id) ;
}
四、数据库升级
1、上面有说到创建
Schema schema = new Schema(1, "de.greenrobot.daoexample");
第一个参数为数据库版本号,数据库升级可以配置如下:
Schema schema = new Schema(2, "de.greenrobot.daoexample");
不过会存在一个问题,之前初始化时DevOpenHelper会将所有的数据表删除,从而会导致数据库升级时数据丢失
DevOpenHelper helper = new DaoMaster.DevOpenHelper (this, "notes-db" , null );
我们来看下DevOpenHelper 这个类
package de.greenrobot.daoexample;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
import de.greenrobot.dao.AbstractDaoMaster;
import de.greenrobot.dao.identityscope.IdentityScopeType;
import de.greenrobot.daoexample.NoteDao;
import de.greenrobot.daoexample.CustomerDao;
import de.greenrobot.daoexample.OrderDao;
// THIS CODE IS GENERATED BY greenDAO, DO NOT EDIT.
/**
* Master of DAO (schema version 1): knows all DAOs.
*/
public class DaoMaster extends AbstractDaoMaster {
public static final int SCHEMA_VERSION = 1;
/** Creates underlying database table using DAOs. */
public static void createAllTables(SQLiteDatabase db, boolean ifNotExists) {
NoteDao.createTable(db, ifNotExists);
CustomerDao.createTable(db, ifNotExists);
OrderDao.createTable(db, ifNotExists);
}
/** Drops underlying database table using DAOs. */
public static void dropAllTables(SQLiteDatabase db, boolean ifExists) {
NoteDao.dropTable(db, ifExists);
CustomerDao.dropTable(db, ifExists);
OrderDao.dropTable(db, ifExists);
}
public static abstract class OpenHelper extends SQLiteOpenHelper {
public OpenHelper(Context context, String name, CursorFactory factory) {
super(context, name, factory, SCHEMA_VERSION);
}
@Override
public void onCreate(SQLiteDatabase db) {
Log.i("greenDAO", "Creating tables for schema version " + SCHEMA_VERSION);
createAllTables(db, false);
}
}
/** WARNING: Drops all table on Upgrade! Use only during development. */
public static class DevOpenHelper extends OpenHelper {
public DevOpenHelper(Context context, String name, CursorFactory factory) {
super(context, name, factory);
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
Log.i("greenDAO", "Upgrading schema from version " + oldVersion + " to " + newVersion + " by dropping all tables");
dropAllTables(db, true);
onCreate(db);
}
}
public DaoMaster(SQLiteDatabase db) {
super(db, SCHEMA_VERSION);
registerDaoClass(NoteDao.class);
registerDaoClass(CustomerDao.class);
registerDaoClass(OrderDao.class);
}
public DaoSession newSession() {
return new DaoSession(db, IdentityScopeType.Session, daoConfigMap);
}
public DaoSession newSession(IdentityScopeType type) {
return new DaoSession(db, type, daoConfigMap);
}
}
DevOpenHelper 类注释上明确说明了(Drops all table on Upgrade! Use only during development)
意思是说,在数据库更新时 使用DevOpenHelper 会将数据表格删除 本地数据被清空;我们看代码也很容易知道,在onUpgrade方法中 调用了
dropAllTables(db, true); 方法 删除所有表。
数据库升级 创建一个Helper类继承 OpenHelper
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import java.util.Set;
import java.util.SortedMap;
import java.util.TreeMap;
import de.greenrobot.dao.DaoMaster;
/***
* 数据库升级使用
*/
public class SQLiteOpenHelper extends DaoMaster.OpenHelper {
private static final SortedMap ALL_VERSION = new TreeMap<>();
static {
ALL_VERSION.put(1, new V1DatabaseUpgrade());
}
public SQLiteOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory) {
super(context, name, factory);
}
@Override
public void onCreate(SQLiteDatabase db) {
super.onCreate(db);
}
@Override
public void onUpgrade(SQLiteDatabase sqLiteDatabase, int oldVersion, int newVersion) {
SortedMap migrations = ALL_VERSION.subMap(oldVersion, newVersion);
executeMigrations(sqLiteDatabase, migrations.keySet());
}
private void executeMigrations(final SQLiteDatabase paramSQLiteDatabase, final Set
migrationVersions) {
for (final Integer version : migrationVersions) {
ALL_VERSION.get(version).onUpgrade(paramSQLiteDatabase);
}
}
}
interface DatabaseUpgrade {
void onUpgrade(SQLiteDatabase db);
}
/**
* 版本升级
*/
class V1DatabaseUpgrade implements DatabaseUpgrade {
@Override
public void onUpgrade(SQLiteDatabase db) {
try{
db.execSQL("ALTER TABLE NOTE ADD COLUMN TEST INTEGER DEFAULT -1");
}catch (Exception e){
}
}
}
这样在 不同版本继承不同的DatabaseUpgrade 接口,对数据库升级根据业务的需要做不同的处理。