项目结构:
新建Android工程GreenDaoTest
新建Java lib工程mylib
next, 取名mylib(自己随便取)
finish, 在Android工程中创建目录Java-gen, 与Java平级, 看第一张图
配置
第一步:在app的build.gradle中添加配置如下:
第二步:在mylib的build.gradle中添加配置如下:
编码
第一步: 在mylib中的类MyClass.java中这样写:
public class MyClass {
public static void main(String[] args) throws Exception {
int version=1;
String defaultPackage="com.ygl.bean";
// String defaultPackage="com.ygl.greendaotest";
//创建模式对象,指定版本号和自动生成的bean对象的包名
Schema schema=new Schema(version,defaultPackage);
//指定自动生成的dao对象的包名,不指定则都DAO类生成在"test.greenDAO.bean"包中
schema.setDefaultJavaPackageDao("com.ygl.dao");
// 模式(Schema)同时也拥有两个默认的 flags,分别用来标示 entity 是否是 activie 以及是否使用 keep sections。
// schema2.enableActiveEntitiesByDefault();
// schema2.enableKeepSectionsByDefault();
addEntity(schema);
String outDir="C:/Users/ygl_panpan/Downloads/GreenDaoTest/app/src/main/java-gen";
//调用DaoGenerator().generateAll方法自动生成代码到之前创建的java-gen目录下
new DaoGenerator().generateAll(schema,outDir);
}
private static Entity addEntity(Schema schema) {
//添加一个实体,则会自动生成实体Entity类
Entity entity = schema.addEntity("student");
//指定表名,如不指定,表名则为 Entity(即实体类名)
entity.setTableName("students");
//给实体类中添加属性(即给test表中添加字段)
entity.addIdProperty().autoincrement();//添加Id,自增长
entity.addStringProperty("name").notNull();//添加String类型的name,不能为空
entity.addIntProperty("age");//添加Int类型的age
entity.addDoubleProperty("score");//添加Double的score
return entity;
}
运行MyClass
在Android工程的Java-gen目录中会有如下红框中的代码生成
使用
官方推荐将获取 DaoMaster 对象的方法放到 Application 层,这样将避免多次创建生成 Session 对象, 新建MyApplication :
public class MyApplication extends Application {
private static MyApplication instance = new MyApplication();
private static DaoSession daoSession;
private static SQLiteDatabase db;
private static DaoMaster.DevOpenHelper helper;
private static DaoMaster daoMaster;
public static MyApplication getInstance(){
if(instance == null){
instance = new MyApplication();
}
return instance;
}
@Override
public void onCreate() {
super.onCreate();
setupDatabase();
}
private void setupDatabase() {
//创建数据库
// 注意:默认的 DaoMaster.DevOpenHelper 会在数据库升级时,删除所有的表,意味着这将导致数据的丢失。
// 所以,在正式的项目中,你还应该做一层封装,来实现数据库的安全升级。
helper = new DaoMaster.DevOpenHelper(this, "test", null);
//得到数据库连接对象
db = helper.getWritableDatabase();
//得到数据库管理者
daoMaster =new DaoMaster(db);
//得到daoSession,可以执行增删改查操作
daoSession = daoMaster.newSession();
}
public DaoSession getDaoSession() {
return daoSession;
}
public SQLiteDatabase getDb() {
return db;
}
}
Activity中这样使用:
public class MainActivity extends AppCompatActivity {
private static final String TAG = "plq";
private com.ygl.dao.studentDao studentDao;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
studentDao =MyApplication.getInstance().getDaoSession().getStudentDao();
}
public void insert(View v) {
List<student> list = new ArrayList<>();
list.add(new student(1l, "张一", 21, 91.0));
list.add(new student(2l, "张二", 22, 92.0));
studentDao.insertOrReplaceInTx(list);
Log.i(TAG, "insert scuccess");
}
public void query(View v) {
List<student> students = studentDao.loadAll();
Log.i(TAG, students.size()+"");
for (student stu : students){
Log.i(TAG, stu.getName());
}
Log.i(TAG, "query scuccess");
}
public void update(View v) {
studentDao.update(new student(1l, "张一yi", 21, 91.0));
Log.i(TAG, "update scuccess");
}
public void delete(View v) {
studentDao.deleteByKey(2l);
Log.i(TAG, "delete scuccess");
}
}
数据库升级:
当我们在MyClass中修改了entity(增减变量), 那么我们应该修改version的值+1, 然后mark project, 之后我们在自动生成的DaoMaster类中添加一行代码, 如下:
需要注意的是每次mark project后, DaoMaster中的代码都会还原, 所以每次mark project后都需要去添加这行代码
MigrationHelper类:
/**
* author:国外大牛 on 2016/12/14 15:25
* email:
*
* description:
* GreenDAO数据库版本升级之旧数据的保存
* 使用: 在DaoMaster类中, 有个继承OpenHelper的内部类DevOpenHelper, 在DevOpenHelper的onUpgrade方法中调用以下一行代码既可(记得注释原先onUpgrade方法中默认代码):
* MigrationHelper.getInstance().migrate(db, xxxDao.class, yyyDao.class, ......);
*/
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<String> 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) {
exception.printStackTrace();
// Crashlytics.logException(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<String> 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()));
exception.printStackTrace();
// Crashlytics.logException(exception);
throw exception;
}
private static List<String> getColumns(SQLiteDatabase db, String tableName) {
List<String> 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;
}
}