• GreenDao3.2使用详解(增,删,改,查,升级)


    首先看一下效果图:

    项目结构如下图所示:

    第一步:在build中添加配置如下:

    projet 目录下的build.gradle

    dependencies {

    classpath 'org.greenrobot:greendao-gradle-plugin:3.2.0'
    }

    moudle 下的build.gradle添加如下内容:
    apply plugin: 'org.greenrobot.greendao'

    dependencies {
    .....................

    compile 'org.greenrobot:greendao:3.2.0'
    }


    添加完成之后点击sync一下工程


    第二步:

    首先在moudle下  build.gradle的根目录下添加如下配置

    greendao {
    //数据库的schema版本,也可以理解为数据库版本号
    schemaVersion 1
    //设置DaoMaster、DaoSession、Dao包名,也就是要放置这些类的包的全路径。
    daoPackage 'com.koimy.greedaotest.dao'
    //设置DaoMaster、DaoSession、Dao目录
    targetGenDir 'src/main/java'
    }
    在项目里面添加实体类Student如下所示:
    @Entity
    public class Student {
    @Id
    private Long id;
    private String name;
    private int age;
    private String num;
    }
    此时项目目录如下所示:


    然后点击 android studio 的 build-->make project

    此时项目结构如下:

    其中dao目录下的文件是由greendao自动生成的,Student 类里面的内容发生了编号如下:

    /**
    * Created by hp on 2018/1/23.
    */
    @Entity
    public class Student {
    @Id
    private Long id;
    private String name;
    private int age;
    private String num;
    @Generated(hash = 1538557423)
    public Student(Long id, String name, int age, String num) {
    this.id = id;
    this.name = name;
    this.age = age;
    this.num = num;
    }
    @Generated(hash = 1556870573)
    public Student() {
    }
    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 int getAge() {
    return this.age;
    }
    public void setAge(int age) {
    this.age = age;
    }
    public String getNum() {
    return this.num;
    }
    public void setNum(String num) {
    this.num = num;
    }
    GreenDao帮助我们自动生成了一些get和set方法,以及构造方法
    第三步:为了方便使用我们添加了一个 db包

    DbManager类如下:

    package com.koimy.greedaotest.db;

    /**
    * Created by hp on 2018/1/23.
    */

    import android.content.Context;
    import android.database.sqlite.SQLiteDatabase;

    import com.koimy.greedaotest.dao.DaoMaster;
    import com.koimy.greedaotest.dao.DaoSession;


    public class DbManager {

    // 是否加密
    public static final boolean ENCRYPTED = true;

    private static final String DB_NAME = "test.db";
    private static DbManager mDbManager;
    private static DaoMaster.DevOpenHelper mDevOpenHelper;
    private static DaoMaster mDaoMaster;
    private static DaoSession mDaoSession;

    private Context mContext;

    private DbManager(Context context) {
    this.mContext = context;
    // 初始化数据库信息
    mDevOpenHelper = new DaoMaster.DevOpenHelper(context, DB_NAME);
    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;
    }

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

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

    return mDevOpenHelper.getWritableDatabase();
    }

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

    // /**
    // * 获取DaoMaster
    // *
    // * 判断是否存在数据库,如果没有则创建数据库
    // * @param context
    // * @return
    // */
    // public static DaoMaster getDaoMaster(Context context) {
    // if (null == mDaoMaster) {
    // synchronized (DbManager.class) {
    // if (null == mDaoMaster) {
    // MyOpenHelper helper = new MyOpenHelper(context,DB_NAME,null);
    // mDaoMaster = new DaoMaster(helper.getWritableDatabase());
    // }
    // }
    // }
    // return mDaoMaster;
    // }

    /**
    * 获取DaoSession
    *
    * @param context
    * @return
    */
    public static DaoSession getDaoSession(Context context) {
    if (null == mDaoSession) {
    synchronized (DbManager.class) {
    mDaoSession = getDaoMaster(context).newSession();
    }
    }
    return mDaoSession;
    }
    }
    SutdentDaoOpe类如下:
    package com.koimy.greedaotest.db;

    /**
    * Created by hp on 2018/1/23.
    */

    import android.content.Context;


    import com.koimy.greedaotest.dao.StudentDao;
    import com.koimy.greedaotest.entity.Student;

    import org.greenrobot.greendao.query.QueryBuilder;

    import java.util.List;


    public class StudentDaoOpe {

    /**
    * 添加数据至数据库
    *
    * @param context
    * @param stu
    */
    public static void insertData(Context context, Student stu) {
    DbManager.getDaoSession(context).getStudentDao().insert(stu);
    }


    /**
    * 将数据实体通过事务添加至数据库
    *
    * @param context
    * @param list
    */
    public static void insertData(Context context, List<Student> list) {
    if (null == list || list.size() <= 0) {
    return;
    }
    DbManager.getDaoSession(context).getStudentDao().insertInTx(list);
    }

    /**
    * 添加数据至数据库,如果存在,将原来的数据覆盖
    * 内部代码判断了如果存在就update(entity);不存在就insert(entity);
    *
    * @param context
    * @param student
    */
    public static void saveData(Context context, Student student) {
    DbManager.getDaoSession(context).getStudentDao().save(student);
    }

    /**
    * 删除数据至数据库
    *
    * @param context
    * @param student 删除具体内容
    */
    public static void deleteData(Context context, Student student) {
    DbManager.getDaoSession(context).getStudentDao().delete(student);
    }

    /**
    * 根据id删除数据至数据库
    *
    * @param context
    * @param id 删除具体内容
    */
    public static void deleteByKeyData(Context context, long id) {
    DbManager.getDaoSession(context).getStudentDao().deleteByKey(id);
    }

    /**
    * 删除全部数据
    *
    * @param context
    */
    public static void deleteAllData(Context context) {
    DbManager.getDaoSession(context).getStudentDao().deleteAll();
    }

    /**
    * 更新数据库
    *
    * @param context
    * @param student
    */
    public static void updateData(Context context, Student student) {
    DbManager.getDaoSession(context).getStudentDao().update(student);
    }


    /**
    * 查询所有数据
    *
    * @param context
    * @return
    */
    public static List<Student> queryAll(Context context) {
    QueryBuilder<Student> builder = DbManager.getDaoSession(context).getStudentDao().queryBuilder();

    return builder.build().list();
    }



    /**
    * 分页加载
    * @param context
    * @param pageSize 当前第几页(程序中动态修改pageSize的值即可)
    * @param pageNum 每页显示多少个
    * @return
    */
    public static List<Student> queryPaging( int pageSize, int pageNum,Context context){
    StudentDao studentDao = DbManager.getDaoSession(context).getStudentDao();
    List<Student> listMsg = studentDao.queryBuilder()
    .offset(pageSize * pageNum).limit(pageNum).list();
    return listMsg;
    }
    }

    activity_main.xml
    <?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.koimy.demo2.MainActivity">


    <Button
    android:id="@+id/button"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="增" />

    <Button
    android:id="@+id/button2"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="删" />

    <Button
    android:id="@+id/button3"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="改" />

    <Button
    android:id="@+id/button4"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="查" />

    <LinearLayout
    android:layout_marginTop="20dp"
    android:gravity="center"
    android:layout_gravity="center_vertical"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <Button
    android:id="@+id/btn_query_all"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="根据ID查询(分页查询)" />

    <Button
    android:id="@+id/button5"
    android:layout_width="107dp"
    android:layout_height="wrap_content"
    android:text="删除全部" />
    </LinearLayout>

    <ScrollView
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <TextView
    android:id="@+id/tv_content"
    android:layout_width="match_parent"
    android:layout_height="wrap_content" />
    </ScrollView>

    </LinearLayout>

    MainActivithy.java
    package com.koimy.greedaotest;

    import android.os.Bundle;
    import android.support.v7.app.AppCompatActivity;
    import android.util.Log;
    import android.view.View;
    import android.widget.Button;
    import android.widget.TextView;
    import android.widget.Toast;

    import com.koimy.greedaotest.db.StudentDaoOpe;
    import com.koimy.greedaotest.entity.Student;

    import java.util.ArrayList;
    import java.util.List;

    import butterknife.BindView;
    import butterknife.ButterKnife;
    import butterknife.OnClick;

    public class MainActivity extends AppCompatActivity {

    @BindView(R.id.button)
    Button button;
    @BindView(R.id.button2)
    Button button2;
    @BindView(R.id.button3)
    Button button3;
    @BindView(R.id.button4)
    Button button4;
    @BindView(R.id.btn_query_all)
    Button btnQueryAll;
    @BindView(R.id.button5)
    Button button5;
    @BindView(R.id.tv_content)
    TextView tvContent;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    ButterKnife.bind(this);
    initData();
    }

    private List<Student> studentList = new ArrayList<>();

    /**
    * 初始化数据
    */
    private void initData() {
    for (int i = 0; i < 100; i++) {
    Student student = new Student((long) i, "huang" + i, 25,"666"+i);
    studentList.add(student);
    }

    }

    int page;

    @OnClick({R.id.button, R.id.button2, R.id.button3, R.id.button4, R.id.button5, R.id.btn_query_all})
    public void onViewClicked(View view) {
    switch (view.getId()) {
    case R.id.button:
    StudentDaoOpe.insertData(this, studentList);
    break;
    case R.id.button2:
    Student student = new Student((long) 5, "haung" + 5, 25,"123456");
    /**
    * 根据特定的对象删除
    */
    StudentDaoOpe.deleteData(this, student);
    /**
    * 根据主键删除
    */
    StudentDaoOpe.deleteByKeyData(this, 7);
    StudentDaoOpe.deleteAllData(this);
    break;
    case R.id.button3:
    student = new Student((long) 2, "caojin", 1314,"888888");
    StudentDaoOpe.updateData(this, student);
    break;
    case R.id.button4:
    List<Student> students = StudentDaoOpe.queryAll(this);
    tvContent.setText(students.toString());
    for (int i = 0; i < students.size(); i++) {
    Log.i("Log", students.get(i).getName());
    }

    break;
    case R.id.button5:
    StudentDaoOpe.deleteAllData(this);
    break;
    case R.id.btn_query_all:
    List<Student> students2 = StudentDaoOpe.queryPaging(page, 20, this);

    if (students2.size() == 0) {
    Toast.makeText(this, "没有更多数据了", Toast.LENGTH_SHORT).show();
    }
    for (Student st : students2) {
    Log.e("TAG", "onViewClicked: ==" + st);
    Log.e("TAG", "onViewClicked: == num = " + st.getNum());
    }
    page++;
    tvContent.setText(students2.toString());
    break;
    }
    }


    }
    最终在/data/data/包名/databases/数据库名/表名 生成的表结构如下所示:

    下面讲一下数据库的升级:

    首先新建一个helper包引入两个类,内容如下:

    MigrationHelper类:


    package com.koimy.greedaotest.helper;

    /**
    * 数据库更新辅助类
    *
    * 原理:创建临时表-->删除原表-->创建新表-->复制临时表数据到新表并删除临时表;这样数据库表的更新就完成了
    */

    import android.database.Cursor;
    import android.text.TextUtils;
    import android.util.Log;


    import com.koimy.greedaotest.dao.DaoMaster;

    import org.greenrobot.greendao.AbstractDao;
    import org.greenrobot.greendao.database.Database;
    import org.greenrobot.greendao.internal.DaoConfig;

    import java.util.ArrayList;
    import java.util.Arrays;
    import java.util.List;


    public class MigrationHelper {

    private static final String CONVERSION_CLASS_NOT_FOUND_EXCEPTION = "MIGRATION HELPER - CLASS DOESN'T MATCH WITH THE CURRENT PARAMETERS";
    private static MigrationHelper instance;

    public static MigrationHelper getInstance() {
    if (instance == null) {
    instance = new MigrationHelper();
    }
    return instance;
    }

    public void migrate(Database db, Class<? extends AbstractDao<?, ?>>... daoClasses) {

    generateTempTables(db, daoClasses);
    DaoMaster.dropAllTables(db, true);
    DaoMaster.createAllTables(db, false);
    restoreData(db, daoClasses);
    }

    /**
    * 生成临时列表
    *
    * @param db
    * @param daoClasses
    */
    private void generateTempTables(Database db, Class<? extends AbstractDao<?, ?>>... daoClasses) {
    for (int i = 0; i < daoClasses.length; i++) {
    DaoConfig daoConfig = new DaoConfig(db, daoClasses[i]);

    String divider = "";
    String tableName = daoConfig.tablename;
    String tempTableName = daoConfig.tablename.concat("_TEMP");
    ArrayList<String> properties = new ArrayList<>();

    StringBuilder createTableStringBuilder = new StringBuilder();

    createTableStringBuilder.append("CREATE TABLE ").append(tempTableName).append(" (");

    for (int j = 0; j < daoConfig.properties.length; j++) {
    String columnName = daoConfig.properties[j].columnName;

    if (getColumns(db, tableName).contains(columnName)) {
    properties.add(columnName);

    String type = null;

    try {
    type = getTypeByClass(daoConfig.properties[j].type);
    } catch (Exception exception) {
    exception.printStackTrace();
    }

    createTableStringBuilder.append(divider).append(columnName).append(" ").append(type);

    if (daoConfig.properties[j].primaryKey) {
    createTableStringBuilder.append(" PRIMARY KEY");
    }

    divider = ",";
    }
    }
    createTableStringBuilder.append(");");

    db.execSQL(createTableStringBuilder.toString());

    StringBuilder insertTableStringBuilder = new StringBuilder();

    insertTableStringBuilder.append("INSERT INTO ").append(tempTableName).append(" (");
    insertTableStringBuilder.append(TextUtils.join(",", properties));
    insertTableStringBuilder.append(") SELECT ");
    insertTableStringBuilder.append(TextUtils.join(",", properties));
    insertTableStringBuilder.append(" FROM ").append(tableName).append(";");

    db.execSQL(insertTableStringBuilder.toString());

    }
    }

    /**
    * 存储新的数据库表 以及数据
    *
    * @param db
    * @param daoClasses
    */
    private void restoreData(Database db, Class<? extends AbstractDao<?, ?>>... daoClasses) {
    for (int i = 0; i < daoClasses.length; i++) {
    DaoConfig daoConfig = new DaoConfig(db, daoClasses[i]);
    String tableName = daoConfig.tablename;
    String tempTableName = daoConfig.tablename.concat("_TEMP");
    ArrayList<String> properties = new ArrayList();

    for (int j = 0; j < daoConfig.properties.length; j++) {
    String columnName = daoConfig.properties[j].columnName;

    if (getColumns(db, tempTableName).contains(columnName)) {
    properties.add(columnName);
    }
    }

    StringBuilder insertTableStringBuilder = new StringBuilder();

    insertTableStringBuilder.append("INSERT INTO ").append(tableName).append(" (");
    insertTableStringBuilder.append(TextUtils.join(",", properties));
    insertTableStringBuilder.append(") SELECT ");
    insertTableStringBuilder.append(TextUtils.join(",", properties));
    insertTableStringBuilder.append(" FROM ").append(tempTableName).append(";");

    StringBuilder dropTableStringBuilder = new StringBuilder();
    dropTableStringBuilder.append("DROP TABLE ").append(tempTableName);
    db.execSQL(insertTableStringBuilder.toString());
    db.execSQL(dropTableStringBuilder.toString());
    }
    }

    private String getTypeByClass(Class<?> type) throws Exception {
    if (type.equals(String.class)) {
    return "TEXT";
    }
    if (type.equals(Long.class) || type.equals(Integer.class) || type.equals(long.class)) {
    return "INTEGER";
    }
    if (type.equals(Boolean.class)) {
    return "BOOLEAN";
    }

    Exception exception = new Exception(CONVERSION_CLASS_NOT_FOUND_EXCEPTION.concat(" - Class: ").concat(type.toString()));
    exception.printStackTrace();
    throw exception;
    }

    private List<String> getColumns(Database db, String tableName) {
    List<String> columns = new ArrayList<>();
    Cursor cursor = null;
    try {
    cursor = db.rawQuery("SELECT * FROM " + tableName + " limit 1", null);
    if (cursor != null) {
    columns = new ArrayList<>(Arrays.asList(cursor.getColumnNames()));
    }
    } catch (Exception e) {
    Log.v(tableName, e.getMessage(), e);
    e.printStackTrace();
    } finally {
    if (cursor != null)
    cursor.close();
    }
    return columns;
    }
    }
    MyOpenHelper类:

    package com.koimy.greedaotest.helper;

    /**
    * Created by hp on 2018/1/23.
    */

    import android.content.Context;
    import android.database.sqlite.SQLiteDatabase;
    import android.util.Log;


    import com.koimy.greedaotest.dao.DaoMaster;
    import com.koimy.greedaotest.dao.StudentDao;

    import org.greenrobot.greendao.database.Database;


    public class MyOpenHelper extends DaoMaster.OpenHelper {

    public MyOpenHelper(Context context, String name, SQLiteDatabase.CursorFactory factory) {
    super(context, name, factory);
    }

    /**
    * 数据库升级
    * @param db
    * @param oldVersion
    * @param newVersion
    */
    @Override
    public void onUpgrade(Database db, int oldVersion, int newVersion) {
    //操作数据库的更新 有几个表升级都可以传入到下面

    Log.i("version", oldVersion + "---先前和更新之后的版本---" + newVersion);
    if (oldVersion < newVersion) {
    Log.i("version", oldVersion + "---先前和更新之后的版本---" + newVersion);
    MigrationHelper.getInstance().migrate(db, StudentDao.class);
    //更改过的实体类(新增的不用加) 更新UserDao文件 可以添加多个 XXDao.class 文件
    // MigrationHelper.getInstance().migrate(db, UserDao.class,XXDao.class);
    }



    //MigrationHelper.getInstance().migrate(db,StudentDao.class);
    }

    }
    然后将
    /**
    * 获取DaoMaster
    *
    * @param context
    * @return
    */
    public static DaoMaster getDaoMaster(Context context) {
    if (null == mDaoMaster) {
    synchronized (DbManager.class) {
    if (null == mDaoMaster) {
    mDaoMaster = new DaoMaster(getWritableDatabase(context));
    }
    }
    }
    return mDaoMaster;
    }
    换成如下所示:

    /**
    * 获取DaoMaster
    *
    * 判断是否存在数据库,如果没有则创建数据库
    * @param context
    * @return
    */
    public static DaoMaster getDaoMaster(Context context) {
    if (null == mDaoMaster) {
    synchronized (DbManager.class) {
    if (null == mDaoMaster) {
    MyOpenHelper helper = new MyOpenHelper(context,DB_NAME,null);
    mDaoMaster = new DaoMaster(helper.getWritableDatabase());
    }
    }
    }
    return mDaoMaster;
    }
    接下来:我们在Student类里面添加一个 属性 grade属性,然后将build.gradle里面schemaVersion改为 2

    然后编译,运行一下程序,然后我们再来看升级后的数据库,如下图所示成功添加了我么新增的字段,还保留了以前的数据



  • 相关阅读:
    RvmTranslator7.3.2
    PipeCAD
    Open CASCADE Technology 7.5.0 released
    IsoAlgo 环路处理
    OD流向地图的绘制——利用ArcGIS与Gephi方法
    Python调用百度地图和高德地图API批量获取国内城市地址经纬度坐标
    ArcGIS地理数据库Geodatabase
    Gephi 安装与简明教程
    安装Java SDK
    ArcGIS中自定义脚本工具制作
  • 原文地址:https://www.cnblogs.com/aibabel/p/11311703.html
Copyright © 2020-2023  润新知