先看效果图:
添加实体:
按条件查询实体:
GreenDao 概述:
适用于Android的轻量级快速ORM框架,可将对象映射到SQLite数据库中,并且针对Andriod进行了高度的优化,greenDao提供了出色的性能,并占用了最少的内存。
优点:
性能上:可能是Android上最快的ORM框架
易用性上:提供强大并且简洁明了的API
轻量:最小的内存消耗与小于150kb的库大小
ORM:即Object-Relational-Mapping,它的作用是在关系型数据库和对象之间做一个映射,这样,我们在具体操作数据库的时候,就不需要再去和复杂的SQL语句打交道,只是像平时操作对象一样操作它就可以了。
greenDao 使用步骤:
1、引入:
根据github文档引入,具体如下:
将以下Gradle配置添加到你的Android项目中。 在你的根build.gradle文件:
buildscript {
repositories {
jcenter()
mavenCentral() // add repository
}
dependencies {
classpath 'com.android.tools.build:gradle:3.5.3'
classpath 'org.greenrobot:greendao-gradle-plugin:3.3.0' // add plugin
}
}
在你的app模块app/build.gradle文件:
apply plugin: 'org.greenrobot.greendao' // apply plugin
android {
//greendao配置
greendao {
// 指定数据库schema版本号,迁移等 c操作会用到
schemaVersion 1
// 设置生成数据库文件的目录,默认是在build中,可以将生成的文件放到我们的java目录中
targetGenDir 'src/main/java'
// 设置生成的数据库相关文件的包名,默认为entity所在的包名
daoPackage '你的包名.greendao.gen'
}
}
dependencies {
implementation 'org.greenrobot:greendao:3.3.0' // add library
}
2、创建实例类:
@Entity
public class PersonInfo {
@Id(autoincrement = true) //设置自增长
private Long id;
@Index(unique = true) //设置唯一性
private String perNo; //人员编号
private String name; //人员姓名
private String sex; //人员性别
}
其中@Entity是greenDao的实体注解(用于标识当前实体需要greenDao生成代码)。
@Id是主键id,Long 类型,可以通过@Id(autoincrement = true)设置自动增长(自动增长主键不能用基本类型long,只能用包装类型Long)。
@Index(unique = true) 是向数据库添加了唯一约束。
3、自动生成实体类代码:
写完上面实体类代码之后,接下来实体类代码的生成就交给 Android Studio 编译器就可以了,首先我们点击菜单栏中 Build 然后点击 Make Project,等待编译器编译完就可以了,编译完后实体类代码如下所示:
package cnwy.xda.greendaotest.greendao.model;
import org.greenrobot.greendao.annotation.Entity;
import org.greenrobot.greendao.annotation.Id;
import org.greenrobot.greendao.annotation.Index;
import org.greenrobot.greendao.annotation.Generated;
@Entity
public class PersonInfo {
@Id(autoincrement = true) //设置自增长
private Long id;
@Index(unique = true) //设置唯一性
private String perNo; //人员编号
private String name; //人员姓名
private String sex; //人员性别
@Generated(hash = 428129582)
public PersonInfo(Long id, String perNo, String name, String sex) {
this.id = id;
this.perNo = perNo;
this.name = name;
this.sex = sex;
}
@Generated(hash = 1597442618)
public PersonInfo() {
}
public Long getId() {
return this.id;
}
public void setId(Long id) {
this.id = id;
}
public String getPerNo() {
return this.perNo;
}
public void setPerNo(String perNo) {
this.perNo = perNo;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return this.sex;
}
public void setSex(String sex) {
this.sex = sex;
}
}
可以选择将这个实体类序列化(不序列化也可以):
package cnwy.xda.greendaotest.greendao.model;
import android.os.Parcel;
import android.os.Parcelable;
import org.greenrobot.greendao.annotation.Entity;
import org.greenrobot.greendao.annotation.Id;
import org.greenrobot.greendao.annotation.Index;
import org.greenrobot.greendao.annotation.Generated;
@Entity
public class PersonInfo implements Parcelable {
@Id(autoincrement = true) //设置自增长
private Long id;
@Index(unique = true) //设置唯一性
private String perNo; //人员编号
private String name; //人员姓名
private String sex; //人员性别
@Generated(hash = 428129582)
public PersonInfo(Long id, String perNo, String name, String sex) {
this.id = id;
this.perNo = perNo;
this.name = name;
this.sex = sex;
}
@Generated(hash = 1597442618)
public PersonInfo() {
}
protected PersonInfo(Parcel in) {
if (in.readByte() == 0) {
id = null;
} else {
id = in.readLong();
}
perNo = in.readString();
name = in.readString();
sex = in.readString();
}
public static final Creator<PersonInfo> CREATOR = new Creator<PersonInfo>() {
@Override
public PersonInfo createFromParcel(Parcel in) {
return new PersonInfo(in);
}
@Override
public PersonInfo[] newArray(int size) {
return new PersonInfo[size];
}
};
public Long getId() {
return this.id;
}
public void setId(Long id) {
this.id = id;
}
public String getPerNo() {
return this.perNo;
}
public void setPerNo(String perNo) {
this.perNo = perNo;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return this.sex;
}
public void setSex(String sex) {
this.sex = sex;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
if (id == null) {
dest.writeByte((byte) 0);
} else {
dest.writeByte((byte) 1);
dest.writeLong(id);
}
dest.writeString(perNo);
dest.writeString(name);
dest.writeString(sex);
}
}
(这里实现了 Parcelable 接口是为了在 Activity 之间传递实体类,实现接口的方法一直 Alt + Enter 就可以了)
点击编译后,编译器不仅会为我们自动完成实体类代码的生成,还会在 build 目录下生成三个文件 DaoMaster,DaoSession,XXXDao。利用这三个文件我们就可以操作数据库了,如下所示:
核心类之间的关系:
DaoMaster:
使用 greenDAO 的入口点。DaoMaster 负责管理数据库对象(SQLiteDatabase)和 DAO 类(对象),我们可以通过它内部类 OpenHelper 和 DevOpenHelper SQLiteOpenHelper 创建不同模式的 SQLite 数据库。
DaoSession :
管理指定模式下的所有 DAO 对象,DaoSession提供了一些通用的持久性方法比如插入、负载、更新、更新和删除实体。
XxxDAO :
每个实体类 greenDAO 多会生成一个与之对应DAO对象,如:User 实体,则会生成一个一个UserDao 类
Entities:
可持久化对象。通常, 实体对象代表一个数据库行使用标准 Java 属性(如一个POJO 或 JavaBean )。
4、封装数据库操作类:
因为我们对数据库的操作无非就是增删改查四个操作,所以我们将他们简单封装一下。
package cnwy.xda.greendaotest.greendao.manager;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import org.greenrobot.greendao.query.Query;
import java.util.List;
import cnwy.xda.greendaotest.greendao.gen.DaoMaster;
import cnwy.xda.greendaotest.greendao.gen.DaoSession;
import cnwy.xda.greendaotest.greendao.gen.PersonInfoDao;
import cnwy.xda.greendaotest.greendao.model.PersonInfo;
public class DbController {
/**
* Helper
*/
private DaoMaster.DevOpenHelper mHelper; //获取Helper对象
/**
* 数据库
*/
private SQLiteDatabase db;
/**
* DaoMaster
*/
private DaoMaster mDaoMaster;
/**
* DaoSession
*/
private DaoSession mDaoSession;
/**
* 上下文
*/
private Context mContext;
/**
* dao
*/
private PersonInfoDao mPersonInfoDao;
private static DbController mDbController;
/**
* 初始化
* @param context
*/
public DbController(Context context) {
this.mContext = context;
mHelper = new DaoMaster.DevOpenHelper(context,"person.db",null);
mDaoMaster = new DaoMaster(getWritableDatabase());
mDaoSession = mDaoMaster.newSession();
mPersonInfoDao = mDaoSession.getPersonInfoDao();
}
/**
* 获取可读数据库
* @return
*/
private SQLiteDatabase getReadableDatabase(){
if (mHelper == null){
mHelper = new DaoMaster.DevOpenHelper(mContext,"person.db",null);
}
SQLiteDatabase db = mHelper.getReadableDatabase();
return db;
}
/**
* 获取可写数据库
* @return
*/
private SQLiteDatabase getWritableDatabase(){
if (mHelper == null){
mHelper = new DaoMaster.DevOpenHelper(mContext,"person.db",null);
}
SQLiteDatabase db = mHelper.getWritableDatabase();
return db;
}
/**
* 获取单例
*/
public static DbController getInstance(Context context){
if (mDbController == null){
synchronized (DbController.class){
if (mDbController==null){
mDbController = new DbController(context);
}
}
}
return mDbController;
}
/**
* 会自动判定是插入还是替换数据
* @param personInfo
*/
public void insertOrReplace(PersonInfo personInfo){
mPersonInfoDao.insertOrReplace(personInfo);
}
/**
* 插入一条记录,表里面要没有与之相同的记录
* @param personInfo
* @return
*/
public long insert(PersonInfo personInfo){
return mPersonInfoDao.insert(personInfo);
}
/**
* 更新数据
* @param personInfo
*/
public void update(PersonInfo personInfo){
PersonInfo mOldPersonInfo = mPersonInfoDao.queryBuilder()
.where(PersonInfoDao.Properties.Id.eq(personInfo.getId())).build().unique();//拿到之前的记录
if (mOldPersonInfo != null){
mOldPersonInfo.setName("张伟");
mPersonInfoDao.update(mOldPersonInfo);
}
}
/**
* 按条件查询数据
* @param wherecluse
* @return
*/
public List<PersonInfo> searchByWhere(String wherecluse){
Query<PersonInfo> query=mPersonInfoDao.queryBuilder()
.where(PersonInfoDao.Properties.Name.eq(wherecluse)) /*查询name属性一致的数据*/
.orderAsc(PersonInfoDao.Properties.Id)
.build();
return query.list();
}
/**
* 查询所有数据
* @return
*/
public List<PersonInfo> searchAll(){
List<PersonInfo> personInfos = mPersonInfoDao.queryBuilder().list();
return personInfos;
}
/**
* 删除数据
* @param wherecluse
*/
public void delete(String wherecluse){
mPersonInfoDao.queryBuilder().where(PersonInfoDao.Properties.Name.eq(wherecluse)) /*根据name属性查找,然后执行删除*/
.buildDelete().executeDeleteWithoutDetachingEntities();
}
}
5、在activity中使用:
package cnwy.xda.greendaotest;
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
import java.util.List;
import cnwy.xda.greendaotest.greendao.manager.DbController;
import cnwy.xda.greendaotest.greendao.model.PersonInfo;
public class MainActivity extends AppCompatActivity {
private Button btnAdd,btnDelete,btnUpdate,btnSearch;
private TextView tvDataArea;
private EditText etAddPerNo,etAddPerName,etAddPerSex;
private EditText etDelete;
private EditText etSearch;
private DbController mDbController;
private PersonInfo personInfo1,personInfo2,personInfo3,personInfo4;
private long insertTipId;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mDbController = DbController.getInstance(MainActivity.this);
initView();
similateData();
Envent();
}
private void similateData() {
personInfo1 = new PersonInfo(null,"001","王大宝","男");
personInfo2 = new PersonInfo(null,"002","李晓丽","女");
personInfo3 = new PersonInfo(null,"003","王大锤","男");
personInfo4 = new PersonInfo(null,"004","李玲玲","女");
mDbController.insertOrReplace(personInfo1);
mDbController.insertOrReplace(personInfo2);
mDbController.insertOrReplace(personInfo3);
mDbController.insertOrReplace(personInfo4);
}
private void initView() {
btnAdd = findViewById(R.id.btn_add);
btnDelete = findViewById(R.id.btn_delete);
btnUpdate = findViewById(R.id.btn_update);
btnSearch = findViewById(R.id.btn_search);
tvDataArea = findViewById(R.id.text_dataArea);
etAddPerNo = findViewById(R.id.etAddPerNo);
etAddPerName = findViewById(R.id.etAddPerName);
etAddPerSex = findViewById(R.id.etAddPerSex);
etDelete = findViewById(R.id.et_delete);
etSearch = findViewById(R.id.et_search);
}
private void showDataList(){
StringBuilder sb = new StringBuilder();
List<PersonInfo>personInfos = mDbController.searchAll();
for (PersonInfo personInfo:personInfos){
sb.append(" id: ").append(personInfo.getId())
.append(" perNo: ").append(personInfo.getPerNo())
.append(" name: ").append(personInfo.getName())
.append(" sec: ").append(personInfo.getSex())
.append("\n");
}
tvDataArea.setText(sb.toString());
}
private void Envent(){
btnAdd.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String perNo = etAddPerNo.getText().toString().trim();
String perName = etAddPerName.getText().toString().trim();
String perSex = etAddPerSex.getText().toString().trim();
if (perNo.isEmpty()||perName.isEmpty()||perSex.isEmpty()){
Toast.makeText(MainActivity.this,"请输入完整的人员信息",Toast.LENGTH_SHORT).show();
return;
}
mDbController.insertOrReplace( new PersonInfo(null,perNo,perName,perSex));
showDataList();
}
});
btnDelete.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String wherecluse = etDelete.getText().toString().trim();
if (wherecluse.isEmpty()){
Toast.makeText(MainActivity.this,"请输入删除条件",Toast.LENGTH_SHORT).show();
return;
}
mDbController.delete(wherecluse);
showDataList();
}
});
btnUpdate.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mDbController.update(personInfo1);
showDataList();
}
});
btnSearch.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String wherecluse = etSearch.getText().toString().trim();
StringBuilder sb = new StringBuilder();
if (wherecluse.isEmpty()){
Toast.makeText(MainActivity.this,"请输入查询条件",Toast.LENGTH_SHORT).show();
return;
}
List<PersonInfo>personInfos = mDbController.searchByWhere(wherecluse);
if(personInfos!=null&&personInfos.size()>0){
for (PersonInfo personInfo:personInfos){
sb.append("id: ").append(personInfo.getId())
.append("perNo: ").append(personInfo.getPerNo())
.append("name: ").append(personInfo.getName())
.append("sec: ").append(personInfo.getSex())
.append("\n");
}
}else{
Toast.makeText(MainActivity.this,"该数据为空",Toast.LENGTH_SHORT).show();
}
tvDataArea.setText(sb.toString());
}
});
}
}
关于queryBuilde:
参考:Android GreenDao框架使用 进阶篇之queryBuilder
queryBuilder的用法可以通过链式指令来执行,比如
testUserDao.queryBuilder().xx.xx.xx.结束指令。
关于结束指令,如下表:
方法 | 解释 |
.list() | 查询符合条件的数据 |
.buildDelete().executeDeleteWithoutDetachingEntities() | 删除符合条件的数据 |
.count() | 查询符合条件的个数 |
关于条件查询,GreenDao提供了很多方法:
方法 | 解释 |
---|---|
where | 查询条件(where里的条件必须全部符合) |
whereOr | 查询条件(where里的条件有符合就可以) |
offset | 忽略查询出的前n条结果 |
orderAsc | 升序排列 |
orderDesc | 降序排列 |
… | … |
下面是条件查询里面的方法:
方法 | 条件 |
---|---|
eq | == |
notEq | != |
like | 模糊查询 |
between | 两个值的区间 |
in | 范围区间 |
notIn | 不在范围区间 |
gt | > |
lt | < |
ge | >= |
le | <= |
isNull | 为空 |
isNotNull | 不为空 |
无论是where还是whereOr里面的判断语句都可以是一条或多条,区别在于where里是 “ 且 ” 的关系,而whereOr是 “ 或 ”的关系。
QueryBuilder<TestUser> qb = testUserDao.queryBuilder();
List<TestUser> testUsers = qb.where(qb.and(TestUserDao.Properties.Name.eq(name)
,TestUserDao.Properties.Age.eq(12))).list();
QueryBuilder<TestUser> qb = testUserDao.queryBuilder();
List<TestUser> testUsers = qb.where(TestUserDao.Properties.Name.eq(name)
,qb.or(TestUserDao.Properties.Age.eq(12),TestUserDao.Properties.Age.eq(15))).list();