[Android]来试试移动端sqlite数据库最高效的框架GreenDao3

前言

greenDAO作为Android移动端的一款开源的orm框架,因其快速开发,而且小而快,为众多安卓程序员所知,成为一款热门,现在迎来了更便捷的3.0+版本,主要亮点就是提供了注解。官网又快速使用的教程How To Start!


greenDAO的特性
最大的性能 (可能是最快的ORM Android);我们的基准是开源易于使用的 强大的api
最小的 内存消耗
jar包很小(< 100 kb),减少构建时间,避免65 k方法限制
数据库加密 :greenDAO支持SQLCipher保证用户的数据安全
强大的社区 :GitHub热门支持https://github.com/greenrobot/greenDAO/

基本使用

按惯例先看demo效果图


1.本文案例基于Android studio,首先在app下的build.gradle下添加如下配置参数来导入当前最新的greenDAO框架

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath 'org.greenrobot:greendao-gradle-plugin:3.2.0'
    }
}

apply plugin: 'org.greenrobot.greendao'

dependencies {
    compile 'org.greenrobot:greendao:3.2.0'
}

现在,当你build项目的时候,就会执行生成greendao代码。在Android Studio中,当你选择build->make project的时候,也会触发。默认情况下,在build/generated/source/greendao目录下生成代码,将这个目录添加为gradle build时的资源目录。 
温馨提示:如果你觉得生成的代码有错误,请首先检查build/generated/source/greendao目录。

如果自己配置dao路径和数据库版本,需要再添加以下配置

greendao {
    //相当于数据库的版本号,每次更新表结构就要改变
    schemaVersion 3
    //设置DAO生成包的路径
    daoPackage "com.example.myapp.db.dao"
    //生成代码的存放地址
    targetGenDir 'src/main/java'
}

2. 创建一个User实体,然后再build -> rebuild project,greenDAO会在指定的目录生成代码。

注意我们这里用的是注解,3.0之前用的都是用它的构建工具来构建dao等类,非常不好用,现在终于可以改革了。


package com.example.myapp.bean;

import org.greenrobot.greendao.annotation.Entity;
import org.greenrobot.greendao.annotation.Generated;
import org.greenrobot.greendao.annotation.Id;
import org.greenrobot.greendao.annotation.NotNull;
import org.greenrobot.greendao.annotation.Property;
import org.greenrobot.greendao.annotation.Transient;

import java.util.Date;

/**
 * Created by jan on 2016/10/18.
 */
@Entity
public class User {
    @Id(autoincrement = true)
    private Long id;
    @Property(nameInDb = "name")
    private String name;
    @NotNull
    private String repos;
    @Transient
    private String tempUseageCount;
    private Date createTime;
    private String icon;
    private int age;
    private String sex;

    @Generated(hash = 2124177453)
    public User(Long id, String name, @NotNull String repos, Date createTime,
            String icon, int age, String sex) {
        this.id = id;
        this.name = name;
        this.repos = repos;
        this.createTime = createTime;
        this.icon = icon;
        this.age = age;
        this.sex = sex;
    }
    @Generated(hash = 586692638)
    public User() {
    }
    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 String getRepos() {
        return this.repos;
    }
    public void setRepos(String repos) {
        this.repos = repos;
    }
    public Date getCreateTime() {
        return this.createTime;
    }
    public void setCreateTime(Date createTime) {
        this.createTime = createTime;
    }
    public String getIcon() {
        return this.icon;
    }
    public void setIcon(String icon) {
        this.icon = icon;
    }
    public int getAge() {
        return this.age;
    }
    public void setAge(int age) {
        this.age = age;
    }
    public String getSex() {
        return this.sex;
    }
    public void setSex(String sex) {
        this.sex = sex;
    }
    

}
@Id:该注解选择一个long类型的属性作为实体类的ID。在数据库里面,它就是主键。这个参数 autoincrement 是一个标记,标志着ID一直都是增长的,从不适用旧值;
@Property:使用该属性定义一个非默认的列名,该变量和该列进行映射。如果缺少,greendao会使用这个变量名来命名数据库的列名(全部大写,并且使用下划线来代替驼峰命名法,eg:customName会变成CUSTOM_NAME)。
NotNull:非空,通常情况下修饰基础类型,比如long,int,short,byte,当然也可以是包装类:Long,Integer,Short,Byte
@Transient:表示该属性不是持久化的,仅仅作为临时变量使用。

Build完之后你会发现,加入了新的小伙伴





知识点:

1.DaoMaster DaoMaster保存数据库对象(SQLiteDatabase)和管理DAO类(而不是对象)为特定的模式。它的静态方法来创建表或删除它们。它的内部类OpenHelper和DevOpenHelper是创建SQLite数据库架构SQLiteOpenHelper实现。
2.DaoSession 管理所有可用的DAO对象,DaoSession还提供了一些通用的持久性的方法,如插入,装载,更新,刷新和删除实体。最后,DaoSession对象也跟踪标识范围。
3.Dao 各个表的Dao类,例如 UserDao,ImageDao等,负责增删改查


3.自己可以继承OpenHelper,为后期的数据库更新添加更新方法(不是本次重点),先贴下代码

public class MySqliteOpenHelper extends DaoMaster.OpenHelper {
    private static final String DB_NAME = "app.db";

    private static final SortedMap<Integer, Migration> ALL_MIGRATIONS = new TreeMap<>();

    static {
        //1-2-....迁移的递增
        ALL_MIGRATIONS.put(1, new V1Migration());
        ALL_MIGRATIONS.put(2, new V2Migration());
    }

    public MySqliteOpenHelper(Context context) {
        this(context, DB_NAME, null);
    }

    public MySqliteOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory) {
        super(context, DB_NAME, factory);
    }
    @Override
    public void onCreate(SQLiteDatabase db) {
        super.onCreate(db);
    }

    @Override
    public void onUpgrade(SQLiteDatabase sqLiteDatabase, int oldVersion, int newVersion) {
        Log.w(MySqliteOpenHelper.class.getSimpleName(), "Upgrade from" + oldVersion + "to" + newVersion);
        SortedMap<Integer, Migration> migrations = ALL_MIGRATIONS.subMap(oldVersion, newVersion);
        executeMigrations(sqLiteDatabase, migrations.keySet());
    }

    private void executeMigrations(final SQLiteDatabase paramSQLiteDatabase, final Set<Integer>
            migrationVersions) {
        for (final Integer version : migrationVersions) {
            ALL_MIGRATIONS.get(version).migrate(paramSQLiteDatabase);
        }
    }
}

/**
 * 实现更新数据库的迁移方案的接口
 */
interface Migration {
    void migrate(SQLiteDatabase db);
}

class V1Migration implements Migration {
    @Override
    public void migrate(SQLiteDatabase db) {
        db.execSQL("ALTER TABLE USER ADD COLUMN AGE");
    }
}

class V2Migration implements Migration {
    @Override
    public void migrate(SQLiteDatabase db) {
        db.execSQL("ALTER TABLE USER ADD COLUMN SEX");
    }
}

4.对DaoMaster.DaoSession,UserDao类进行第一次简单封装-DaoManager.java

/**
 * Created by Jan on 2016/10/19.
 */
public class DBManager {
    private static DBManager mDBManager;
    private static MySqliteOpenHelper mOpenHelper;
    private static DaoMaster mDaoMaster;
    private static DaoSession mDaoSession;
    private Context mContext;

    private DBManager(Context context) {
        this.mContext = context;
        // 初始化数据库信息
        mOpenHelper = new MySqliteOpenHelper(context);
        getDaoMaster(context);
        getDaoSession(context);
    }

    public static DBManager getInstance(Context context) {
        if (null == mDBManager) {
            synchronized (DBManager.class) {
                if (null == mDBManager) {
                    mDBManager = new DBManager(context);
                }
            }
        }
        return mDBManager;
    }

    /**
     * @desc 获取可读数据库
     **/
    public static SQLiteDatabase getReadableDatabase(Context context) {
        if (null == mOpenHelper) {
            getInstance(context);
        }
        return mOpenHelper.getReadableDatabase();
    }

    /**
     * @desc 获取可写数据库
     **/
    public static SQLiteDatabase getWritableDatabase(Context context) {
        if (null == mOpenHelper) {
            getInstance(context);
        }
        return mOpenHelper.getWritableDatabase();
    }

    /**
     * @desc 获取DaoMaster
     **/
    public static DaoMaster getDaoMaster(Context context) {
        if (null == mDaoMaster) {
            synchronized (DBManager.class) {
                if (null == mDaoMaster) {
                    mDaoMaster = new DaoMaster(getWritableDatabase(context));
                }
            }
        }
        return mDaoMaster;
    }

    /**
     * @desc 获取DaoSession
     **/
    public static DaoSession getDaoSession(Context context) {
        if (null == mDaoSession) {
            synchronized (DBManager.class) {
                mDaoSession = getDaoMaster(context).newSession();
            }
        }
        return mDaoSession;
    }
}
在DaoManager基础上,我们可以再对User的数据库业务层的操作进行一次封装,把最基础的几个增删查改操作做封装,这个类就是:UserDaoOpe.java

package com.example.myapp.db.dao;

import android.content.Context;

import com.example.myapp.bean.User;
import com.example.myapp.db.DBManager;

import org.greenrobot.greendao.query.QueryBuilder;

import java.util.List;


/**
 * 用户表的数据库方法的简单封装和管理的类
 * Created by Jan on 2016/10/19.
 */
public class UserDaoOpe {
    private static UserDaoOpe instance;
    private static Context appContext;
    private DaoSession mDaoSession;
    private UserDao mUserDao;

    private UserDaoOpe(){
    }

    /**
     * 单例
     * @param context
     * @return
     */
    public static UserDaoOpe getInstance(Context context) {
        if (instance == null) {
            instance = new UserDaoOpe();
            if (appContext == null){
                appContext = context.getApplicationContext();
            }
            instance.mDaoSession = DBManager.getDaoSession(context);
            instance.mUserDao = DBManager.getDaoSession(context).getUserDao();
        }
        return instance;
    }

    /**
     * 插入一个用户实体数据
     * @param user
     */
    public void insert(User user) {
        try {
            mUserDao.insert(user);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 删除一个用户
     * @param user
     */
    public void delete(User user){
        try {
            mUserDao.delete(user);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 根据主键ID来删除user
     * @param id
     */
    public void deleteUserById(Long id){
        try {
            mUserDao.deleteByKey(id);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 清空表中的内容
     */
    public void deleteAll(){
        try {
            mUserDao.deleteAll();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 更新User
     * @param user
     */
    public void upgrade(User user){
        try {
            mUserDao.update(user);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     *  利用事务来插入list
     * @param list
     */
    public void insertList(List<User> list){
        if(list==null || list.size()==0){
            return;
        }
        try {
            mUserDao.insertInTx(list);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 查询所有的user
     * @return
     */
    public List<User> queryAll(){
        try {
            QueryBuilder<User> builder = mUserDao.queryBuilder();
            return builder.build().list();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 查询大于指定年龄的用户群
     * @param age
     * @return
     */
    public List<User> findGtAgeUsers(int age){
        List<User> userList = null;
        try {
            userList = mUserDao.queryBuilder().where(UserDao.Properties.Age.gt(age)).list();
        }catch (Exception e){
            e.printStackTrace();
        }
        return userList;
    }

    /**
     * 根据主键ID来查询指定的User数据
     * @param id
     * @return
     */
    public User findUserById(String id){
       User user= null;
        try {
            QueryBuilder qb = mUserDao.queryBuilder().where(UserDao.Properties.Id.eq(id));
//            qb.limit(1);
//            qb.offset(0);
            List<User> userList = qb.list();
            user = userList.get(0);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return user;
    }
}
5.以上都是我们对greenDao方法的简单使用,应该是很好理解的,基本的增删查改方法,在下面我们就是在视图层的调用,直接调用UserDaoOpe这个类的API,很方便。如果你有更好的方式可以留言哦。

下面就是贴本次Activity的代码了。不是很重要,有兴趣的朋友可以看看哦。

GreenDaoDemo.java

public class GreenDaoDemo extends BaseActivity {
    ListView mListview;
    Button mSaveBtn,mDelBtn,mQueryBtn;
    PtrClassicFrameLayout mPtrFl;

    UserListAdapter mListAdapter;
    Random random = new Random();
    private Context context;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_greendao);
        context = this;
        initViews();
    }

    private void initViews() {
        mSaveBtn = (Button) findViewById(R.id.btn_save);
        mDelBtn = (Button) findViewById(R.id.btn_reset);
        mQueryBtn = (Button) findViewById(R.id.btn_querylist);
        mListview = (ListView) findViewById(R.id.lv_user);
        //下拉刷新组件的默认设置-与本次主题无关,请忽略
        mPtrFl = (PtrClassicFrameLayout) findViewById(R.id.ptr_frame);
        mPtrFl.setLastUpdateTimeRelateObject(this);
        mPtrFl.setResistance(1.7f);
        mPtrFl.setRatioOfHeaderHeightToRefresh(1.2f);
        mPtrFl.setDurationToClose(200);
        mPtrFl.setDurationToCloseHeader(1000);
        mPtrFl.setPullToRefresh(false);
        mPtrFl.setKeepHeaderWhenRefresh(true);
        mSaveBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                addUser();
            }
        });
        mDelBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                resetAndCleanAll();
            }
        });
        mQueryBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                findUserGt(30);
            }
        });
        mPtrFl.setPtrHandler(new PtrHandler() {
            @Override
            public boolean checkCanDoRefresh(PtrFrameLayout frame, View content, View header) {
                return PtrDefaultHandler.checkContentCanBePulledDown(frame, content, header);
            }

            @Override
            public void onRefreshBegin(PtrFrameLayout frame) {
                frame.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        notifyListview();
                    }
                }, 1500);
            }
        });
        mListAdapter = new UserListAdapter(this);
        mListview.setAdapter(mListAdapter);
        mListAdapter.setOnItemMenuSelectedListener(new UserListAdapter.OnItemMenuSelectedListener() {
            @Override
            public void onItemDel(int position) {
                User user = (User) mListAdapter.getItem(position);
//                UserDaoOpe.getInstance(context).delete(user);
                UserDaoOpe.getInstance(context).deleteUserById(user.getId());
            }

            @Override
            public void onItemUpdate(int position) {
                User user = (User) mListAdapter.getItem(position);
                BusPoster.postSticky(context,user,UserDetailActivity.class);
            }
        });
    }

    @Override
    protected void onStart() {
        super.onStart();
        notifyListview();
    }

    @Override
    public void onEvent(BaseEvent myEvent) {
        super.onEvent(myEvent);
        notifyListview();
    }

    private void notifyListview() {
        try {
            List<User> users = UserDaoOpe.getInstance(context).queryAll();
            if (users.size() > 0) {
                Log.d("DaoExample", "user's size is " + users.size());
                Log.d("DaoExample", "the last user 's icon's site " + users.get(users.size() - 1).getIcon());
            }
            mListAdapter.updateData(users);
            mPtrFl.refreshComplete();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 查询用户年龄大于age的数据
     * @param age
     */
    private void findUserGt(int age){
        List<User> users = UserDaoOpe.getInstance(context).findGtAgeUsers(age);
        mListAdapter.updateData(users);
    }

    /**
     * 清空所有数据
     */
    private void resetAndCleanAll(){
        UserDaoOpe.getInstance(context).deleteAll();
        notifyListview();
    }

    /**
     * 添加一个用户到本地数据库
     */
    private void addUser() {
        int randomInt = random.nextInt(100);
        Log.d("DaoExample", "Inserted random Int: " + randomInt);
        User user = new User(null, "NewName : " + randomInt, "content:" + randomInt, new Date(), "http://blog.youkuaiyun.com/jan_s/", randomInt, null);
        UserDaoOpe.getInstance(context).insert(user);
        Log.d("DaoExample", "Inserted new user, ID: " + user.getId());
        notifyListview();
    }

    /**
     * 模拟插入1000条用户信息
     */
    private void addUsers() {
        List<User> userList = new ArrayList<>();
        for (int i = 0; i < 1000; i++) {
            int randomInt = random.nextInt();
            User user = new User(null, "NewName" + randomInt, "content:" + randomInt, new Date(), "http://blog.youkuaiyun.com/jan_s/", randomInt, null);
            userList.add(user);
        }
        UserDaoOpe.getInstance(context).insertList(userList);
//        userDao.insertInTx(userList);
        notifyListview();
    }


    @Override
    protected void onDestroy() {
        super.onDestroy();
    }
}
修改的界面-UserDetailActivity.java


public class UserDetailActivity extends BaseActivity {

    EditText mIdEt,mNameEt,mReposEt,mAgeEt;
    Button mUpgradeBtn;
    User mUser;
    Context context;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_userdetail);
        context = this;
        initViews();
        initEvent();
    }

    @Override
    public void onEvent(BaseEvent myEvent) {
        super.onEvent(myEvent);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        BusPoster.removeSticky(User.class);
    }

    private void initViews(){
        mIdEt = (EditText) findViewById(R.id.et_id);
        mNameEt = (EditText) findViewById(R.id.et_name);
        mReposEt = (EditText) findViewById(R.id.et_repos);
        mAgeEt = (EditText) findViewById(R.id.et_age);
        mUpgradeBtn = (Button) findViewById(R.id.btn_upgrade);
    }

    private void initEvent(){
        mUpgradeBtn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                updateUser();
            }
        });
        mUser = (User) BusPoster.getSticky(User.class);
        mUser = UserDaoOpe.getInstance(context).findUserById(mUser.getId()+"");
        if(mUser!=null){
            mIdEt.setText(mUser.getId()+"");
            mNameEt.setText(mUser.getName());
            mReposEt.setText(mUser.getRepos());
            mAgeEt.setText(""+mUser.getAge());
        }
    }

    private void updateUser(){
        try {
            if(mUser!=null){
                String id = mIdEt.getText().toString().trim();
                String name = mNameEt.getText().toString().trim();
                String repos = mReposEt.getText().toString().trim();
                String age = mAgeEt.getText().toString().trim();
                mUser.setId(Long.parseLong(id));
                mUser.setName(name);
                mUser.setRepos(repos);
                mUser.setAge(Integer.parseInt(age));
                UserDaoOpe.getInstance(context).upgrade(mUser);
            }
        }catch (Exception e){
            e.printStackTrace();
            Toast.makeText(context,"数据不对哦",Toast.LENGTH_SHORT).show();
        }
    }

    @Override
    public void onBackPressed() {
        super.onBackPressed();
    }
}
OK!结束!

本文链接,转载请留言(http://blog.youkuaiyun.com/jan_s/article/details/53127108



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值