一、环境配置
1、在Android Studio中,在.src/main目录下新建一个java-gen文件夹,和java文件夹同级。用于存放greenDAO生成的DaoMaster、DaoSession、Table、TableDaoSession实体类。
2、配置项目的app.gradle文件,指定java-gen文件,引入greenDAO第三方jar包
sourceSets {
main {
java.srcDirs = ['src/main/java', 'src/main/java-gen']
}
}
compile 'de.greenrobot:greendao:1.3.7'
3、新建一个greengenerator模块,用于代码自动生成DaoMaster、DaoSession、Table、TableDao实体类
配置新建moudle的build.gradle文件
compile 'de.greenrobot:greendao-generator:1.3.1'
至此,greenDAO的环境配置就完成了。
二、利用greedgenerater模块生成DaoMaster、DaoSession、Table、TableDao实体类的代码,编写moudle下的MyClass类
import de.greenrobot.daogenerator.DaoGenerator;
import de.greenrobot.daogenerator.Entity;
import de.greenrobot.daogenerator.Schema;
public class MyClass {
public static void main(String[] args) throws Exception {
// 正如你所见的,你创建了一个用于添加实体(Entity)的模式(Schema)对象。
// 两个参数分别代表:数据库版本号与自动生成代码的包路径。
Schema schema = new Schema(1, "test.greendao");
// 当然,如果你愿意,你也可以分别指定生成的 Bean 与 DAO 类所在的目录,只要如下所示:
// Schema schema = new Schema(1, "test.greendao.bean");
// schema.setDefaultJavaPackageDao("test.greendao.dao");
// 模式(Schema)同时也拥有两个默认的 flags,分别用来标示 entity 是否是 activie 以及是否使用 keep sections。
// schema2.enableActiveEntitiesByDefault();
// schema2.enableKeepSectionsByDefault();
// 一旦你拥有了一个 Schema 对象后,你便可以使用它添加实体(Entities)了。
addNote(schema);
// 最后我们将使用 DAOGenerator 类的 generateAll() 方法自动生成代码,此处你需要根据自己的情况更改输出目录(既之前创建的 java-gen)。
// 其实,输出目录的路径可以在 build.gradle 中设置,有兴趣的朋友可以自行搜索,这里就不再详解。
new DaoGenerator().generateAll(schema, "/Users/licheng/Documents/Healthdoctor/app/src/main/java-gen");
}
/**
* @param schema
*/
private static void addNote(Schema schema) {
// 一个实体(类)就关联到数据库中的一张表,此处表名为「Note」(既类名)
Entity note = schema.addEntity("TestTable");
// 你也可以重新给表命名
// note.setTableName("NODE");
// greenDAO 会自动根据实体类的属性值来创建表字段,并赋予默认值
// 接下来你便可以设置表中的字段:
note.addIdProperty();
note.addStringProperty("aa");
// 与在 Java 中使用驼峰命名法不同,默认数据库中的命名是使用大写和下划线来分割单词的。
// For example, a property called “creationDate” will become a database column “CREATION_DATE”.
note.addIntProperty("bb");
note.addIntProperty("cc");
note.addIntProperty("dd");
note.addIntProperty("ee");
}
}
三、greenDAO代码全局配置
1、DaoMaster、DaoSession配置
一个APP项目,一般不只一个数据库,一个数据库里也不只一个表,如果有多个表的情况,按照上面的配置,会发现每生成一个实体类表,除了Table和TableDao类外,都会有一个DaoMaster和DaoSession生成,这时候我们就可以配置DaoMaster和DaoSession类了,一个类管理多张表。
我们可以再生成一个实体类表,表名为TestAnOtherTable,这样,一个数据库下就有了2个表。
配置DaoMaster类
package test.greendao;
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 test.greendao.TestAnOtherTableDao;
// 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) {
TestAnOtherTableDao.createTable(db, ifNotExists);
TestTableDao.createTable(db, ifNotExists);
}
/** Drops underlying database table using DAOs. */
public static void dropAllTables(SQLiteDatabase db, boolean ifExists) {
TestAnOtherTableDao.dropTable(db, ifExists);
TestTableDao.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(TestAnOtherTableDao.class);
registerDaoClass(TestTableDao.class);
}
public DaoSession newSession() {
return new DaoSession(db, IdentityScopeType.Session, daoConfigMap);
}
public DaoSession newSession(IdentityScopeType type) {
return new DaoSession(db, type, daoConfigMap);
}
}
配置DaoSession类
package test.greendao;
import android.database.sqlite.SQLiteDatabase;
import java.util.Map;
import de.greenrobot.dao.AbstractDao;
import de.greenrobot.dao.AbstractDaoSession;
import de.greenrobot.dao.identityscope.IdentityScopeType;
import de.greenrobot.dao.internal.DaoConfig;
import test.greendao.TestAnOtherTable;
import test.greendao.TestAnOtherTableDao;
// THIS CODE IS GENERATED BY greenDAO, DO NOT EDIT.
/**
* {@inheritDoc}
*
* @see de.greenrobot.dao.AbstractDaoSession
*/
public class DaoSession extends AbstractDaoSession {
private final DaoConfig testAnOtherTableDaoConfig;
private final DaoConfig testTableDaoConfig;
private final TestAnOtherTableDao testAnOtherTableDao;
private final TestTableDao testTableDao;
public DaoSession(SQLiteDatabase db, IdentityScopeType type, Map>, DaoConfig>
daoConfigMap) {
super(db);
testAnOtherTableDaoConfig = daoConfigMap.get(TestAnOtherTableDao.class).clone();
testAnOtherTableDaoConfig.initIdentityScope(type);
testTableDaoConfig = daoConfigMap.get(TestTable.class).clone();
testTableDaoConfig.initIdentityScope(type);
testAnOtherTableDao = new TestAnOtherTableDao(testAnOtherTableDaoConfig, this);
testTableDao = new TestTableDao(testTableDaoConfig, this);
registerDao(TestAnOtherTable.class, testAnOtherTableDao);
registerDao(TestTable.class, testTableDao);
}
public void clear() {
testAnOtherTableDaoConfig.getIdentityScope().clear();
testTableDaoConfig.getIdentityScope().clear();
}
public TestAnOtherTableDao getTestAnOtherTableDao() {
return testAnOtherTableDao;
}
public TestTableDao getTestTableDao() {
return testTableDao;
}
}
2、greenDAO Application配置
greedDAO官方建议,DaoSession最好配置在Application里。
我们新建一个GreenDaoUtils类,用来新建数据库以及管理所有数据库表。
public class GreenDaoUtils {
/**
* 创建数据库连接
*
* @param context
* @return
*/
public static DaoSession createDB(Context context) {
DaoMaster.DevOpenHelper helper = new DaoMaster.DevOpenHelper(context,
TableNameEntity.DB_NAME, null);
return new DaoMaster(helper.getWritableDatabase()).newSession();
}
/**
* 给TestTable表插入数据
* @param testTable
* @param daoSession
*/
public static void addTestTableInfo(TestTable testTable, DaoSession daoSession){
daoSession.getTestTableDao().insert(testTable);
}
/**
* 获取TestTable表所有数据
* @param daoSession
* @return
*/
public static List> getTestTableInfoList(DaoSession daoSession){
QueryBuilder queryBuilder = daoSession.getTestTableDao()
.queryBuilder().orderAsc(TestTableDao.Properties.Id);
if(!ListUtils.isEmpty(queryBuilder.list())){
return queryBuilder.list();
}
return null;
}
}
public class HealthApplication extends Application {
private GreenDaoUtils mGreenDaoUtils;
private DaoSession mDaoSession;
private static HealthApplication instance;
public static HealthApplication getInstance(){
return instance;
}
@Override
public void onCreate() {
super.onCreate();
instance = this;
//greenDao数据库
initGreenDao();
}
/** greenDao数据库框架初始化 **/
private void initGreenDao() {
mGreenDaoUtils = new GreenDaoUtils();
mDaoSession = mGreenDaoUtils.createDB(this);
}
public DaoSession getmDaoSession() {
return mDaoSession;
}
}
DaoSession mDaoSession = HealthApplication.getInstance().getmDaoSession();
TestTable testTable = new TestTable();
testTable.setAa("aa");
testTable.setBb(11);
testTable.setCc(22);
testTable.setFf(44);
GreenDaoUtils.addTestTableInfo(testTable, mDaoSession);
三、greedDAO数据库的升级
新建一个MigrationHelper类
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.text.TextUtils;
import android.util.Log;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import de.greenrobot.dao.AbstractDao;
import de.greenrobot.dao.internal.DaoConfig;
public class MigrationHelper {
private static final String CONVERSION_CLASS_NOT_FOUND_EXCEPTION =
"MIGRATION HELPER - CLASS DOESN'T MATCH WITH THE CURRENT PARAMETERS";
private static MigrationHelper instance;
public static MigrationHelper getInstance() {
if (instance == null) {
instance = new MigrationHelper();
}
return instance;
}
public void migrate(SQLiteDatabase db, Class extends AbstractDao, ?>>... daoClasses) {
generateTempTables(db, daoClasses);
DaoMaster.dropAllTables(db, true);
DaoMaster.createAllTables(db, false);
restoreData(db, daoClasses);
}
private void generateTempTables(SQLiteDatabase db, Class extends AbstractDao, ?>>... daoClasses) {
for (int i = 0; i < daoClasses.length; i++) {
DaoConfig daoConfig = new DaoConfig(db, daoClasses[i]);
String divider = "";
String tableName = daoConfig.tablename;
String tempTableName = daoConfig.tablename.concat("_TEMP");
ArrayList properties = new ArrayList<>();
StringBuilder createTableStringBuilder = new StringBuilder();
createTableStringBuilder.append("CREATE TABLE ").append(tempTableName).append(" (");
for (int j = 0; j < daoConfig.properties.length; j++) {
String columnName = daoConfig.properties[j].columnName;
if (getColumns(db, tableName).contains(columnName)) {
properties.add(columnName);
String type = null;
try {
type = getTypeByClass(daoConfig.properties[j].type);
} catch (Exception exception) {
}
createTableStringBuilder.append(divider).append(columnName).append(" ").append(type);
if (daoConfig.properties[j].primaryKey) {
createTableStringBuilder.append(" PRIMARY KEY");
}
divider = ",";
}
}
createTableStringBuilder.append(");");
db.execSQL(createTableStringBuilder.toString());
StringBuilder insertTableStringBuilder = new StringBuilder();
insertTableStringBuilder.append("INSERT INTO ").append(tempTableName).append(" (");
insertTableStringBuilder.append(TextUtils.join(",", properties));
insertTableStringBuilder.append(") SELECT ");
insertTableStringBuilder.append(TextUtils.join(",", properties));
insertTableStringBuilder.append(" FROM ").append(tableName).append(";");
db.execSQL(insertTableStringBuilder.toString());
}
}
private void restoreData(SQLiteDatabase db, Class extends AbstractDao, ?>>... daoClasses) {
for (int i = 0; i < daoClasses.length; i++) {
DaoConfig daoConfig = new DaoConfig(db, daoClasses[i]);
String tableName = daoConfig.tablename;
String tempTableName = daoConfig.tablename.concat("_TEMP");
ArrayList properties = new ArrayList();
for (int j = 0; j < daoConfig.properties.length; j++) {
String columnName = daoConfig.properties[j].columnName;
if (getColumns(db, tempTableName).contains(columnName)) {
properties.add(columnName);
}
}
StringBuilder insertTableStringBuilder = new StringBuilder();
insertTableStringBuilder.append("INSERT INTO ").append(tableName).append(" (");
insertTableStringBuilder.append(TextUtils.join(",", properties));
insertTableStringBuilder.append(") SELECT ");
insertTableStringBuilder.append(TextUtils.join(",", properties));
insertTableStringBuilder.append(" FROM ").append(tempTableName).append(";");
StringBuilder dropTableStringBuilder = new StringBuilder();
dropTableStringBuilder.append("DROP TABLE ").append(tempTableName);
db.execSQL(insertTableStringBuilder.toString());
db.execSQL(dropTableStringBuilder.toString());
}
}
private String getTypeByClass(Class> type) throws Exception {
if (type.equals(String.class)) {
return "TEXT";
}
if (type.equals(Long.class) || type.equals(Integer.class) || type.equals(long.class)) {
return "INTEGER";
}
if (type.equals(Boolean.class)) {
return "BOOLEAN";
}
Exception exception =
new Exception(CONVERSION_CLASS_NOT_FOUND_EXCEPTION.concat(" - Class: ").concat(type.toString()));
throw exception;
}
private static List getColumns(SQLiteDatabase db, String tableName) {
List columns = new ArrayList<>();
Cursor cursor = null;
try {
cursor = db.rawQuery("SELECT * FROM " + tableName + " limit 1", null);
if (cursor != null) {
columns = new ArrayList<>(Arrays.asList(cursor.getColumnNames()));
}
} catch (Exception e) {
Log.v(tableName, e.getMessage(), e);
e.printStackTrace();
} finally {
if (cursor != null) cursor.close();
}
return columns;
}
}
/** 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);
MigrationHelper.getInstance().migrate(db, TestTable.class);
MigrationHelper.getInstance().migrate(db, TestAnOtherTable.class);
}
}
public static final int SCHEMA_VERSION = 1;
每次改动数据库,该值需要更改。
如果数据库表字段有更新、或添加删除字段,或数据库有增删表,利用generater模块类重新生成实体类表,然后更改数据库版本号,就可以实现数据库的更新。