ORM对象关系映射之使用GreenDAO进行CRUD操作
在Android中,我们都知道使用的数据库是SQLite,而使用这种原生的数据库非常繁琐,它对表的管理和进行CRUD操作都需要我们写sql语句,在进行多表关联的操作上,更是需要写一堆sql,而且维护起来也极其不便。所以ORM程序设计技术应用而生,它主要是用于实现面向对象编程语言里不同类型系统的数据之间的转换。
目前流行的ORM框架
目前主要流行这么三款ORM框架:
下面主要说一下它们的优缺点:
ORMLite
优点:
文档比较全面,使用简单,易于上手
缺点:
使用注解和反射的方式,导致ORMLite性能较差、效率上不理想
ActiveAndroid
优点:
轻量级,使用起来非常简单
缺点:
基于注解的方式,使用前需要在manifest中配置
GreenDAO
关于GreenDAO,则是本篇的重点
优点:
性能最大化、内存开销最小化、对Android高度优化、操作方便、文件体积比较小
效率很高,插入和更新的速度是SQLite的2倍,加载实体的速度是ORMLite的4.5倍
缺点:
学习成本较高,对于整个框架的需要有一定的理解才能灵活的使用。它使用时需要创建一个java工程去generate相应的实体类和DAO,另外还有众多API需要理解,如Properties、QueryBuilder、Dao等API,可以说学起来还是有一定的难度的
所以,个人还是比较喜欢GreenDAO这个框架,所以接下来就是介绍在Android Studio中配置和使用GreenDAO框架
GreenDAO的配置和使用
首先新建一个Project工程,配置java-gen目录
新建一个Project工程,然后在Module中创建一个与java目录同级
的java-gen
目录,如图:
该目录主要用来存放GreenDAO生成的实体类和DAO类
添加GreenDAO依赖
目前GreenDAO已经Release到2.0.0版本了,可以去它官网和github上看github地址
我们需要在Module中的gradle添加如下依赖
compile 'de.greenrobot:greendao:2.0.0'
然后在Module中的gradle文件中这样配置:
sourceSets{
main{
java.srcDirs = ['src/main/java','src/main/java-gen']
}
}
在Project工程中新创建一个Java Library项目
我们创建好后,需要为该Java项目添加依赖,注意,在Java项目中添加的是greendao-generator
依赖,这与上面的不同,因为这个Java项目就是负责生成相应的实体和DAO的,如下:
compile 'de.greenrobot:greendao-generator:2.0.0'
利用Java项目自动生成相应的实体类和DAO
这是使用GreenDAO配置的最后一步了,就是在java-gen
目录下生成实体类和DAO类,我们在刚刚创建的Java项目中,在main方法中这样创建数据库的结构:
public class GreenDaoGenerator {
public static void main(String[] args) throws Exception{
//创建一个用于添加实体的Schema对象,第一个参数表示数据库的版本,第二个参数表示在java-gen目录下自动生成的实体类和DAO类存放的包名
Schema schema = new Schema(1,"com.sunzxyong.greendao");
// schema.setDefaultJavaPackageDao("com.sunzxyong.dao");//假如你不想实体类和DAO类都放在一个包中,你可以重新为DAO类设置一个新的包
//创建一个实体,一个实体对应一张表,此处表示生成的实体名为Student,同样它默认也是表名
Entity entity = schema.addEntity("Student");
// entity.setTableName("Students");//你如果不想实体名和表名相同,也可以重新设置一个表名
//为Student表添加字段,这里的参数表示实体类Student的字段名,生成的表中的字段会变成大写,如name在表中字段为NAME
entity.addIdProperty().autoincrement().primaryKey();
entity.addStringProperty("name").notNull();
entity.addIntProperty("age");
entity.addBooleanProperty("is_man");
//最后通过DaoGenerator对象的generateAll()方法来生成相应的实体类和DAO类,参数分别为Schema对象和java-gen目录路径
new DaoGenerator().generateAll(schema,"../GreenDAODemo/app/src/main/java-gen");
}
}
其中一个Schema一对象代表一个数据库,而往数据库中add多个Entity说明在这个数据库中创建了多张表。
然后右击运行这个类,这时候等待数秒,在控制台中有这样的输出就证明成功生成了相应的实体类和DAO类,控制台的输出为:
可以看见在java-gen
目录下的com.sunzxyong.greendao
包中成功创建了四个类,分别是实体类:Student,DAO类:StudentDao、DaoMaster、DaoSession。
在app项目中的目录结构如下:
至此,现在GreenDAO的基本配置就全部完成了,同时也生成了相应的实体类和DAO类(注意,此时并没有生成相应的数据表,只是生成了实体类,只要当我们调用DaoMaster.DevOpenHelper()
这个方法时,才生成了实体类对应的数据表)
在Android项目中使用GreenDAO进行CRUD操作
GreenDAO终于配置好了,接下来就是通过一个demo来看看使用GreenDAO具体怎么操作数据表以及进行CRUD操作。
首先我们创建一个布局:
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity">
<EditText
android:id="@+id/edt_content"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="16sp" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:id="@+id/btn_add"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:onClick="click"
android:text="添加" />
<Button
android:id="@+id/btn_delete"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:onClick="click"
android:text="删除" />
<Button
android:id="@+id/btn_update"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:onClick="click"
android:text="修改" />
<Button
android:id="@+id/btn_search"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:onClick="click"
android:text="查询" />
</LinearLayout>
<ListView
android:id="@+id/listview"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</LinearLayout>
下面就通过代码来看看使用GreenDAO具体是怎么做CRUD操作的,代码中有注释,就不多叙述了,可以看见GreenDAO做CRUD操作非常的方便
代码为:
public class MainActivity extends AppCompatActivity {
private DaoMaster.DevOpenHelper helper;
private DaoMaster master;
private DaoSession session;
private StudentDao dao;
private EditText mEditText;
private ListView mListView;
private SimpleCursorAdapter adapter;
private Cursor cursor;
private SQLiteDatabase db;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mEditText = (EditText) findViewById(R.id.edt_content);
mListView = (ListView) findViewById(R.id.listview);
//第一个参数为Context,第二个参数为数据表的文件名,这个我们可以以"表名+s+'-db'"来命名,第三个通常为null
helper = new DaoMaster.DevOpenHelper(this, "students-db", null);
db = helper.getWritableDatabase();
master = new DaoMaster(db);
session = master.newSession();
//得到StudentDAO对象,所以在这看来,对于这三个DAO文件,我们更能接触到的是StudentDao文件,进行CRUD操作也是通过StudentDao对象来操作
dao = session.getStudentDao();
//遍历表中的所有数据
cursor = db.query(dao.getTablename(), dao.getAllColumns(), null, null, null, null, null);
//通过StudentDao的静态内部类得到Name字段对应表中的列名
String[] from = {StudentDao.Properties.Name.columnName, StudentDao.Properties.Age.columnName};
int[] to = {android.R.id.text1, android.R.id.text2};
adapter = new SimpleCursorAdapter(this, android.R.layout.simple_list_item_2, cursor, from, to, SimpleCursorAdapter.NO_SELECTION);
mListView.setAdapter(adapter);
}
public void click(View view) {
switch (view.getId()) {
case R.id.btn_add:
add();
Cursor cursor = db.query(dao.getTablename(), dao.getAllColumns(), null, null, null, null, null);
adapter.swapCursor(cursor);//交换cursor数据集从而实时更新UI
//cursor.requery();//这个也可以实时更新UI,不过官方已经不推荐使用了,因为它可能会阻塞UI线程造成ANR
break;
case R.id.btn_delete:
delete();
Cursor cursor2 = db.query(dao.getTablename(), dao.getAllColumns(), null, null, null, null, null);
adapter.swapCursor(cursor2);
break;
case R.id.btn_update:
update();
Cursor cursor3 = db.query(dao.getTablename(), dao.getAllColumns(), null, null, null, null, null);
adapter.swapCursor(cursor3);
break;
case R.id.btn_search:
search();
break;
}
}
private void add() {
String content = mEditText.getText().toString().trim();
// DateFormat format = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM, Locale.CHINA);
Student student = new Student(null, content,18, true);//由于主键id之前设置了自增长,所以传入null即可
dao.insert(student);//插入数据
}
private void delete() {
String content = mEditText.getText().toString().trim();
dao.deleteByKey(Long.valueOf(content));//通过主键来删除某行数据
// dao.deleteAll();//全部删除
}
private void update() {
String content = mEditText.getText().toString().trim();
//update只能通过主键来更新某个实体对应的数据,这里的主键为id
dao.update(new Student(Long.valueOf(content), "这是修改的", 120, true));
}
private void search() {
String content = mEditText.getText().toString().trim();
//通过queryBuilder()来查询可以更方便的设置查询的条件,其中eq()方法表示equal(),判断Name是否和content相等,然后通过build建立查询
Query<Student> query = dao.queryBuilder().where(StudentDao.Properties.Name.eq(content)).build();
List<Student> list = query.list();
//下面两个Flag的设置可以在控制台中打印出此次查询的sql语句和value值
QueryBuilder.LOG_SQL = true;
QueryBuilder.LOG_VALUES = true;
new AlertDialog.Builder(this).setMessage(list.get(0).getName()+","+list.get(0).getAge()).setPositiveButton("确定",null).create().show();
}
}
我们来看看效果:
同时,我们也来看看刚刚命名为students-db
的数据库文件是不是真的创建了:
再来看看其中比较重要的两个类StudentDao和Property的源码:
StudentDao.java
public class StudentDao extends AbstractDao<Student, Long> {
public static final String TABLENAME = "STUDENT";
/**
* Properties of entity 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, Integer.class, "age", false, "AGE");
public final static Property Is_man = new Property(3, Boolean.class, "is_man", false, "IS_MAN");
};
//...
}
Property.java
public class Property {
public final int ordinal;
public final Class<?> type;
public final String name;
public final boolean primaryKey;
public final String columnName;
public Property(int ordinal, Class<?> type, String name, boolean primaryKey, String columnName) {
this.ordinal = ordinal;
this.type = type;
this.name = name;
this.primaryKey = primaryKey;
this.columnName = columnName;
}
/** Creates an "equal ('=')" condition for this property. */
public WhereCondition eq(Object value) {
return new PropertyCondition(this, "=?", value);
}
/** Creates an "not equal ('<>')" condition for this property. */
public WhereCondition notEq(Object value) {
return new PropertyCondition(this, "<>?", value);
}
/** Creates an "LIKE" condition for this property. */
public WhereCondition like(String value) {
return new PropertyCondition(this, " LIKE ?", value);
}
/** Creates an "BETWEEN ... AND ..." condition for this property. */
public WhereCondition between(Object value1, Object value2) {
Object[] values = { value1, value2 };
return new PropertyCondition(this, " BETWEEN ? AND ?", values);
}
/** Creates an "IN (..., ..., ...)" condition for this property. */
public WhereCondition in(Object... inValues) {
StringBuilder condition = new StringBuilder(" IN (");
SqlUtils.appendPlaceholders(condition, inValues.length).append(')');
return new PropertyCondition(this, condition.toString(), inValues);
}
/** Creates an "IN (..., ..., ...)" condition for this property. */
public WhereCondition in(Collection<?> inValues) {
return in(inValues.toArray());
}
/** Creates an "NOT IN (..., ..., ...)" condition for this property. */
public WhereCondition notIn(Object... notInValues) {
StringBuilder condition = new StringBuilder(" NOT IN (");
SqlUtils.appendPlaceholders(condition, notInValues.length).append(')');
return new PropertyCondition(this, condition.toString(), notInValues);
}
/** Creates an "NOT IN (..., ..., ...)" condition for this property. */
public WhereCondition notIn(Collection<?> notInValues) {
return notIn(notInValues.toArray());
}
/** Creates an "greater than ('>')" condition for this property. */
public WhereCondition gt(Object value) {
return new PropertyCondition(this, ">?", value);
}
/** Creates an "less than ('<')" condition for this property. */
public WhereCondition lt(Object value) {
return new PropertyCondition(this, "<?", value);
}
/** Creates an "greater or equal ('>=')" condition for this property. */
public WhereCondition ge(Object value) {
return new PropertyCondition(this, ">=?", value);
}
/** Creates an "less or equal ('<=')" condition for this property. */
public WhereCondition le(Object value) {
return new PropertyCondition(this, "<=?", value);
}
/** Creates an "IS NULL" condition for this property. */
public WhereCondition isNull() {
return new PropertyCondition(this, " IS NULL");
}
/** Creates an "IS NOT NULL" condition for this property. */
public WhereCondition isNotNull() {
return new PropertyCondition(this, " IS NOT NULL");
}
}
可以看到我们可以通过StudentDao得到静态内部类Properties中的各个字段对应的Property对象,然后通过Property对象可以得到这个字段对应的列名、是否为主键以及其它的一些操作方法。
后续几篇再慢慢介绍GreenDAO的高级用法!
ORM对象关系映射之使用GreenDAO进行CRUD操作的更多相关文章
- ORM 对象关系映射
ORM (object relation mapping) 就是将对象数据转换为sql语句并执行 对象关系映射框架 orm 需要做的事情 1 生成创建表的语句 2 插入数据的语句 3 删除数据的语句 ...
- Django---静态文件配置,post提交表单的csrf问题(日后细说),创建app子项目和分析其目录,ORM对象关系映射简介,Django操作orm(重点)
Django---静态文件配置,post提交表单的csrf问题(日后细说),创建app子项目和分析其目录,ORM对象关系映射简介,Django操作orm(重点) 一丶Django的静态文件配置 #we ...
- Php ORM 对象关系映射
ORM的全称是Object Relational Mapping,即对象关系映射.它的实质就是将关系数据(库)中的业务数据用对象的形式表示出来,并通过面向对象(Object-Oriented)的方式将 ...
- $Django setting.py配置 ,GET、POST深入理解,三件套,orm对象关系映射简介
1 django中app的概念: 大学:----------------- 项目 信息学院 ----------app01 物理学院-----------app02 ****强调***:创建的每一 ...
- ORM对象关系映射
ORM 总结: ORM:对象关系映射 作用: 1.将定义数据库模型类--> 数据库表 2.将定义数据库模型类中的属性--->数据库表字段 3.将模型对象的操作(add,delete,com ...
- Java 自定义注解实现ORM对象关系映射
一,ORM概念 ORM即Object Relation Mapping,Object就是对象,Relation就是关系数据库,Mapping映射,就是说Java中的对象和关系数据库中的表存在一种对应关 ...
- django-模型之(ORM)对象关系映射(一)
所谓对象关系映射,就是将数据库的一些名字与python中的一些名字相对应,表名-->类名,字段-->属性,操作(增删改查)-->方法.这样,我们就可以通过对Python代码的编辑来对 ...
- ORM对象关系映射之GreenDAO源码解析
上一篇我们学习了GreenDAO的CRUD基本操作,可以说是非常的方便的,而且GreenDAO的效率和性能远远高于其它两款流行的ORM框架,下面是我从官网找的一副它们三个ORM框架之间的性能测试的直观 ...
- ORM对象关系映射之GreenDAO建立多表关联
利用GreenDAO可以非常方便的建立多张表之间的关联 一对一关联 通常我们在操作数据库的时候,我们往往不是单独的对一张表进行操作,而是对这张表的操作会联动的影响另外一张表或者多张表,比如:现在有两张 ...
随机推荐
- ubuntu初始化python3+postgresql+uwsgi+nginx+django
一. postgresql 数据库 安装 apt-get update apt-get install postgresql 进入psql客户端 sudo -u postgres psql 创建数据库 ...
- 大话XML解析
之前我写过一篇关于xml解析的文章:http://blog.csdn.net/sdksdk0/article/details/50749326.今天这篇文章主要是进一步加深对xml基础的理解了使用,毕 ...
- springMVC源码分析--AbstractHandlerMethodMapping获取url和HandlerMethod对应关系(十)
在之前的博客springMVC源码分析--AbstractHandlerMapping(二)中我们介绍了AbstractHandlerMethodMapping的父类AbstractHandlerMa ...
- Xcode7.3.1中通过最新的CocoaPod安装pop动画引擎
CocoaPod是一个用ruby实现,用于方便的管理Xcode中第三方插件的管理器.用它我们可以很方便的安装和升级插件而不用担心破坏原有的项目. 而pop是一个用于实现App中动画的引擎,它是由Fac ...
- [uwsgi]使用建议(类似最佳实践)
看了下uwsgi官方的一个使用建议,之前都是直接参考了下django文档中那个比较简单的配置或者就写了个能运行的配置,么有注意很多细节问题,这里学习下,把需要的配置添加到项目配置中. 1 http a ...
- JAVA面向对象-----封装
我们日常使用的电脑主机,把cpu.内存.主板等等都封装到机箱里面去.假如没有机箱的话的出现什么问题,主机.主板全部都散落在一处,然后开机没有开机按钮,那么需要我们直接操作接跳线才能把电脑开启.这样子的 ...
- Swift中实现ruby中字符串乘法倍增的功能
大熊猫猪·侯佩原创或翻译作品.欢迎转载,转载请注明出处. 如果觉得写的不好请多提意见,如果觉得不错请多多支持点赞.谢谢! hopy ;) 我们知道在ruby中对于字符串类型我们可以用乘法生成一个指定数 ...
- 01_Eclipse的使用方法
1 选择工作站 Workspace:表示工作站 2 切换工作站 选择工作站的方式:File->SwitchWorkspace 这里选择其他的工作站 清除工作站的方式: 找到MyEclips ...
- 3.0、Android Studio构建和运行应用
默认情况下,Android Studio可以通过简单的点击就会将新的项目部署到虚拟机或者物理设备中.在Instant Run的帮助下,你可以将更改的方法或资源文件直接推送到一个运行的app而无需构建一 ...
- [ExtJS5学习笔记]第二十节 Extjs5配合数组的push方法,动态创建并加载组件
本文地址:http://blog.csdn.net/sushengmiyan/article/details/39226773 官方例子:http://docs.sencha.com/extjs/5. ...