GreenDao的优点
- 性能高,号称Android最快的关系型数据库
- 支持数据库加密 greendao支持SQLCipher进行数据库加密
- 库文件比较小,小于100K
- 内存占用小
GreenDao 3.0的变化
3.0之前需要通过新建GreenDaoGenerator工程生成Java数据对象(实体)和DAO对象,非常的繁琐而且也加大了使用成本。
GreenDao 3.0最大的变化就是采用注解的方式通过编译方式生成Java数据对象和DAO对象。
GreenDao 3.0使用方式
在模块gradle添加如下配置:
apply plugin: 'org.greenrobot.greendao'
greendao{
//schemaVersion表示数据库版本号,每次数据库升级的时候我们修改这里的版本号即可
schemaVersion 1
//targetGenDir表示greenDAO生成的DAOMaster和DaoSession的位置
targetGenDir 'src/main/java'
}
dependencies {
compile 'org.greenrobot:greendao:3.1.0'
}
greendao里面内容配置的含义
- schemaVersion: 数据库schema版本,也可以理解为数据库版本号
- daoPackage:设置DaoMaster 、DaoSession、Dao包名
- targetGenDir:设置DaoMaster 、DaoSession、Dao目录
- targetGenDirTest:设置生成单元测试目录
- generateTests:设置自动生成单元测试用例
在build.gradle添加如下配置:
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath 'org.greenrobot:greendao-gradle-plugin:3.0.0'
}
}
新建实体类
@Entity
public class Teacher {
@Id
private Long id;
@Property(nameInDb = "NAME")
private String username;
@Property(nameInDb = "NICKNAME")
private String nickname;
// 下面的就是自动生成的
public String getNickname() {
return this.nickname;
}
public void setNickname(String nickname) {
this.nickname = nickname;
}
public String getUsername() {
return this.username;
}
public void setUsername(String username) {
this.username = username;
}
public Long getId() {
return this.id;
}
public void setId(Long id) {
this.id = id;
}
@Generated(hash = 407720401)
public Teacher(Long id, String username, String nickname) {
this.id = id;
this.username = username;
this.nickname = nickname;
}
@Generated(hash = 1630413260)
public Teacher() {
}
}
实体类中各个注释的含义
实体@Entity注解
- schema:告知GreenDao当前实体属于哪个schema
- active:标记一个实体处于活动状态,活动实体有更新、删除和刷新方法
- nameInDb:在数据中使用的别名,默认使用的是实体的类名
- indexes:定义索引,可以跨越多个列
- createInDb:标记创建数据库表
基础属性注解
- @Id :主键 Long型,可以通过@Id(autoincrement = true)设置自增长
- @Property:设置一个非默认关系映射所对应的列名,默认是的使用字段名 举例:@Property (nameInDb=”name”)
- @NotNul:设置数据库表当前列不能为空
- @Transient :添加次标记之后不会生成数据库表的列
索引注解
- @Index:使用@Index作为一个属性来创建一个索引,通过name设置索引别名,也可以通过unique给索引添加约束
- @Unique:向数据库列添加了一个唯一的约束
关系注解
- @ToOne:定义与另一个实体(一个实体对象)的关系
- @ToMany:定义与多个实体对象的关系
/**
* 在applicaiton中初始化DatabaseHelper
*/
private DaoMaster.DevOpenHelper getOpenHelper(@NonNull Context context, @Nullable String dataBaseName,String userId) {
closeDbConnections();
return new DaoMaster.DevOpenHelper(new GreenDaoContext(context,userId), dataBaseName, null);
}
GreenDaoContext可以指定生成数据库的位置
public class GreenDaoContext extends ContextWrapper {
private String currentUserId = "default";
private Context mContext;
/**
* 可以根据用户名字来创建不同的数据库,防止出现调用错误的现象
* @param context 系统上下文
* @param userId 用户的标志
*/
public GreenDaoContext(Context context,String userId) {
super(context);
this.mContext = context;
if(!TextUtils.isEmpty(userId)){
this.currentUserId=userId;
}
}
/**
* 获得数据库路径,如果不存在,则创建对象
*
* @param dbName
*/
@Override
public File getDatabasePath(String dbName) {
String path = SdCardUtils.getDatabaseDir(mContext);
StringBuffer buffer = new StringBuffer();
buffer.append(path);
buffer.append(File.separator);
buffer.append(currentUserId);
buffer.append(File.separator);
buffer.append(dbName);
File file=new File(buffer.toString());
if(!file.getParentFile().exists()){
FileUtils.makeFolders(file.getParentFile().getAbsolutePath());
}
return new File(buffer.toString());
}
/**
* 重载这个方法,是用来打开SD卡上的数据库的,android 2.3及以下会调用这个方法。
*
* @param name
* @param mode
* @param factory
*/
@Override
public SQLiteDatabase openOrCreateDatabase(String name, int mode,
SQLiteDatabase.CursorFactory factory) {
SQLiteDatabase result = SQLiteDatabase.openOrCreateDatabase(getDatabasePath(name), factory);
return result;
}
/**
* Android 4.0会调用此方法获取数据库。
*
* @param name
* @param mode
* @param factory
* @param errorHandler
* @see android.content.ContextWrapper#openOrCreateDatabase(java.lang.String, int,
* android.database.sqlite.SQLiteDatabase.CursorFactory,
* android.database.DatabaseErrorHandler)
*/
@Override
public SQLiteDatabase openOrCreateDatabase(String name, int mode, SQLiteDatabase.CursorFactory factory,
DatabaseErrorHandler errorHandler) {
SQLiteDatabase result = SQLiteDatabase.openOrCreateDatabase(getDatabasePath(name), factory);
return result;
}
}
/**
* 拿到可写的数据库对象
*/
private SQLiteDatabase getWritableDatabase() {
return mHelper.getWritableDatabase();
}
/**
* 拿到可读的数据库对象
*/
private SQLiteDatabase getReadableDatabase() {
return mHelper.getReadableDatabase();
}
public DaoSession openWritableDb() throws SQLiteException {
if (daoWriteSession == null) {
daoWriteSession = new DaoMaster(getWritableDatabase()).newSession();
}
return daoWriteSession;
}
之后就可以进行各种增删改查的操作了
。。。
多表联查
一对一的关系
Student
@Id(autoincrement = true)
private Long id;
private String name;
private Long tid;//这是关联的外键
@ToOne(joinProperty = "tid") //这个是注解绑定 tid就是上面一行的tid
private Teacher teacher;
Teacher
@Id
private Long id;
private String name;
Teacher t=new Teacher();
t.setId(110L);
t.setName("teacher");
Student s=new Student();
s.setId(null);
s.setTid(110L);
s.setName("name");
s.setTeacher(t);
一对多:比如一个老师有多个学生
#teacher类中
@ToMany(referencedJoinProperty = "tid")//指定与之关联的其他类的id
private List<Student> studnets;
#student类中
@Id
private Long id;
private Long tid;//这个就是外键 就是teacher的id
多对多一个老师有很多的学生同时一个学生也不止一个老师,这时候需要生成一张中间表,来建立两者之间的联系
//第三张表
@Entity
public class StudentToTeacher {
@Id(autoincrement = true)
private Long id;
//和person关联的id
private Long tid;
//和student关联的id
private Long sid;
}
@Entity
public class Student {
@Id
private Long id;
private String name;
// 对多,@JoinEntity注解:entity 中间表;sourceProperty 实体属性;targetProperty 外链实体属性
@ToMany
@JoinEntity(
entity = StudentToTeacher.class,
sourceProperty = "sid",
targetProperty = "tid"
)
private List<Teacher> teacher;
}
@Entity
Teacher{
@Id(autoincrement = true)
private Long id;
private String name;
// 对多,@JoinEntity注解:entity 中间表;sourceProperty 实体属性;targetProperty 外链实体属性
@ToMany
@JoinEntity(
entity = StudentToTeacher.class,
sourceProperty = "tid",
targetProperty = "sid"
)
private List<Student> students;
}
中间表实际为两者建立了联系,表述了两者的依赖关系,这样针对多张表的操作久没有问题了