ORM框架简化了java对象和数据库之间的存储转化,使得数据库数据和java对象可以直接转化而不必通过大量重复的对象的分解与构建动作来完成业务逻辑。在java中,比较知名的ORM框架当属Hibernate框架,在Android中也有比较常用的ORM框架,像ORMlite、GreenDAO、DBFlow框架等等。今天就介绍一下GreenDAO框架的使用。
GreenDAO作为Android平台上的ORM框架,它并没有像hibernate那样,通过特定annotaion和hibernate.cfg.xml文件配置对象和数据库之间的关系,毕竟这个库只有不到100kb的大小。GreenDao的做法是生成帮助用户生成特定的数据库文件、java对象和直接存储数据库的DAO操作对象来简化用户的操作,所以GreenDAO框架包含两个部分:GreenDAOGenerator和GreenDAO两个部分。
- GreenDAOGenerator
使用GreenDAOGenrator的目的是生成用户使用的java类和DAO类,这是一个java工程,应该在java工程中使用,那么如何使用呢?
首先使用GreenDAOGenerator必须用到两个库,我们以最新的库文件来说:greendao-generator-2.1.0.jar和freemarker-2.3.23.jar,这里有个要注意的地方就是freemarker库版本的要求必须是2.3.23,不然会不兼容。如何找到这两个jar包呢?推荐使用maven仓库中去下载,http://mvnrepository.com/。
public class GeneratorMotion {
public static void main(String[] args) {
//schema是用来生成数据和相关类的1,1表示数据库的版本,第二个参数标识生成这些类的包名
Schema schema = new Schema(1, "com.app.motion.warmcloudweather.domain.dao");
//添加数据库字段
addPerson(schema);
try {
//生成相关类
new DaoGenerator().generateAll(schema, "src");
} catch (Exception e) {
e.printStackTrace();
}
}
//创建一个数据库
public static void addPerson(Schema schema) {
//entity相当于数据库中的表
Entity entity = schema.addEntity("tb_student");
//添加一个id字段
entity.addIdProperty();
//添加一个name字段
entity.addStringProperty("name").notNull();
//添加一个age字段
entity.addIntProperty("age").notNull();
//添加一个gender字段
entity.addStringProperty("gender").notNull();
//添加一个grader字段
entity.addIntProperty("grader").notNull();
}
}
上面的代码生成了一个操作数据库tb_student的各种dao文件。从上面的代码看,使用greendaogenerator非常简单:Schema中定义生成数据库的版本和位置,在schema中添加表示表名的entity,在这个entity中可以通过各种addXXXProperty来生成不同的字段,最后通过DaoGenerator生成所有需要用到的java文件。
一共生成了4个文件:DAOMaster、DAOSession、tb_student、tb_studentDAO,大致看一下这些类是干什么用的。
- DAOMater
/** Creates underlying database table using DAOs. */
public static void createAllTables(SQLiteDatabase db, boolean ifNotExists) {
tb_studentDao.createTable(db, ifNotExists);
}
/** Drops underlying database table using DAOs. */
public static void dropAllTables(SQLiteDatabase db, boolean ifExists) {
tb_studentDao.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);
}
}
大致可以了解是封装了SQLiteOpenHelper类,用来帮助我们构建数据库的。
- DAOSession
public class DaoSession extends AbstractDaoSession {
private final DaoConfig tb_studentDaoConfig;
private final tb_studentDao tb_studentDao;
public DaoSession(SQLiteDatabase db, IdentityScopeType type, Map<Class<? extends AbstractDao<?, ?>>, DaoConfig>
daoConfigMap) {
super(db);
tb_studentDaoConfig = daoConfigMap.get(tb_studentDao.class).clone();
tb_studentDaoConfig.initIdentityScope(type);
tb_studentDao = new tb_studentDao(tb_studentDaoConfig, this);
registerDao(tb_student.class, tb_studentDao);
}
public void clear() {
tb_studentDaoConfig.getIdentityScope().clear();
}
这个类中没有太多的方法,但是这个类继承了AbstractDaoSession类,AbstractDaoSession类中定义了很多操作数据库的方法例如update、query、load等方法,这些方法都是会话级别的,更加细粒度的调用应该使用tb_studentDao中的方法。
- tb_student
package com.app.motion.warmcloudweather.domain.dao;
// THIS CODE IS GENERATED BY greenDAO, DO NOT EDIT. Enable "keep" sections if you want to edit.
/**
* Entity mapped to table "TB_STUDENT".
*/
public class tb_student {
private Long id;
/** Not-null value. */
private String name;
private int age;
/** Not-null value. */
private String gender;
private int grader;
public tb_student() {
}
public tb_student(Long id) {
this.id = id;
}
public tb_student(Long id, String name, int age, String gender, int grader) {
this.id = id;
this.name = name;
this.age = age;
this.gender = gender;
this.grader = grader;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
/** Not-null value. */
public String getName() {
return name;
}
/** Not-null value; ensure this value is available before it is saved to the database. */
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
/** Not-null value. */
public String getGender() {
return gender;
}
/** Not-null value; ensure this value is available before it is saved to the database. */
public void setGender(String gender) {
this.gender = gender;
}
public int getGrader() {
return grader;
}
public void setGrader(int grader) {
this.grader = grader;
}
}
这个类没什么说的,就是数据库对应的POJO类
- tb_studentDao
public class tb_studentDao extends AbstractDao<tb_student, Long> {
public static final String TABLENAME = "TB_STUDENT";
/**
* Properties of entity tb_student.<br/>
* Can be used for QueryBuilder and for referencing column names.
*/
public static class Properties {
public final static Property Id = new Property(0, Long.class, "id", true, "_id");
public final static Property Name = new Property(1, String.class, "name", false, "NAME");
public final static Property Age = new Property(2, int.class, "age", false, "AGE");
public final static Property Gender = new Property(3, String.class, "gender", false, "GENDER");
public final static Property Grader = new Property(4, int.class, "grader", false, "GRADER");
};
public tb_studentDao(DaoConfig config) {
super(config);
}
public tb_studentDao(DaoConfig config, DaoSession daoSession) {
super(config, daoSession);
}
/** Creates the underlying database table. */
public static void createTable(SQLiteDatabase db, boolean ifNotExists) {
String constraint = ifNotExists? "IF NOT EXISTS ": "";
db.execSQL("CREATE TABLE " + constraint + ""TB_STUDENT" (" + //
""_id" INTEGER PRIMARY KEY ," + // 0: id
""NAME" TEXT NOT NULL ," + // 1: name
""AGE" INTEGER NOT NULL ," + // 2: age
""GENDER" TEXT NOT NULL ," + // 3: gender
""GRADER" INTEGER NOT NULL );"); // 4: grader
}
/** Drops the underlying database table. */
public static void dropTable(SQLiteDatabase db, boolean ifExists) {
String sql = "DROP TABLE " + (ifExists ? "IF EXISTS " : "") + ""TB_STUDENT"";
db.execSQL(sql);
}
/** @inheritdoc */
@Override
protected void bindValues(SQLiteStatement stmt, tb_student entity) {
stmt.clearBindings();
Long id = entity.getId();
if (id != null) {
stmt.bindLong(1, id);
}
stmt.bindString(2, entity.getName());
stmt.bindLong(3, entity.getAge());
stmt.bindString(4, entity.getGender());
stmt.bindLong(5, entity.getGrader());
}
这个类直接封装了更加细粒度的操作,load、update、delete方法,在实际操作中都将调用这个类的方法来操作数据库。生成了这些java文件之后接下来就是要在android生产环境中使用了,将这些文件复制到相同包名路径下的Android工程中。
- GreenDAO
将这些文件导入到Android工程之后,再将greendao-2.1.0.jar导入到工程中,之前的一些报错都被消除了,greendao的jar包同样可以使用上述的maven地址下载。
package com.app.motion.greendaomotion;
import android.database.sqlite.SQLiteDatabase;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import com.app.motion.warmcloudweather.domain.dao.DaoMaster;
import com.app.motion.warmcloudweather.domain.dao.DaoSession;
import com.app.motion.warmcloudweather.domain.dao.tb_student;
import com.app.motion.warmcloudweather.domain.dao.tb_studentDao;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private Button mInsertBtn;
private Button mDeleteBtn;
private Button mUpdateBtn;
private Button mQueryBtn;
private DaoMaster.DevOpenHelper mOpenHelper;
private DaoMaster mDaoMaster;
private DaoSession mDaoSession;
private tb_studentDao mStudentDao;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initViews();
initDao();
}
private void initViews() {
mInsertBtn = (Button) this.findViewById(R.id.insert);
mDeleteBtn = (Button) this.findViewById(R.id.delete);
mUpdateBtn = (Button) this.findViewById(R.id.update);
mQueryBtn = (Button) this.findViewById(R.id.query);
mInsertBtn.setOnClickListener(this);
mDeleteBtn.setOnClickListener(this);
mUpdateBtn.setOnClickListener(this);
mQueryBtn.setOnClickListener(this);
}
private void initDao() {
mOpenHelper = new DaoMaster.DevOpenHelper(this, "students.db3", null);
SQLiteDatabase db = mOpenHelper.getWritableDatabase();
mDaoMaster = new DaoMaster(db);
mDaoSession = mDaoMaster.newSession();
mStudentDao = mDaoSession.getTb_studentDao();
}
@Override
public void onClick(View view) {
int id = view.getId();
switch (id) {
case R.id.insert:
tb_student student = new tb_student(1L, "zhangsan", 12, "male", 6);
mStudentDao.insert(student);
break;
case R.id.delete:
mStudentDao.deleteByKey(1L);
break;
case R.id.update:
tb_student tmp = mStudentDao.load(1L);
tmp.setName("wangwu");
mStudentDao.update(tmp);
break;
case R.id.query:
tb_student currentStu = mStudentDao.load(1L);
break;
}
}
}
在initDao方法中我们最终得到了tb_studentDao对象,使用这个对象我们就可以执行增删改查操作了。
插入操作 tb_studentDao.insert()
查询操作 tb_studentDao.load(),这个方法根据id查询到所有数据并且封装到tb_student对象中,如果想使用更加细致的查询可以使用query操作。
更新操作tb_studentDao.update(),这个方法和Hibernate有个通病,都是要先查询出来tb_student对象来,然后更新了对象之后才能调用update方法
删除操作tb_studentDao.deleteByKey(id).
that’s all~~