我的Android入门之路:一、初步接触之GreenDAO学习使用体验

来源:互联网 发布:单片机蜂鸣器实验报告 编辑:程序博客网 时间:2024/05/30 07:13

最近开始正式接触Android开发,这是首次使用博客,也是初步接触GreenDAO,写的会很初级。大家如果看了我的文章,不论是文章本身的不足,还是代码本身的缺陷,都欢迎帮忙多多指出,先在此谢过。同时也希望我的文章能帮到同样刚开始接触GreenDAO的朋友。

本文的内容是利用GreenDAO对SQLite数据库中的表单进行创建并实现增删查改等功能。
首先是对于GreenDAO的简单介绍:
GreenDAO是一个可以帮助Android开发者快速将Java对象映射到SQLite数据库的表单中的ORM解决方案,
通过使用一个简单的面向对象API,开发者可以对Java对象进行存储、更新、删除和查询。
GreenDAO的主要设计目标:最大性能(最快的Android ORM)、易于使用API、高度优化、最小内存消耗。
GreenDAO官网:http://greendao-orm.com/
项目下载地址:https://github.com/greenrobot/greenDAO(或者官网)

官方Demo里共有六个工程目录,分别为:
(1).DaoCore:库目录,即jar文件greendao-1.3.7.jar的代码;
(2).DaoExample:android范例工程;
(3).DaoExampleGenerator:DaoExample工程的DAO类构造器,java工程;
(4).DaoGenerator:DAO类构造器,java工程;
(5).DaoTest、PerformanceTestOrmLite:其他测试相关的工程。

学习使用步骤:

一、DAO类的构造

首先需要新建一个java工程来生成DAO类文件,该工程需要导入greendao-generator.jar和freemarker.jar文件到项目中。(右键当前项目–Build Path–Configure Build Path–Libraries–Add External JARs即可导入)
以下是我本次项目中建立的java工程,目标是设置一个有关学生信息的实体类。

package org.yijing.test;import de.greenrobot.daogenerator.DaoGenerator;import de.greenrobot.daogenerator.Entity;import de.greenrobot.daogenerator.Schema;public class Make {    public static void main(String[] args) throws Exception {        //该方法第一个参数用来更新数据库版本号,第二个参数为要生成的DAO类所在包路径        Schema schema = new Schema(3, "org.yijing.test");        //进行建表        addInfo(schema);        //设置要生成DAO文件的目标工程的项目名称,其中src-gen这个目录名需要在运行前手动创建,否则报错        new DaoGenerator().generateAll(schema, "../StudentInfo/src-gen");    }    //设置名为StudentInfo(学生信息)的实体对象包含有“(自增长)ID”、“学号”、“姓名”、“年龄”等属性    private static void addInfo(Schema schema) {        Entity info = schema.addEntity("StudentInfo");        info.addIdProperty().autoincrement();        info.addIntProperty("number");        info.addStringProperty("name").notNull();        info.addIntProperty("age");    }}
代码中每一步骤的实现目标均已注释。其中默认表名就是类名,也可以自定义表名:info.setTableName("StudentInformation");若运行后出现以下的提示说明DAO文件自动生成成功了,刷新一下StudentInfo项目即可看到。
greenDAO GeneratorCopyright 2011-2014 Markus Junginger, greenrobot.de. Licensed under GPL V3.This program comes with ABSOLUTELY NO WARRANTYProcessing schema version 3...Written J:\Android\work\workspace\StudentInfo\src-gen\org\yijing\test\StudentInfoDao.javaWritten J:\Android\work\workspace\StudentInfo\src-gen\org\yijing\test\StudentInfo.javaWritten J:\Android\work\workspace\StudentInfo\src-gen\org\yijing\test\DaoMaster.javaWritten J:\Android\work\workspace\StudentInfo\src-gen\org\yijing\test\DaoSession.javaProcessed 1 entities in 113ms

二、表的增删查改

增删查改其实相当方便,完全的面向对象,不需要涉及到任何的sql语言。
以下就是我本次项目的主体,也就是对增删查改的具体实现,功能详细来说有五:
1.添加学生信息,包括学号、姓名、年龄
2.通过学号查询对应学生的姓名
3.根据ID顺序每五人一组,通过分组号查询对应五名学生的姓名
4.输入学号,删除对应的学生信息
5.输入学号,以及修改后的名字,完成该学号对应的学生姓名的修改

具体代码如下(先上完整代码,再逐步分析):

package org.yijing.test.studentinfo;import java.util.List;import org.yijing.test.DaoMaster;import org.yijing.test.DaoMaster.DevOpenHelper;import org.yijing.test.DaoSession;import org.yijing.test.StudentInfo;import org.yijing.test.StudentInfoDao;import org.yijing.test.StudentInfoDao.Properties;import android.database.sqlite.SQLiteDatabase;import android.os.Bundle;import android.support.v7.app.ActionBarActivity;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;import android.widget.EditText;import android.widget.TextView;import android.widget.Toast;import de.greenrobot.dao.query.QueryBuilder;public class MainActivity extends ActionBarActivity {    private SQLiteDatabase db;    private EditText addNumberText, addNameText, addAgeText, queryNumberText,            queryGroupText, delNumberText, alterNumberText, alterNameText;    private TextView queryNameText, queryGroupNameText,allMemberQuantityText;    private DaoMaster daoMaster;    private DaoSession daoSession;    private StudentInfoDao studentInfoDao;    @Override    public void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        //使用DaoMaster类获得一个方便的SQLiteOpenHelper        DevOpenHelper helper = new DaoMaster.DevOpenHelper(this, "notes-db",null);        db = helper.getWritableDatabase();        daoMaster = new DaoMaster(db);        daoSession = daoMaster.newSession();        studentInfoDao = daoSession.getStudentInfoDao();        addNumberText = (EditText) findViewById(R.id.addNumberText);        addNameText = (EditText) findViewById(R.id.addNameText);        addAgeText = (EditText) findViewById(R.id.addAgeText);        queryNumberText = (EditText) findViewById(R.id.queryNumberText);        queryGroupText = (EditText) findViewById(R.id.queryGroupText);        delNumberText = (EditText) findViewById(R.id.delNumberText);        alterNumberText = (EditText) findViewById(R.id.alterNumberText);        alterNameText = (EditText) findViewById(R.id.alterNameText);        queryNameText = (TextView) findViewById(R.id.queryNameText);        queryGroupNameText = (TextView) findViewById(R.id.queryGroupNameText);        allMemberQuantityText = (TextView) findViewById(R.id.allMemberQuantityText);        Button buttonAdd = (Button) findViewById(R.id.buttonAdd);        Button buttonName = (Button) findViewById(R.id.buttonName);        Button buttonGroup = (Button) findViewById(R.id.buttonGroup);        Button buttonDel = (Button) findViewById(R.id.buttonDel);        Button buttonAlter = (Button) findViewById(R.id.buttonAlter);        //最下方显示当前已记录的总人数        allMemberQuantityText.setText("总人数:" + studentInfoDao.count());        //添加学生信息,包括学号、姓名、年龄        buttonAdd.setOnClickListener(new OnClickListener() {            @Override            public void onClick(View v) {                //判断学生信息是否完整填写                //不完整则弹出提示:请完善你的信息                //完整填写再判断是否已有                //若已有则弹出提示:该学号已有对应的学生                //若没有则进行添加,并提示:插入完成                String numberText = addNumberText.getText().toString();                String nameText = addNameText.getText().toString();                String ageText = addAgeText.getText().toString();                QueryBuilder<StudentInfo> qb = studentInfoDao.queryBuilder().where(Properties.Number.eq(numberText));                if (numberText.trim().equals("")|| nameText.trim().equals("")|| ageText.trim().equals("")) {                    Toast.makeText(MainActivity.this, "请完善你的信息", 3000).show();                } else {                    if (qb.list().isEmpty()) {                        int numberT = Integer.valueOf(numberText);                        int ageT = Integer.valueOf(ageText);                        addNumberText.setText("");                        addNameText.setText("");                        addAgeText.setText("");                        StudentInfo sInfo = new StudentInfo(null, numberT,nameText, ageT);                        studentInfoDao.insert(sInfo);                        Toast.makeText(MainActivity.this, "插入完成", 3000).show();                        allMemberQuantityText.setText("总人数:" + studentInfoDao.count());                    } else {                        Toast.makeText(MainActivity.this, "该学号已有对应的学生", 3000).show();                    }                }             }        });        //通过学号查询对应学生的姓名        buttonName.setOnClickListener(new OnClickListener() {            @Override            public void onClick(View v) {                //判断是否已正确输入学号                //未输入或者未正确输入则提示:请输入正确的学号                //已正确输入则显示对应学生姓名                String qNumber = queryNumberText.getText().toString();                if (qNumber.trim().equals("")                        ||studentInfoDao.queryBuilder().where(Properties.Number.eq(qNumber)).list().isEmpty()) {                    Toast.makeText(MainActivity.this, "请输入正确的学号", 3000).show();                } else {                    QueryBuilder<StudentInfo> qb = studentInfoDao.queryBuilder();                    queryNameText.setText(qb.where(Properties.Number.eq(queryNumberText                                    .getText().toString())).list().get(0).getName());                }            }        });        //每五人一组,通过分组号查询对应五名学生的姓名        buttonGroup.setOnClickListener(new OnClickListener() {            @Override            public void onClick(View v) {                //判断是否已输入分组号                //确定输入后根据分组号显示对应成员                //其中若输入组号超过有人员分配的总组数,则提示:已超过人数上限,该组无成员                if (queryGroupText.getText().toString().trim().equals("")) {                    Toast.makeText(MainActivity.this, "请输入分组号", 3000).show();                } else {                    int groupNumber = Integer.valueOf(queryGroupText.getText().toString());                    int firstNumber = (groupNumber - 1) * 5;                    List<StudentInfo> students = studentInfoDao.queryBuilder().limit(5).offset(firstNumber).list();                    int memberNumber = students.size();                    if (memberNumber > 0) {                        queryGroupNameText.setText("");                        for (int i = 0; i < memberNumber; i++) {                            queryGroupNameText.setText(queryGroupNameText.getText() + "\"" + students.get(i).getName() + "\"");                        }                    } else {                        Toast.makeText(MainActivity.this, "已超过人数上限,该组无成员", 3000).show();                    }                }            }        });        //输入学号,删除对应的学生信息        buttonDel.setOnClickListener(new OnClickListener() {            @Override            public void onClick(View v) {                //判断是否输入已有的学号                //如果不是,则提示:请输入已有的学号                //如果是,则删除对应的学生信息                String numberText = delNumberText.getText().toString();                QueryBuilder<StudentInfo> qb = studentInfoDao.queryBuilder().where(Properties.Number.eq(numberText));                if (qb.list().isEmpty()){                       Toast.makeText(MainActivity.this, "请输入已有的学号", 3000).show();                } else {                    qb.buildDelete().executeDeleteWithoutDetachingEntities();                    allMemberQuantityText.setText("总人数:" + studentInfoDao.count());                }            }        });        //输入学号,以及修改后的名字,完成该学号对应的学生姓名的修改        buttonAlter.setOnClickListener(new OnClickListener() {            @Override            public void onClick(View v) {                //先判断是否输入已有的学号,未输入或者错误输入都将提示:请输入已有的学号                //再判断是否已输入修改后的名字,未输入则提示:请输入想要修改成的名字                //学号和名字都正确输入并点击按钮之后,就进行学号对应的名字修改,并提示:信息已修改                String numberText = alterNumberText.getText().toString();                QueryBuilder<StudentInfo> qb = studentInfoDao.queryBuilder().where(Properties.Number.eq(numberText));                if (qb.list().isEmpty()){                       Toast.makeText(MainActivity.this, "请输入已有的学号", 3000).show();                } else if (alterNameText.getText().toString().trim().equals("")) {                    Toast.makeText(MainActivity.this, "请输入想要修改成的名字", 3000).show();                } else{                    long id = qb.list().get(0).getId();                    int number = Integer.valueOf(numberText);                    int age = qb.list().get(0).getAge();                    StudentInfo sChangedInfo = new StudentInfo(id, number,alterNameText.getText().toString(), age);                    studentInfoDao.insertOrReplace(sChangedInfo);                    Toast.makeText(MainActivity.this, "信息已修改", 3000).show();                }            }        });    }}

其实具体的注释均已在上述代码中标明,以下主要讲述我写代码时的思路与所遇问题:

(1)使用DaoMaster类获得一个方便的SQLiteOpenHelper

        DevOpenHelper helper = new DaoMaster.DevOpenHelper(this, "notes-db",null);        db = helper.getWritableDatabase();        daoMaster = new DaoMaster(db);        daoSession = daoMaster.newSession();        studentInfoDao = daoSession.getStudentInfoDao();

这样就不需要直接使用SQL语句了,GreenDAO会自动帮忙完成。

(2)在进行操作前首先在最下方显示当前已记录的总人数

        allMemberQuantityText.setText("总人数:" + studentInfoDao.count());

由于本次项目只是很简略地实现增删查改功能,并没有设定将信息列表完整显示出来。通过上述代码能在刚点开程序时了解到当前已记录人数。

(3)实现功能:添加学生信息,包括学号、姓名、年龄

    buttonAdd.setOnClickListener(new OnClickListener() {            @Override            public void onClick(View v) {                //判断学生信息是否完整填写                //不完整则弹出提示:请完善你的信息                //完整填写再判断是否已有                //若已有则弹出提示:该学号已有对应的学生                //若没有则进行添加,并提示:插入完成                String numberText = addNumberText.getText().toString();                String nameText = addNameText.getText().toString();                String ageText = addAgeText.getText().toString();                QueryBuilder<StudentInfo> qb = studentInfoDao.queryBuilder().where(Properties.Number.eq(numberText));                if (numberText.trim().equals("") || nameText.trim().equals("") || ageText.trim().equals("")) {                    Toast.makeText(MainActivity.this, "请完善你的信息", 3000).show();                } else {                    if (qb.list().isEmpty()) {                        int numberT = Integer.valueOf(numberText);                        int ageT = Integer.valueOf(ageText);                        addNumberText.setText("");                        addNameText.setText("");                        addAgeText.setText("");                        StudentInfo sInfo = new StudentInfo(null, numberT,nameText, ageT);                        studentInfoDao.insert(sInfo);                        Toast.makeText(MainActivity.this, "插入完成", 3000).show();                        allMemberQuantityText.setText("总人数:" + studentInfoDao.count());                    } else {                        Toast.makeText(MainActivity.this, "该学号已有对应的学生", 3000).show();                    }                }             }        });

初写之时只考虑了正确输入三项数据之后进行正确添加。写完之后发现若信息填写不完整,程序就会自动停止运行;且就算输入重复的学号也依旧会被添加。所以添加了两个IF语句判断其是否填写完整或者该学号是否已存在,并用Toast语句进行相应的弹窗提示。同时更新总人数显示以方便后续操作。

(4)实现功能:通过学号查询对应学生的姓名

        buttonName.setOnClickListener(new OnClickListener() {            @Override            public void onClick(View v) {                //判断是否已正确输入学号                //未输入或者未正确输入则提示:请输入正确的学号                //已正确输入则显示对应学生姓名                String qNumber = queryNumberText.getText().toString();                if (qNumber.trim().equals("")                        ||studentInfoDao.queryBuilder().where(Properties.Number.eq(qNumber)).list().isEmpty()) {                    Toast.makeText(MainActivity.this, "请输入正确的学号", 3000).show();                } else {                    QueryBuilder<StudentInfo> qb = studentInfoDao.queryBuilder();                    queryNameText.setText(qb.where(Properties.Number.eq(queryNumberText                                    .getText().toString())).list().get(0).getName());                }            }        });

有了上一个功能实现时遇到的问题,在考虑后续功能的时候自然不会忘了加入输入判断,只有在正确输入之后才会进行显示对应学生姓名的操作。
其中通过queryBuilder的where语句匹配学号对应表,通过list().get(0).getName()语句来得到对应名字。

(5)实现功能:以自增长的ID为序,每5人一组,通过分组号查询对应五名学生的姓名

(原先代码如下:)

        buttonGroup.setOnClickListener(new OnClickListener() {            @Override            public void onClick(View v) {                //判断是否已输入分组号                //确定输入后根据分组号显示对应成员                //其中若输入组号超过有人员分配的总组数,则提示:已超过人数上限,该组无成员                if (queryGroupText.getText().toString().trim().equals("")) {                    Toast.makeText(MainActivity.this, "请输入分组号", 3000).show();                } else {                    List<StudentInfo> students = studentInfoDao.loadAll();                    int groupNumber = Integer.valueOf(queryGroupText.getText().toString());                    int firstNumber = (groupNumber - 1) * 5;                    int memberNumber = students.size() - firstNumber;                    if (memberNumber > 0) {                        queryGroupNameText.setText("");                        for (int i = 0; i < memberNumber && i < 5; i++) {                            queryGroupNameText.setText(queryGroupNameText.getText() + "\"" + students.get(firstNumber + i).getName() + "\"");                        }                    } else {                        Toast.makeText(MainActivity.this, "已超过人数上限,该组无成员", 3000).show();                    }                }            }        });

(修改后的代码如下:)

        buttonGroup.setOnClickListener(new OnClickListener() {            @Override            public void onClick(View v) {                //判断是否已输入分组号                //确定输入后根据分组号显示对应成员                //其中若输入组号超过有人员分配的总组数,则提示:已超过人数上限,该组无成员                if (queryGroupText.getText().toString().trim().equals("")) {                    Toast.makeText(MainActivity.this, "请输入分组号", 3000).show();                } else {                    int groupNumber = Integer.valueOf(queryGroupText.getText().toString());                    int firstNumber = (groupNumber - 1) * 5;                    List<StudentInfo> students = studentInfoDao.queryBuilder().limit(5).offset(firstNumber).list();                    int memberNumber = students.size();                    if (memberNumber > 0) {                        queryGroupNameText.setText("");                        for (int i = 0; i < memberNumber; i++) {                            queryGroupNameText.setText(queryGroupNameText.getText() + "\"" + students.get(i).getName() + "\"");                        }                    } else {                        Toast.makeText(MainActivity.this, "已超过人数上限,该组无成员", 3000).show();                    }                }            }        });

在实现该功能的过程中,最初在显示名字时采取的是在setText()里依次get(firstNumber+1~~+5)固定五个人来显示,这样操作当然会在最后一组不满5人的时候报错,故此改成循环语句获得较灵活的小组人数,同时也将代码略微精简了。 其中以”“将学生区分开。
修改:原先用loadAll获取整张表的数据,再进行筛选。后被告知“如果名单上万,难道你要把一万人都取出来再找其中5人?”,于是采用Limit、Offset方法将所需5行信息取出,再获取其名字,谢谢师傅提醒。

(6)实现功能:输入学号,删除对应的学生信息

        buttonDel.setOnClickListener(new OnClickListener() {            @Override            public void onClick(View v) {                //判断是否输入已有的学号                //如果不是,则提示:请输入已有的学号                //如果是,则删除对应的学生信息                String numberText = delNumberText.getText().toString();                QueryBuilder<StudentInfo> qb = studentInfoDao.queryBuilder().where(Properties.Number.eq(numberText));                if (qb.list().isEmpty()){                       Toast.makeText(MainActivity.this, "请输入已有的学号", 3000).show();                } else {                    qb.buildDelete().executeDeleteWithoutDetachingEntities();                    allMemberQuantityText.setText("总人数:" + studentInfoDao.count());                }            }        });

由于在上述其他功能实现时解决了相关问题,在写这段代码的时候便没有遇到什么问题了。
唯一值得一提的是删除信息的方式除了上述语句,也可以在获取对应id之后采用studentInfoDao.deleteByKey(id)来进行删除。
再者由于删除信息减少了学生人数,需要再更新一下显示的总人数,同时也以总人数的减少作为成功操作的反馈提示。

(7)实现功能:输入学号,以及修改后的名字,完成该学号对应的学生姓名的修改

        buttonAlter.setOnClickListener(new OnClickListener() {            @Override            public void onClick(View v) {                //先判断是否输入已有的学号,未输入或者错误输入都将提示:请输入已有的学号                //再判断是否已输入修改后的名字,未输入则提示:请输入想要修改成的名字                //学号和名字都正确输入并点击按钮之后,就进行学号对应的名字修改,并提示:信息已修改                String numberText = alterNumberText.getText().toString();                QueryBuilder<StudentInfo> qb = studentInfoDao.queryBuilder().where(Properties.Number.eq(numberText));                if (qb.list().isEmpty()){                       Toast.makeText(MainActivity.this, "请输入已有的学号", 3000).show();                } else if (alterNameText.getText().toString().trim().equals("")) {                    Toast.makeText(MainActivity.this, "请输入想要修改成的名字", 3000).show();                } else{                    long id = qb.list().get(0).getId();                    int number = Integer.valueOf(numberText);                    int age = qb.list().get(0).getAge();                    StudentInfo sChangedInfo = new StudentInfo(id, number,alterNameText.getText().toString(), age);                    studentInfoDao.insertOrReplace(sChangedInfo);                    Toast.makeText(MainActivity.this, "信息已修改", 3000).show();                }            }        });

同样是为了不报错,在进行修改操作前需要进行判断,分别对学号和姓名是否正确输入进行判断,只有都正确后才会进行修改操作,并弹窗提示。
其中在创建用于替换信息的sChangedInfo表时一定要将学号对应的id信息填入,这是StudentInfo这张表中的主键,是唯一不能重复的属性。若不填,只会在当前表末再新添加一个学生信息,这样就会出现两个学号相同的学生。

最后放上的是该项目显示的成果截图:
实现界面(未美化)

以上所有代码中的解决方法都是我在查看他人资料和源代码之后想出的,可能用的不是最简便最直接甚至是复杂化了的方式来解决的,再次欢迎大家帮忙指出各种不足之处。
同时我自己也准备在知识掌握到一定熟练度之后再回头试试简化完善。

最后列出我所参考的主要几篇文章,感谢大神们的分享,同时也作为自己以后再度翻阅的参考:
官网:http://greendao-orm.com/
Android开源:数据库ORM框架GreenDao学习心得及使用总结:http://www.it165.net/pro/html/201401/9026.html
GreenDao官方文档翻译:http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2014/1127/2069.html
Android之greenDao,一个orm的使用:http://www.cnblogs.com/lee0oo0/archive/2013/12/20/3483604.html
GreenDao 学习笔记:http://blog.csdn.net/ivolianer/article/details/39102405

0 0
原创粉丝点击