近期应公司要求研究了下GreenDao框架的使用,于是打算记录一下关于GreenDao的使用。
GreenDao的使用
GreenDao就是一个将对象映射到 SQLite 数据库中的轻量且快速的 ORM 解决方案。
GreenDao官网给出的优点
- 性能是AndroidORM中最快的
- 易于使用的API
- 最小的内存消耗
- 强大的社区:超过5000个GitHub明星表明有一个强大而活跃的社区
- 数据库加密:greenDAO支持SQLCipher,以确保用户的数据安全
- 库大小(<100KB),以保持较低的构建时间并避免65k方法限制
GreenDao引入
- 在Project的Bulid中引入:
repositories {
……
mavenCentral() // add repository
}
dependencies {
……
classpath 'org.greenrobot:greendao-gradle-plugin:3.2.2' // add plugin
}
- 在Model的Build中引入
apply plugin: 'org.greenrobot.greendao' // apply plugin
greendao {
schemaVersion 1 //数据库版本号
daoPackage 'com.example.sqlperformancetest.GreenDao'//设置DaoMaster、DaoSession、Dao包名
targetGenDir 'src/main/java'//设置DaoMaster、DaoSession、Dao目录
//targetGenDirTest:设置生成单元测试目录
//generateTests:设置自动生成单元测试用例
}
dependencies {
……
//GreenDao 轻量级数据库连接框架
implementation 'org.greenrobot:greendao:3.2.2'
}
Bean类注册
GreenDao的方便之处在于,当你创建了一个Bean实体类后,可以自动生成DaoMaster.java、DaoSession.java、PlayerDao.java,并且无须自己手动添加get、set函数。
@Entity
public class Player {
@Id//注意:Long型id,如果传入null,则GreenDao会默认设置自增长的值。
private Long Id;
@Unique
private String name;
@Property(nameInDb = "age")
private Integer age;
@Property
private String sex;
}
其中关于各类名词的解释如下:
@Entity:将我们的java普通类变为一个能够被greenDAO识别的数据库类型的实体类
@Id:主键,通过这个注解标记的字段必须是Long类型的,这个字段在数据库中表示它就是主键,并且它默认就是自增的
@NotNull:设置数据库表当前列不能为空
@Uniqu:设置当前数据在表中是唯一值
@Property:设置一个非默认关系映射所对应的列名,默认是使用字段名,例如:@Property(nameInDb = “name”)
@Transient:表明这个字段不会被写入数据库,只是作为一个普通的java类字段,用来临时存储数据的,不会被持久化
@Generated:编译后自动生成的构造函数、方法等的注释,提示构造函数、方法等不能被修改
@ToOne : 建立外键关系 类如:@ToOne(joinProperty = “friendId”)
当写好bean类之后,重新build一下工程就可以看到自己工程中就会出现DaoMaster.java、DaoSession.java、PlayerDao.java三个类以及Bean生成的各个函数。
@Entity
public class Player {
@Id
private Long Id;
@Unique
private String name;
@Property(nameInDb = "age")
private Integer age;
@Property
private String sex;
@Generated(hash = 1076317688)
public Player(Long Id, String name, Integer age, String sex) {
this.Id = Id;
this.name = name;
this.age = age;
this.sex = sex;
}
@Generated(hash = 30709322)
public Player() {
}
public Long getId() {
return this.Id;
}
public void setId(Long Id) {
this.Id = Id;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public Integer getAge() {
return this.age;
}
public void setAge(Integer age) {
this.age = age;
}
public String getSex() {
return this.sex;
}
public void setSex(String sex) {
this.sex = sex;
}
}
数据库操作
当定义好数据库后,就可以对数据库进行操作。我是将他封装为一个DataBaseOperation类,并添加了基础的增删改查。
public class DataBaseOperation {
/**
* 数据库名称
*/
private static final String DATABASE_NAME = "players.db";
private DaoSession mDaoSession;
/**
* 初始化DaoSession
* 即获取一个全局的DaoSession实例
* 可以使用一个单例类单独管理这个对象
*/
public void initDaoSession(Context context) {
MyDevOpenHelper myDevOpenHelper = new MyDevOpenHelper(context,DATABASE_NAME,null);
DaoMaster daoMaster = new DaoMaster(myDevOpenHelper.getWritableDatabase());
mDaoSession = daoMaster.newSession();
}
/**
* 插入一条数据
* insertOrReplace() :当指定主键在表中存在时会覆盖数据,有该数据时则更新
* insert():插入一条记录, 当指定主键在表中存在时会发生异常
* @param player
*/
public void insertData(Player player) {
PlayerDao playerDao = mDaoSession.getPlayerDao();
playerDao.insert(player);
}
/**
* 根据id删除一条数据
* delete(T entity):从数据库中删除给定的实体
* deleteByKey(K key):从数据库中删除给定Key所对应的实体
* deleteInTx(T... entities):使用事务操作删除数据库中给定的实体
* deleteInTx(<T> entities):使用事务操作删除数据库中给定实体集合中的实体
* deleteByKeyInTx(K... keys):使用事务操作删除数据库中给定的所有key所对应的实体
* deleteByKeyInTx(Iterable<K> keys):使用事务操作删除数据库中给定的所有key所对应的实
* @param id
*/
public void deleteData(Long id) {
PlayerDao playerDao = mDaoSession.getPlayerDao();
playerDao.deleteByKey(id);
}
/**
* 删除所有数据
*/
public void deleterAllData(){
PlayerDao playerDao = mDaoSession.getPlayerDao();
playerDao.deleteAll();
}
/**
* 更新一条数据
* 更新年龄
*
* @param id
* @param age
*/
public void updateData(long id, int age) {
PlayerDao playerDao = mDaoSession.getPlayerDao();
Player player = playerDao.queryBuilder()
.where(PlayerDao.Properties.Id.eq(id))
.build()
.unique();
player.setAge(age);
playerDao.update(player);
}
/**
* 获取全部数据,按照Id升序排列
*
* @return 数据列表
*/
public List<Player> getAllData() {
PlayerDao playerDao = mDaoSession.getPlayerDao();
return playerDao.queryBuilder()
.orderAsc(PlayerDao.Properties.Id)
.build()
.list();
}
之后就可以在其他地方调用这些方法了
例如在MainActivity中创建一个Button用于添加数据
DataBaseOperation dataBaseOperation;
protected void onCreate(Bundle savedInstanceState) {
······
dataBaseOperation = new DataBaseOperation();
dataBaseOperation.initDaoSession(this);
}
playerAdd.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
addPlayer();
}
});
private void addPlayer() {
new Thread(new Runnable() {
@Override
public void run() {
try {
Player player = new Player();
player.setId(Long.valueOf(i));
player.setName("小明" + i);
player.setAge(10);
dataBaseOperation.insertData(player);
}
} catch (Exception e) {
Looper.prepare();
Toast.makeText(MainActivity.this, "不能重复添加,请删除", Toast.LENGTH_SHORT).show();
Looper.loop();
}
}
}).start();
}
GreenDao的复杂查询
//查询Sex="男"的列表
playerDao.queryBuilder()
.where(PlayerDao.Properties.Sex.eq("男"))
.list();
//查询name!="小明"的列表
playerDao.queryBuilder()
.where(PlayerDao.Properties.Name.notEq("小明"))
.list();
/**
* like模糊查询
* 模糊查询name="小"的列表
*/
playerDao.queryBuilder()
.where(PlayerDao.Properties.Name.eq("小%"))
.list();
//查询年龄在20-30之间的列表
playerDao.queryBuilder()
.where(PlayerDao.Properties.Age.between(20,30))
.list();
//gt: greater than 半开区间查询,年龄大于18
playerDao.queryBuilder()
.where(PlayerDao.Properties.Age.gt(18))
.list();
//ge: greater equal 半封闭区间查询,年龄大于或者等于18
playerDao.queryBuilder()
.where(PlayerDao.Properties.Age.ge(18))
.list();
//lt: less than 半开区间查询,年龄小于18
playerDao.queryBuilder()
.where(PlayerDao.Properties.Age.lt(18))
.list();
//le: less equal 半封闭区间查询,年龄小于或者等于18
playerDao.queryBuilder()
.where(PlayerDao.Properties.Age.le(18))
.list();
/**
* 多项查询
* 年龄小于等于18并且叫小明的男生
*/
playerDao.queryBuilder()
.where(PlayerDao.Properties.Age.le(18)
,PlayerDao.Properties.Name.eq("小明")
,PlayerDao.Properties.Sex.eq("男"))
.unique();
//名字以"小"开头,年龄升序排序
playerDao.queryBuilder()
.where(PlayerDao.Properties.Name.like("小%"))
.orderDesc(PlayerDao.Properties.Age)
.list();
学习期间参考了以下博主的文章:
总有刁民想杀寡人
weixin_30548917
GreenDao官网