作者:邹峰立,微博:zrunker,邮箱:zrunker@yahoo.com,微信公众号:书客创作,个人平台:www.ibooker.cc。
在Android中,对SQLite数据库的操作,是一件很频繁的事情。而greenDao是Android中SQLite数据库的一个ORM框架,它以占用资源少,效率高,而得到广泛使用。
greenDao 3相对于greenDao 2的使用还是有一些区别的。greenDao 3更加精简,采用注解的方式。那么greenDao 3究竟该如何使用呢?
greenDao 3的使用
1、配置app的gradle文件
dependencies {
/*数据库orm-greendao*/
implementation 'org.greenrobot:greendao:3.2.2'
}
apply plugin: 'org.greenrobot.greendao' // apply plugin
// 配置数据库的信息
greendao {
schemaVersion 1 // 对应当前数据库版本
daoPackage 'cc.ibooker.greendao' // 由GreenDao自动生成代码所在的包名,默认的是在项目包下面新建一个gen。
targetGenDir 'src/main/java' // 设置自动生成代码的目录
}
2、配置module的gradle文件
buildscript {
dependencies {
classpath 'org.greenrobot:greendao-gradle-plugin:3.2.2' // add plugin
}
}
注意:github中提示添加maven仓库,但是android studio 项目已经默认包含了jcenter仓库,而jcenter仓库就是maven仓库的一个分支,因此我们不要再添加仓库,直接添加classPath即可。
3、定义实体类,这里定义两个实体类User和Friend。
/**
* 用户表+实体类
* Created by 邹峰立 on 2017/9/23 0023.
*/
@Entity(
// active表示update/delete/refresh 方法是否自动生成,默认为false
active = true,
// createInDb表示是否在数据库中创建该表,默认为true
createInDb = true,
// generateConstructors表示是否生成构造方法(一般有两个,一个有参数,一个无参数),默认为true
generateConstructors = true,
// indexes表示数据表查询返回数据默认排序,name中的字段是该实体在数据表中的列名,value表示改实体的真实名称,unique表示是否唯一(默认为false)
indexes = {@Index(value = "_id ASC"),@Index(value = "uId DESC")},
// nameInDb表示数据表的名称默认为实体类的名称
nameInDb = "t_user",
// 表示是否生成get/set方法,默认为true
generateGettersSetters = true
)
public class User {
@Id(autoincrement = true)
@Property(nameInDb = "_id")
private Long _id;
@NotNull
@Unique
@Property(nameInDb = "u_id")
private long uId;
@Property(nameInDb = "u_realname")
private String uRealName;
@Property(nameInDb = "u_sex")
private String uSex;
@Property(nameInDb = "u_birthday")
private String uBirthday;
@Property(nameInDb = "u_height")
private float uHeight;
@Property(nameInDb = "u_weight")
private float uWeight;
@Property(nameInDb = "u_domicile")
private String uDomicile;
@Property(nameInDb = "u_phone")
private long uPhone;
@Property(nameInDb = "u_email")
private String uEmail;
@Property(nameInDb = "u_weibo")
private String uWeibo;
// 一堆多
@ToMany(referencedJoinProperty = "fUid")
private List<Friend> friends;
public User() {
super();
}
public User(long uId, String uRealName, String uSex, String uBirthday, float uHeight, float uWeight, String uDomicile, long uPhone, String uEmail, String uWeibo) {
this.uId = uId;
this.uRealName = uRealName;
this.uSex = uSex;
this.uBirthday = uBirthday;
this.uHeight = uHeight;
this.uWeight = uWeight;
this.uDomicile = uDomicile;
this.uPhone = uPhone;
this.uEmail = uEmail;
this.uWeibo = uWeibo;
}
public long getuId() {
return uId;
}
public void setuId(long uId) {
this.uId = uId;
}
public String getuRealName() {
return uRealName;
}
public void setuRealName(String uRealName) {
this.uRealName = uRealName;
}
public String getuSex() {
return uSex;
}
public void setuSex(String uSex) {
this.uSex = uSex;
}
public String getuBirthday() {
return uBirthday;
}
public void setuBirthday(String uBirthday) {
this.uBirthday = uBirthday;
}
public float getuHeight() {
return uHeight;
}
public void setuHeight(float uHeight) {
this.uHeight = uHeight;
}
public float getuWeight() {
return uWeight;
}
public void setuWeight(float uWeight) {
this.uWeight = uWeight;
}
public String getuDomicile() {
return uDomicile;
}
public void setuDomicile(String uDomicile) {
this.uDomicile = uDomicile;
}
public long getuPhone() {
return uPhone;
}
public void setuPhone(long uPhone) {
this.uPhone = uPhone;
}
public String getuEmail() {
return uEmail;
}
public void setuEmail(String uEmail) {
this.uEmail = uEmail;
}
public String getuWeibo() {
return uWeibo;
}
public void setuWeibo(String uWeibo) {
this.uWeibo = uWeibo;
}
@Override
public String toString() {
return "User{" +
"uId=" + uId +
", uRealName='" + uRealName + '\'' +
", uSex='" + uSex + '\'' +
", uBirthday='" + uBirthday + '\'' +
", uHeight=" + uHeight +
", uWeight=" + uWeight +
", uDomicile='" + uDomicile + '\'' +
", uPhone=" + uPhone +
", uEmail='" + uEmail + '\'' +
", uWeibo='" + uWeibo + '\'' +
'}';
}
}
/**
* 朋友表+实体类
* Created by 邹峰立 on 2017/9/23 0023.
*/
@Entity(
// active表示update/delete/refresh 方法是否自动生成,默认为false
active = true,
// createInDb表示是否在数据库中创建该表,默认为true
createInDb = true,
// generateConstructors表示是否生成构造方法(一般有两个,一个有参数,一个无参数),默认为true
generateConstructors = true,
// indexes表示数据表查询返回数据默认排序,name中的字段是该实体在数据表中的列名,value表示改实体的真实名称,unique表示是否唯一(默认为false)
indexes = {@Index(value = "_id ASC"),@Index(value = "fId DESC")},
// nameInDb表示数据表的名称默认为实体类的名称
nameInDb = "t_friend",
// 表示是否生成get/set方法,默认为true
generateGettersSetters = true
)
public class Friend {
@Id(autoincrement = true)
@Property(nameInDb = "_id")
private Long _id;
@NotNull
@Unique
@Property(nameInDb = "f_id")
private long fId;// ID
@NotNull
@Property(nameInDb = "f_gname")
private String fGname;// 组名
@NotNull
@Property(nameInDb = "f_uid")
private long fUid;// 用户ID
@ToOne(joinProperty = "fUid")
private User user;
public Friend() {
super();
}
public Friend(long fId, String fGname, long fUid) {
this.fId = fId;
this.fGname = fGname;
this.fUid = fUid;
}
public long getfId() {
return fId;
}
public void setfId(long fId) {
this.fId = fId;
}
public String getfGname() {
return fGname;
}
public void setfGname(String fGname) {
this.fGname = fGname;
}
public long getfUid() {
return fUid;
}
public void setfUid(long fUid) {
this.fUid = fUid;
}
@Override
public String toString() {
return "Friend{" +
"fId=" + fId +
", fGname='" + fGname + '\'' +
", fUid=" + fUid +
'}';
}
}
4、greenDao注解解释
@Entity 用于描述实体类名,其中active表示update/delete/refresh 方法是否自动生成,默认为false.
createInDb 表示是否在数据库中创建表,默认为true,如果为false,将不创建该表.
generateConstructors 表示是否自动生成构造方法(一个有参构造,一个无参构造).
indexes 表示制定查询数据返回的默认排序规则.(@Index中的value制定排序的数据表中的列明加上排序规则即(ASC/DESC),
name 表示......,unique 表示是否唯一即SQL中的去重复
如果按照多个字段来排序可以这样(比如(indexes={@Index(value="ID ASC"),@Index(value="AGE DESC")}或者
indexes={@Index(value="ID ASC AGE DESC")})))
nameInDb 表示该实体对应的数据表的名称,默认为实体名的拼音全大写
generateGettersSetters 表示是否自动生成get/set方法,默认为true
@Id 标识主键,该字段的类型为long或Long类型(推荐Long),autoincrement设置是否自动增长,默认为false
@Property 标识该属性在表中对应的列名称, nameInDb设置名称
@Transient 表示在创建数据表时候忽略这个字段,也就是在创建表的时候不会创建这个字段
@NotNull 设置表中当前列的值不可为空
@Convert 指定自定义类型(@linkPropertyConverter)
@Generated greenDAO运行所产生的构造函数或者方法,被此标注的代码可以变更或者下次运行时清除
@Index 使用@Index作为一个属性来创建一个索引;定义多列索引(@link Entity#indexes())
@JoinEntity 定义表连接关系
@JoinProperty 定义名称和引用名称属性关系
@referencedJoinProperty 表示当前标识的实体对应的数据表的主键
@Keep 注解的代码段在GreenDao下次运行时保持不变
1.注解实体类:默认禁止修改此类
2.注解其他代码段,默认禁止修改注解的代码段
@OrderBy 指定排序
@ToMany 定义与多个实体对象的关系
@ToOne 定义与另一个实体(一个实体对象)的关系
@Unique 向数据库列添加了一个唯一的约束
5、generator构建
点击工具栏build下面的Make Project,对项目进行重新构建,在daoPackage的目录下就会自动生成相应的类(DaoMaster,DaoSession,FriendDao,UserDao),同时对应的实体类也发生改变。
Friend实体类变化后代码:User实体类也发生类似变化
/**
* 朋友表+实体类
* Created by 邹峰立 on 2017/9/23 0023.
*/
@Entity(
// active表示update/delete/refresh 方法是否自动生成,默认为false
active = true,
// createInDb表示是否在数据库中创建该表,默认为true
createInDb = true,
// generateConstructors表示是否生成构造方法(一般有两个,一个有参数,一个无参数),默认为true
generateConstructors = true,
// indexes表示数据表查询返回数据默认排序,name中的字段是该实体在数据表中的列名,value表示改实体的真实名称,unique表示是否唯一(默认为false)
indexes = {@Index(value = "_id ASC"),@Index(value = "fId DESC")},
// nameInDb表示数据表的名称默认为实体类的名称
nameInDb = "t_friend",
// 表示是否生成get/set方法,默认为true
generateGettersSetters = true
)
public class Friend {
@Id(autoincrement = true)
@Property(nameInDb = "_id")
private long _id;
@NotNull
@Unique
@Property(nameInDb = "f_id")
private long fId;// ID
@NotNull
@Property(nameInDb = "f_gname")
private String fGname;// 组名
@NotNull
@Property(nameInDb = "f_uid")
private long fUid;// 用户ID
@ToOne(joinProperty = "fUid")
private User user;
/** Used to resolve relations */
@Generated(hash = 2040040024)
private transient DaoSession daoSession;
/** Used for active entity operations. */
@Generated(hash = 76285035)
private transient FriendDao myDao;
@Generated(hash = 251390918)
private transient Long user__resolvedKey;
public Friend() {
super();
}
public Friend(long fId, String fGname, long fUid) {
this.fId = fId;
this.fGname = fGname;
this.fUid = fUid;
}
@Generated(hash = 1517071117)
public Friend(long _id, long fId, @NotNull String fGname, long fUid) {
this._id = _id;
this.fId = fId;
this.fGname = fGname;
this.fUid = fUid;
}
public long getfId() {
return fId;
}
public void setfId(long fId) {
this.fId = fId;
}
public String getfGname() {
return fGname;
}
public void setfGname(String fGname) {
this.fGname = fGname;
}
public long getfUid() {
return fUid;
}
public void setfUid(long fUid) {
this.fUid = fUid;
}
@Override
public String toString() {
return "Friend{" +
"fId=" + fId +
", fGname='" + fGname + '\'' +
", fUid=" + fUid +
'}';
}
public long get_id() {
return this._id;
}
public void set_id(long _id) {
this._id = _id;
}
public long getFId() {
return this.fId;
}
public void setFId(long fId) {
this.fId = fId;
}
public String getFGname() {
return this.fGname;
}
public void setFGname(String fGname) {
this.fGname = fGname;
}
public long getFUid() {
return this.fUid;
}
public void setFUid(long fUid) {
this.fUid = fUid;
}
/** To-one relationship, resolved on first access. */
@Generated(hash = 736394026)
public User getUser() {
long __key = this.fUid;
if (user__resolvedKey == null || !user__resolvedKey.equals(__key)) {
final DaoSession daoSession = this.daoSession;
if (daoSession == null) {
throw new DaoException("Entity is detached from DAO context");
}
UserDao targetDao = daoSession.getUserDao();
User userNew = targetDao.load(__key);
synchronized (this) {
user = userNew;
user__resolvedKey = __key;
}
}
return user;
}
/** called by internal mechanisms, do not call yourself. */
@Generated(hash = 113038422)
public void setUser(@NotNull User user) {
if (user == null) {
throw new DaoException(
"To-one property 'fUid' has not-null constraint; cannot set to-one to null");
}
synchronized (this) {
this.user = user;
fUid = user.get_id();
user__resolvedKey = fUid;
}
}
/**
* Convenient call for {@link org.greenrobot.greendao.AbstractDao#delete(Object)}.
* Entity must attached to an entity context.
*/
@Generated(hash = 128553479)
public void delete() {
if (myDao == null) {
throw new DaoException("Entity is detached from DAO context");
}
myDao.delete(this);
}
/**
* Convenient call for {@link org.greenrobot.greendao.AbstractDao#refresh(Object)}.
* Entity must attached to an entity context.
*/
@Generated(hash = 1942392019)
public void refresh() {
if (myDao == null) {
throw new DaoException("Entity is detached from DAO context");
}
myDao.refresh(this);
}
/**
* Convenient call for {@link org.greenrobot.greendao.AbstractDao#update(Object)}.
* Entity must attached to an entity context.
*/
@Generated(hash = 713229351)
public void update() {
if (myDao == null) {
throw new DaoException("Entity is detached from DAO context");
}
myDao.update(this);
}
/** called by internal mechanisms, do not call yourself. */
@Generated(hash = 1516049992)
public void __setDaoSession(DaoSession daoSession) {
this.daoSession = daoSession;
myDao = daoSession != null ? daoSession.getFriendDao() : null;
}
}
到这里greenDao的前期准备工作就算完成了,接下来就是对greenDao进行封装和使用。
6、定义DBHelper,让其继承DaoMaster.OpenHelper,并实现抽象方法,其中onUpgrade方法是用于实现数据库升级维护处理。
/**
* OpenHelper
* Created by 邹峰立 on 2017/9/23 0023.
*/
public class DBHelper extends DaoMaster.OpenHelper {
public static final String DBNAME = "ibookerdata.db";
public DBHelper(Context context, String name) {
this(context, name, null);
}
public DBHelper(Context context, String name, SQLiteDatabase.CursorFactory factory) {
super(context, name, factory);
}
/**
* 当数据库版本更新的时候回调函数
*
* @param db 数据库对象
* @param oldVersion 数据库旧版本
* @param newVersion 数据库新版本
*/
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
super.onUpgrade(db, oldVersion, newVersion);
if (newVersion > oldVersion) {
// 创建临时表
// 复制旧数据到临时表
// 数据库(表)删除
// 临时表重命名
}
}
}
7、创建greenDao管理类GreenDaoManager,在该类中实现对DaoMaster和DaoSession的管理。
/**
* GreenDao管理类
*/
public class GreenDaoManager {
private DaoMaster mDaoMaster;
private DaoSession mDaoSession;
private static volatile GreenDaoManager mInstance = null;
// 构造方法
private GreenDaoManager() {
if (mInstance == null) {
// 重写DBHelper数据库升级,数据不丢失
// MyApplication.getContext()上下文表示了数据库存储路径为手机内存
DBHelper helper = new DBHelper(MyApplication.getInstance(), DBHelper.DBNAME, null);
mDaoMaster = new DaoMaster(helper.getWritableDatabase());
mDaoSession = mDaoMaster.newSession();
}
}
// 单例模式
public static GreenDaoManager getInstance() {
if (mInstance == null) {
synchronized (GreenDaoManager.class) {
if (mInstance == null) {
mInstance = new GreenDaoManager();
}
}
}
return mInstance;
}
public DaoMaster getMaster() {
return mDaoMaster;
}
public DaoSession getSession() {
return mDaoSession;
}
// 获取新的DaoSession
public DaoSession getNewSession() {
mDaoSession = mDaoMaster.newSession();
return mDaoSession;
}
// 打印查询日志
public static void enableQueryBuilderLog(){
QueryBuilder.LOG_SQL = true;
QueryBuilder.LOG_VALUES = true;
}
}
同时自定义Application,实现GreenDaoManager初始化工作。
/**
* 自定义MyApplication
* Created by 邹峰立 on 2017/9/23 0023.
*/
public class MyApplication extends Application {
private static MyApplication instance;
@Override
public void onCreate() {
super.onCreate();
// 全局上下文赋值
instance = this;
// 初始化数据库
GreenDaoManager.getInstance();
}
// 获取全局上下文对象
public static MyApplication getInstance() {
return instance;
}
}
注意:最后要在中进行引用
<application
android:name="cc.ibooker.myapplition.MyApplication"
...
</application>
8、封装数据库表相应的管理类。
/**
* 对数据库t_user进行管理
* Created by 邹峰立 on 2017/9/23 0023.
*/
public class UserDbUtil {
private static volatile UserDbUtil mInstance = null;
private UserDao userDao;
// 构造方法
private UserDbUtil() {
if (mInstance == null) {
userDao = GreenDaoManager.getInstance().getSession().getUserDao();
}
}
// 单例
public static UserDbUtil getInstance() {
if (mInstance == null) {
synchronized (UserDbUtil.class) {
if (mInstance == null) {
mInstance = new UserDbUtil();
}
}
}
return mInstance;
}
// 查询全部用户信息
private List<User> queryAll() {
List<User> users = userDao.queryBuilder().list();
for (User user : users)
Log.d("queryAll", user.toString());
return users;
}
...
}
/**
* 朋友表t_friend进行管理
* Created by 邹峰立 on 2017/9/23 0023.
*/
public class FriendDbUtil {
private static volatile FriendDbUtil mInstance = null;
private FriendDao friendDao;
// 构造方法
private FriendDbUtil() {
if (mInstance == null) {
friendDao = GreenDaoManager.getInstance().getSession().getFriendDao();
}
}
// 单例
public static FriendDbUtil getInstance() {
if (mInstance == null) {
synchronized (UserDbUtil.class) {
if (mInstance == null) {
mInstance = new FriendDbUtil();
}
}
}
return mInstance;
}
...
}
9、使用
这里只需要调用相应表的管理类就可以实现对表的增删改查。如:查询全部用户信息。
UserDbUtil userDbUtil = UserDbUtil.getInstance();
List<User> user = userDbUtil.queryAll();