greenDAO 3.0
greenDAO 是一个对象关系映射(ORM)的框架,能够提供一接口通过操作对象的方式去操作关系型数据库,它能够让你操作数据库是更简单、更方便。
1.greenDAO 优点
- 性能高
- 内存占用小
- 库文件比较小,小于100K,编译时间低,而且可以避免65K方法限制
- 支持数据库加密,greenDAO 支持 SQLCipher 进行数据库加密
- 简洁易用的API
greenDAO 3.0 采用注解的方式通过编译方式生成 Java 数据对象和 DAO 对象
2.greenDAO 使用
添加依赖。在 build.gradle添加如下配置
// In your root build.gradle file:
buildscript {
repositories {
jcenter()
mavenCentral() // add repository
}
dependencies {
classpath 'com.android.tools.build:gradle:2.3.3'
classpath 'org.greenrobot:greendao-gradle-plugin:3.2.2' // add plugin
}
}
// In your app projects build.gradle file:
apply plugin: 'com.android.application'
apply plugin: 'org.greenrobot.greendao' // apply plugin
dependencies {
compile 'org.greenrobot:greendao:3.2.2' // add library
}
greenDAO 自动生成的 DaoMaster、DaoSession、Dao,默认位置为 ../app/build/generated/source/greendao/packgename
,如果想指定生成DaoMaster、DaoSession、Dao 的位置,需要在 build.gradle添加如下配置:
greendao {
schemaVersion 1 //指定数据库schema版本号,迁移等操作会用到
daoPackage 'com.zhang.greendaodemo.dao' //dao的包名,包名默认是entity所在的包
targetGenDir 'src/main/java'
}
- schemaVersion: 数据库schema版本,也可以理解为数据库版本号
- daoPackage: 设置DaoMaster、DaoSession、Dao包名
- targetGenDir:设置DaoMaster、DaoSession、Dao目录
- targetGenDirTest: 设置生成单元测试目录
- generateTests: 设置自动生成单元测试用例
3.新建实体类
新建如下实体类,点击 Make Project
,会自动生成 Setter and Getter
并创建对应的DAO文件。
@Entity
public class User {
@Id(autoincrement = true)
private Long id;
@Property(nameInDb = "STUDENTNUM")
private String studentNum;
@Property(nameInDb = "NAME")
@NotNull
private String name;
}
1.实体类 @Entity 注解
- schema : 告知greenDAO当前实体属于哪个schema
- active : 标记一个实体处于活动状态,活动实体有更新、删除和刷新方法
- nameInDb : 在数据库中使用的别名,默认使用的是实体的类名
- indexes : 定义索引,可以跨越多个列
- createInDb : 标记创建数据库表
2.基础属性注解
- @Id : 主键 Long 型,可以通过
@Id(autoincrement = true)
设置自增长 - @Property : 设置一个非默认关系映射所对应的列名,默认的是使用字段名。E.g.
@Property(nameInDb = "STUDENTNUM")
- @NotNull : 设置数据库当前列不能为空
- @Transient : 添加此标记之后不会生成数据库表的列
3.索引注解
- @Index : 使用
@Index
作为一个属性来创建一个索引,通过 name 设置索引别名,也可以通过 unique 给索引添加约束 - @Unique : 向数据库添加了一个唯一的约束
4.关系注解
- @ToOne :定义与另一个实体(一个实体对象)的关系,通过joinProperty参数来定义一个外键。
public class Order {
@Id
private Long id;
private long customerId;
@ToOne(joinProperty = "customerId")
private Customer customer;
}
@Entity
public class Customer {
@Id
private Long id;
}
Customer 表通过 id 与 Order 表关联,查询 Order 的 Customer 是需要先知道 Order 中的 customerId 然后根据 id = customerId 值在去数据库中查询该id所对应的 Customer 对象。
然而在 greenDAO 中只需要使用 @ToOne注释定义一个关联对象即可。这样只要获得 Order 对象就可以通过 getCustomer()
方法回去 Order 所对应的 Customer了。
@ToMany : 定义与多个实体对象的关系
- referencedJoinProperty 在目标实体中我们需要定义一个与源实体关联起来的外键,即 Order 中的 customerId ,然后需要在源实体里我们需要将 customerId 作为 referencedJoinProperty的属性。
@Entity
public class Customer {
@Id private Long id;
@ToMany(referencedJoinProperty = "customerId")
@OrderBy("date ASC")
private List<Order> orders;
}
@Entity
public class Order {
@Id private Long id;
private Date date;
private long customerId;
}
- joinProperties。在 referencedJoinProperty 参数中我们发现两个实体关联的外键是 CustomerId 与 id,但是如果我们的需求是外键不能通过 id 来定义,需要用自己自定义属性来定义,第一种方法就没有用了,而 joinProperties 就是为了解决这个需求的。
@Entity
public class Customer {
@Id private Long id;
@Unique private String tag;
@ToMany(joinProperties = {
@JoinProperty(name = "tag", referencedName = "customerTag")
})
@OrderBy("date ASC")
private List<Site> orders;
}
@Entity
public class Order {
@Id private Long id;
private Date date;
@NotNull private String customerTag;
}
如果改为
@ToMany(joinProperties = {
@JoinProperty(name = "id", referencedName = "customerId")
})
这样的话就和第一种方法实现原理是一样的了。
4.创建数据库管理类
public class DBMaster {
// 是否加密
public static final boolean ENCRYPTED = false;
private static String DB_NAME = "student.db";
private static DaoMaster.DevOpenHelper mHelper;
private static DaoMaster mDaoMaster;
private static DaoSession mDaoSession;
private static volatile DBMaster instance = null;
private DBMaster() {
initDatabase();
}
public static DBMaster getInstance() {
if (instance == null) {
synchronized (DBMaster.class) {
if (instance == null) {
instance = new DBMaster();
}
}
}
return instance;
}
/**
* 初始化greenDao,这个操作建议在Application初始化的时候添加;
*/
public static void initDatabase() {
mHelper = new DaoMaster.DevOpenHelper(context, DB_NAME, null);
getDaoMaster(context);
getDaoSession(context);
mDaoSession = mDaoMaster.newSession();
}
/**
* 获取可读数据库
*/
public static SQLiteDatabase getReadableDatabase() {
if (null == mHelper) {
getInstance();
}
return mHelper.getReadableDatabase();
}
/**
* 获取可写数据库
*/
public static SQLiteDatabase getWritableDatabase() {
if (null == mHelper) {
getInstance();
}
return mHelper.getWritableDatabase();
}
/**
* 获取DaoMaster
*/
public static DaoMaster getDaoMaster(Context context) {
if (null == mDaoMaster) {
synchronized (DBMaster.class) {
if (null == mDaoMaster) {
MyOpenHelper helper = new MyOpenHelper(context, DB_NAME, null);
if (ENCRYPTED) {
mDaoMaster = new DaoMaster(helper.getEncryptedWritableDb(DB_NAME)); // 加密数据库
} else {
mDaoMaster = new DaoMaster(helper.getWritableDatabase());
}
}
}
}
return mDaoMaster;
}
/**
* 获取DaoSession
*/
public static DaoSession getDaoSession(Context context) {
if (null == mDaoSession) {
synchronized (DBMaster.class) {
mDaoSession = getDaoMaster(context).newSession();
}
}
return mDaoSession;
}
}
可以在 Application.java中进行数据库初始化工作。
public class MyApplication extends Application{
public static Context context;
@Override
public void onCreate() {
context = this;
super.onCreate();
GreenDaoHelper.initDatabase();
}
}
5.数据库操作
1.获取 DAO
private StudentMsBeanDao studentMsBeanDao;
studentMsBeanDao = DBMaster.getmDaoSession(getApplicationContext()).getStudentMsBeanDao();
2.插入数据
/**
* 插入数据
*/
private void insert(StudentMsBean studentMsBean) {
studentMsBeanDao.insert(studentMsBean);
// studentMsBeanDao.insertOrReplace(studentMsBean); // 插入或新增
// studentMsBeanDao.save(studentMsBean); // 插入或新增,相较于 insertOrReplace(Object) 可能更有效率,因为如果key已经存在,则不必查询该key是否已经存在
}
/**
* 插入数据集合
*/
private void insertList(List<StudentMsBean> students){
if(students == null || students.isEmpty()){
return;
}
studentMsBeanDao.insertInTx(students);
// studentMsBeanDao.insertOrReplaceInTx(students);
// studentMsBeanDao.saveInTx(students);
// studentMsBeanDao.saveInTx(student1,student2,student3);
}
4.删除数据
// 删除某一项
studentMsBeanDao.delete(studentMsBean);
// 根据主键删除数据
studentMsBeanDao.deleteByKey((long) 1);
// 删除全部
studentMsBeanDao.deleteAll();
// 删除多个数据
studentMsBeanDao.deleteInTx(java.lang.Iterable<T> entities);
// 删除多个数据
studentMsBeanDao.deleteInTx(studentMsBean1,studentMsBean2,studentMsBean3);
// 根据 key 删除多个数据
deleteByKeyInTx(java.lang.Iterable<K> keys);
5.修改数据
// 修改某项数据
studentMsBeanDao.update(studentMsBean);
6.查询数据
private void query() {
// 查询全部数据
List<StudentMsBean> list = studentMsBeanDao.loadAll();
// 查询一条数据
StudentMsBean studentMsBean = studentMsBeanDao.queryBuilder()
.where(StudentMsBeanDao.Properties.Name.eq("卫子夫"))
.build()
.unique();
}
运算符
运算符 | 作用 |
---|---|
eq | = |
notEq | <> |
like | LIKE |
between | BETWEEN … AND … |
in | IN (…, …, …) |
notIn | NOT IN (…, …, …) |
ge | > |
le | < |
isNull | IS NULL |
isNotNull | IS NOT NULL |
6.数据库加密
greenDAO 支持数据库加密,以保护敏感数据。greenDAO是直接支持 SQLCipher
的。SQLCipher是一个自定义使用256位的AES加密的SQLite。
1.添加依赖库
compile 'net.zetetic:android-database-sqlcipher:3.5.1' // 数据库加密依赖库
2.修改 GreenDaoHelper 类
// 获取加密的DaoMaster
mDaoMaster = new DaoMaster(mHelper.getEncryptedWritableDb(DB_NAME);
3.查询加密结果
// 查询一条数据
StudentMsBean studentMsBean = studentMsBeanDao.queryBuilder()
.where(StudentMsBeanDao.Properties.Name.eq("卫子夫"))
.build()
.unique();
7.数据库升级
如果我们需要在实体类中增加一个字段或者改变字段属性等,就需要版本更新来保存之前的数据了。
- 使用 MigrationHelper
- 数据库更新表的方法是 DaoMaster 类中的
onUpgrade
方法,需要构建 MyOpenHelper 帮助类,重写onUpgrade
方法。
public class MyOpenHelper extends DaoMaster.OpenHelper {
public MyOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory) {
super(context, name, factory);
}
@Override
public void onUpgrade(Database db, int oldVersion, int newVersion) {
// 操作数据库的更新 有几个表升级都可以传入到下面
MigrationHelper.getInstance().migrate(db, StudentMsBeanDao.class);
}
}
- 使用 MyOpenHelper 类。需要修改获取 DaoMaster 的方法。使用 MyOpenHelper 代替默认的 DaoMaster.DevOpenHelper来获取 mDaoMaster。
/**
* 获取DaoMaster
*/
public static DaoMaster getDaoMaster(Context context) {
if (null == mDaoMaster) {
synchronized (DBMaster.class) {
if (null == mDaoMaster) {
MyOpenHelper helper = new MyOpenHelper(context, DB_NAME, null);
if (ENCRYPTED) {
mDaoMaster = new DaoMaster(helper.getEncryptedWritableDb(DB_NAME)); // 加密数据库
} else {
mDaoMaster = new DaoMaster(helper.getWritableDatabase());
}
}
}
}
return mDaoMaster;
}
4.在 build.gradle 中升级版本
greendao {
schemaVersion 2 //指定数据库schema版本号,迁移等操作会用到
}