greenDao是一个将对象(java对象)映射到SQLite数据库中的轻量且快速的ORM解决方案。
对象关系映射(英语:(Object Relational Mapping,简称ORM,或O/RM,或O/R mapping),是一种程序技术,用于实现面向对象编程语言里不同类型系统的数据之间的转换
1. 什么是greenDao
弄明白greenDao之前我们应该先了解什么是ORM(Object Relation Mapping 即 对象关系映射),说白了就是将面向对象编程语言里的对象与数据库关联起来的一种技术,而greenDao就是实现这种技术之一,所以说greenDao其实就是一种将java object 与SQLite Database关联起来的桥梁,它们之间的关系 如下图所示;
greenDao可以说是当今最流行,最高效而且还在迭代的关系型数据库。而且greenDao3.0还支持RxJava操作,greenDao如此受欢迎离不开以下几点:
● 存取速度快
每秒中可以操作数千个实体
● 支持数据库加密
支持android原生的数据库SQLite,也支持SQLCipher(在SQLite基础上加密型数据库)。
● 轻量级
greenDao的代码库仅仅100k大小
● 激活实体
处于激活状态下的实体可以有更多操作方法
● 支持缓存
能够将使用的过的实体存在缓存中,下次使用时可以直接从缓存中取,这样可以使性能提高N个数量级
● 代码自动生成
greenDao 会根据modle类(java bean类)自动生成实体类(entities)和Dao对象,并且Dao对象是根据entities类量身定做的并且一 一对应。
总结
1、一个精简的库
2、性能最大化
3、内存开销最小化
4、易于使用的 APIs
5、对 Android 进行高度优化
GreenDao 3.0采用注解的方式来定义实体类,通过gradle插件生成相应的代码。
例子
module gradle
apply plugin: 'org.greenrobot.greendao' // apply plugin
dependencies {
//greendao插件
compile 'org.greenrobot:greendao:3.2.2'
// add library例子中用到了xlistview
implementation project(':xlistviewlibrary')
}
//配置数据库信息
greendao {
schemaVersion 1//数据库版本号
daoPackage 'com.anye.greendao.gen'
targetGenDir 'src/main/java'
}
属性介绍:
schemaVersion--> 指定数据库schema版本号,也可以理解成数据库版本号,迁移等操作会用到;
daoPackage --> dao的包名,包名默认是entity所在的包;(可以自定义输出目录,如果不定义,默认是entity的包)
targetGenDir --> 生成数据库文件的目录;/设置DaoMaster 、DaoSession、Dao目录,这个是greendao默认生成的三个重要的类
根gradle
dependencies {
classpath 'org.greenrobot:greendao-gradle-plugin:3.2.2' //greenDao生产代码插件
}
核心类
DaoMaster:
是GreenDao的入口也是greenDao顶级对象,对于一个指定的表单持有数据库对象(SQLite数据库)并且能够管理DAO类
能够创建表和删除表
其内部类OpenHelper 与DevOpenHelper是创建SQlite数据库的SQLiteOpenHelper的具体实现
DaoSession:
对于一个指定的表单可以管理所有的Dao 对象。
也能够对实体类执行 insert ,load,update,refresh.delete操作。
DaoSession也能跟踪 identity scope:即session查询后的实体会存在缓存中,并给该实体生成一个flag来追踪该实体,下次再次查询时会直接从缓存中取出来而不是从数据库中取出来
DAOS
能够持久访问和查询实体类
比起DaoSession有更多的持久化方法 count, loadAll,insertInt等等;
Entities
自动生成的代码,一般情况下与javaBean对象的属性一一对应。
构建Model类
Molde类需要用java类来定义并且可以通过GreenDao中的注释来表明Model中的每个属性在数据库的中该如何定义;定义model类后点击Make project选项GreenDao就会自动生成DaoMaster,DaoSession,和DAOS类,生成的代码将会保存在预先在budle gradle中设置的位置,GreenDao 通过注释来定义表单与实体
@Entity
● 告诉GreenDao 该Bean类需要持久化。只有使用@Entity注释的Bean类才能被dao类操作;
● @Entity可以在不使用参数下使用,但是也可以给Entity配置参数,其参数如下
类注释:
//如果该实体属于多个表单,可以使用该参数;
schema = "myschema",
// 该实体属于激活状态,激活状态的实体有更新,删除,刷新方法;
active = true,
// 给这个表指定一个名字,默认情况下名字是类名
nameInDb = "AWESOME_USERS",
// 可以给多个属性定义索引和其他属性.
indexes = { @Index(value = "name DESC", unique = true) },
//是否使用GreenDao创建该表.
createInDb = false,
// 是否所有的属性构造器都应该被生成,无参构造器总是被要求
generateConstructors = true,
// 如果该类中没有set get方法是否自动生成
generateGettersSetters = true
属性注解:
● @ID 一般会选择long/Long属性作为Entity ID(即数据库中的主键)autoincrement=true表示主键会自增如果false就会使用旧值
● @Property 可以自定义一个该属性在数据库中的名称,默认情况下数据库中该属性名称是Bean对象中的 属性名但是不是以驼峰式而是以大写与下划线组合形式来命名的比如:customName将命名为 CUSTOM_NAME;注意:外键不能使用该属性;
● @NotNull 确保属性值不会为null值;
● @Transient 使用该注释的属性不会被存入数据库中;
● @Unique 将属性变成唯一约束属性;也就是说在数据库中该值必须唯一
● @Generated 提示开发者该属性不能被修改;并且实体类的方法,属性,构造器一旦被@Generated注释就不能被再次修改,否则或报错
● 主键限制
每个实体类都应该有一个long或者LONG型属性作为主键;如果你不想用long或者LONG型作为主键,你可以使用一个唯一索引(使用@Index(unique = true)注释使普通属性改变成唯一索引属性)属性作为关键属性。
@Id
private Long id;
@Index(unique = true)
private String key;
● 索引属性
使用@Index 可以将一个属性变为数据库索引;其有两个参数
● name :不使用默认名称,自定义索引名称
● unique : 给索引增加一个唯一约束,迫使该值唯一
@Entity
public class User {
@Id
private Long id;
@Index(unique = true)
private String name;
}
● 核心代码初始化
创建数据库过程
// 下面代码仅仅需要执行一次,一般会放在application
helper = new DaoMaster.DevOpenHelper(this, "notes-db", null);
db = helper.getWritableDatabase();
daoMaster = new DaoMaster(db);
daoSession = daoMaster.newSession();
// 在activity或者fragment中获取Dao对象
noteDao = daoSession.getNoteDao()
查询操作
- eq():==
- noteq():!=
- gt(): >
- lt():<
- ge:>=
- le:<=
- like():包含
- between:俩者之间
- in:在某个值内
- notIn:不在某个值内
● 分页查询
○ limit(int): 限制查询的数量;
○ offset(int): 每次返回的数量; offset不能单独使用;
例子
第三方库初始化
public class MApp extends Application {
public static Context context;
@Override
public void onCreate() {
super.onCreate();
context = getApplicationContext();
//第三方库初始化
GreenDaoUtil.getInstance().init();
}
}
工具类
/**
* 封装greendao,orm框架
*/
public class GreenDaoUtil {
private DaoMaster daoMaster;
private DaoSession daoSession;
private DaoMaster.DevOpenHelper devOpenHelper;
private SQLiteDatabase sqLiteDatabase;
private volatile static GreenDaoUtil greenDaoUtil;
private GreenDaoUtil() {
}
/**
* 双重检查锁:
* 单例模式实现,不加同步锁,多线程同时调用这个方法的时候,可能会创建多个对象,
* 加上同步锁,同一时刻只能有一个线程访问
*/
public static GreenDaoUtil getInstance(){
if (greenDaoUtil == null) {
synchronized (GreenDaoUtil.class) {
if (greenDaoUtil == null) {
greenDaoUtil = new GreenDaoUtil();
}
}
}
return greenDaoUtil;
}
public void init() {
setDataBase();
}
/**
* 初始化greendao自动生成的几个重要对象*/
private void setDataBase() {
devOpenHelper = new DaoMaster.DevOpenHelper(MApp.context, "lq-db", null);
sqLiteDatabase = devOpenHelper.getWritableDatabase();
daoMaster = new DaoMaster(sqLiteDatabase);
daoSession = daoMaster.newSession();
}
public DaoSession getDaoSession() {
return daoSession;
}
public SQLiteDatabase getSqLiteDatabase(){
return sqLiteDatabase;
};
}
entity类通过@Entity注解后
来生成
/**
* 实体类,实际上就是通过greendao链接数据库的一个javabean类
* 和greendao通过注解关联@Entity
*/
@Entity(nameInDb = "user2",active = true)
public class User {
@Id(autoincrement = true)
private Long _id;
private String name;
private int age;
private String sex;
/** Used to resolve relations */
@Generated(hash = 2040040024)
private transient DaoSession daoSession;
/** Used for active entity operations. */
@Generated(hash = 1507654846)
private transient UserDao myDao;
@Generated(hash = 486379655)
public User(Long _id, String name, int age, String sex) {
this._id = _id;
this.name = name;
this.age = age;
this.sex = sex;
}
@Generated(hash = 586692638)
public User() {
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public Long get_id() {
return this._id;
}
public void set_id(Long _id) {
this._id = _id;
}
/**
* 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 = 2059241980)
public void __setDaoSession(DaoSession daoSession) {
this.daoSession = daoSession;
myDao = daoSession != null ? daoSession.getUserDao() : null;
}
}
对数据库进行增删改查
public class MainActivity extends AppCompatActivity implements View.OnClickListener,XListView.IXListViewListener {
private static final String TAG = "MainActivity";
private UserDao userDao;
List<User> list = new ArrayList<>();
private XListView xListView;
private EditText input_id;
private EditText input_name;
private EditText input_age;
private EditText input_sex;
private User user;
private int page = 1;
private MAdapter mAdapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
}
private void initView() {
Button dantiao1 = (Button) findViewById(R.id.dantiao1);
Button piliang1 = (Button) findViewById(R.id.piliang1);
Button update1 = (Button) findViewById(R.id.update1);
Button delete1 = (Button) findViewById(R.id.delete1);
Button select_primary1 = (Button) findViewById(R.id.select_primary1);
Button selectall = (Button) findViewById(R.id.selectall);
Button limit1 = (Button) findViewById(R.id.limit1);
xListView = (XListView) findViewById(R.id.xlv);
input_id = (EditText) findViewById(R.id.input_id);
input_name = (EditText) findViewById(R.id.input_name);
input_age = (EditText) findViewById(R.id.input_age);
input_sex = (EditText) findViewById(R.id.input_sex);
dantiao1.setOnClickListener(this);
piliang1.setOnClickListener(this);
update1.setOnClickListener(this);
delete1.setOnClickListener(this);
select_primary1.setOnClickListener(this);
selectall.setOnClickListener(this);
limit1.setOnClickListener(this);
DaoSession daoSession = GreenDaoUtil.getInstance().getDaoSession();
userDao = daoSession.getUserDao();
xListView.setPullLoadEnable(true);
xListView.setPullRefreshEnable(true);
xListView.setXListViewListener(this);
xListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> adapterView, View view, int i, long l) {
user = list.get(i);
input_id.setText(user.get_id() + "");
input_name.setText(user.getName());
input_age.setText(user.getAge()+"");
input_sex.setText(user.getSex());
}
});
}
@Override
public void onClick(View view) {
switch (view.getId()) {
case R.id.dantiao1:
// 单条添加
addData("lq" + "单条插入");
queryData();
break;
case R.id.piliang1:
// 批量添加
for (int i = 0; i < 5; i++) {
addData("lq" + "多条插入" + i);
}
queryData();
break;
case R.id.update1:
// 修改
update();
queryData();
break;
case R.id.delete1:
// 删除
delete();
queryData();
break;
case R.id.select_primary1:
// 查询主键下单条数据
String sid = input_id.getText().toString();
long id = Long.parseLong(sid);
queryById(id);
break;
case R.id.selectall:
// 查询所有数据
Log.d(TAG, "onClick: +++++++++++++++");
queryData();
break;
case R.id.limit1:
// 分页查询
limitSelect(0);
break;
}
}
private void limitSelect(int page){
Query<User> query = userDao.queryBuilder().offset(page*10).limit(10).build();
List<User> list1 = query.list();
list.addAll(list1);
MAdapter mAdapter = new MAdapter(list, MainActivity.this);
xListView.setAdapter(mAdapter);
uiComplete();
}
private void queryById(Long id) {
Query<User> query = userDao.queryBuilder().where(UserDao.Properties._id.eq(id)).build();
List<User> list1 = query.list();
MAdapter mAdapter = new MAdapter(list1, MainActivity.this);
xListView.setAdapter(mAdapter);
}
private void queryData() {
Query<User> query = userDao.queryBuilder().build();
list = query.list();
mAdapter = new MAdapter(list, MainActivity.this);
xListView.setAdapter(mAdapter);
uiComplete();
}
private void addData(String name) {
User user = new User();
user.setAge(18);
user.setName(name);
user.setSex("man");
//添加数据库操作
userDao.insert(user);
}
private void delete() {
userDao.delete(user);
clear();
}
private void clear() {
input_id.setText("");
input_name.setText("");
input_age.setText("");
input_sex.setText("");
}
private void update() {
String sid = input_id.getText().toString();
long id = Long.parseLong(sid);
String name = input_name.getText().toString();
String ages = input_age.getText().toString();
int age = Integer.parseInt(ages);
String sex = input_sex.getText().toString();
userDao.update(new User(id,name,age,sex));
clear();
}
@Override
public void onRefresh() {
limitSelect(0);
uiComplete();
}
@Override
public void onLoadMore() {
Log.d(TAG, "onLoadMore: "+page);
limitSelect(page);
page++;
uiComplete();
}
/**
* 让刷新头 或者刷新底部ui返回;
*/
private void uiComplete(){
xListView.stopRefresh();//停止刷新
xListView.stopLoadMore();//停止上拉加载更多
xListView.setRefreshTime("刚刚");
}
}
adapter
public class MAdapter extends BaseAdapter {
private List<User> list;
private Context context;
public MAdapter(List<User> list, Context context) {
this.list = list;
this.context = context;
}
@Override
public int getCount() {
return list.size();
}
@Override
public Object getItem(int i) {
return null;
}
@Override
public long getItemId(int i) {
return 0;
}
@Override
public View getView(int i, View view, ViewGroup viewGroup) {
ViewHolder viewHolder ;
if (view == null) {
view = LayoutInflater.from(context).inflate(R.layout.list_item, null);
viewHolder = new ViewHolder();
viewHolder.textView = view.findViewById(R.id.item_tv);
view.setTag(viewHolder);
}else{
viewHolder = (ViewHolder) view.getTag();
}
User user = list.get(i);
viewHolder.getTextView().setText(user.get_id() +"-"+ user.getName() +"-"+ user.getAge() +"-"+ user.getSex());
return view;
}
class ViewHolder{
private TextView textView;
public TextView getTextView() {
return textView;
}
}
}
布局
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.bwie.greendaodemo1.MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:id="@+id/dantiao1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="单条添加" />
<Button
android:id="@+id/piliang1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="批量添加" />
<Button
android:id="@+id/update1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="修改" />
<Button
android:id="@+id/delete1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="删除" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<Button
android:id="@+id/select_primary1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="查询主键下单条数据" />
<Button
android:id="@+id/selectall"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="查询所有数据" />
<Button
android:id="@+id/limit1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="分页查询" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="id:"/>
<EditText
android:id="@+id/input_id"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="姓名:"/>
<EditText
android:id="@+id/input_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="年龄:"/>
<EditText
android:id="@+id/input_age"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="性别"/>
<EditText
android:id="@+id/input_sex"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1" />
</LinearLayout>
<com.bwie.xlistviewlibrary.View.XListView
android:id="@+id/xlv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"/>
</LinearLayout>