XUtils3框架数据库的基本使用方法

2018-11-06 06:42:59

今天给大家带来数据库模块的讲解,现在主流的ORM框架很多,比如OrmLite,GreenDao,Active Android,Realm等等,这些框架每个都有自己的优点和缺点,大家完全可以根据自己项目的实际需求进行选择,下面开始进入今天的数据库模块的介绍。


今天主要给大家带来以下几个模块: 

如何创建删除一张表 

如何对表进行增删查改操作 

如何创建数据库和删除数据库 

如何建立一表对一表,多表对一表,多表对多表的外键操作。 

相信对ORM框架有过了解的人,大概都知道只要创建一个JavaBean对象,在类的上面和属性的上面添加注释标签,这样就能生成一个表。下面带大家看一下XUtils3的实体bean的写法:


@Table(name="person")

public class PersonTable {

    @Column(name="id",isId=true,autoGen=true)

    private int id;

    //姓名

    @Column(name="name")

    private String name;


    //年龄

    @Column(name="age")

    private int age;


    //性别

    @Column(name="sex")

    private String sex;


    //工资

    @Column(name="salary")

    private String salary;


    public int getId() {

        return id;

    }


    public void setId(int id) {

        this.id = id;

    }


    public String getName() {

        return name;

    }


    public void setName(String name) {

        this.name = name;

    }



    public String getSex() {

        return sex;

    }


    public void setSex(String sex) {

        this.sex = sex;

    }


    public int getAge() {

        return age;

    }


    public void setAge(int age) {

        this.age = age;

    }



    public String getSalary() {

        return salary;

    }


    public void setSalary(String salary) {

        this.salary = salary;

    }


    @Override

    public String toString() {

        return "PersonTable [id=" + id + ", name=" + name + ", age=" + age

                + ", sex=" + sex + ", salary=" + salary + "]";

    }

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

通过上方的实体bean,我们需要知道一个表对应的实体bean需要注意以下几点: 

1.在类名上面加入@Table标签,标签里面的属性name的值就是以后生成的数据库的表的名字 

2.实体bean里面的属性需要加上@Column标签,这样这个标签的name属性的值会对应数据库里面的表的字段。 

3.实体bean里面的普通属性,如果没有加上@Column标签就不会在生成表的时候在表里面加入字段。 

4.实体bean中必须有一个主键,如果没有主键,表以后不会创建成功,@Column(name=”id”,isId=true,autoGen=true)这个属性name的值代表的是表的主键的标识,isId这个属性代表的是该属性是不是表的主键,autoGen代表的是主键是否是自增长,如果不写autoGen这个属性,默认是自增长的属性。


既然知道怎么写实体bean了,下面看看如何在程序中创建一个数据库和如何生成表的吧。


public class XUtil {

    static DbManager.DaoConfig daoConfig;

    public static DaoConfig getDaoConfig(){

        File file=new File(Environment.getExternalStorageDirectory().getPath());

        if(daoConfig==null){

            daoConfig=new DbManager.DaoConfig()

            .setDbName("shiyan.db")

            .setDbDir(file)

            .setDbVersion(1)

            .setAllowTransaction(true)

            .setDbUpgradeListener(new DbUpgradeListener() {

                @Override

                public void onUpgrade(DbManager db, int oldVersion, int newVersion) {


                }

            });

        }

        return daoConfig;

    }

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

通过XUtil.getDaoConfig()方法,我们能够获取到一个DaoConfig对象。通过getDaoConfig()方法,我们可以知道这个方法主要可以做以下事情: 

1.setDbName 设置数据库的名称 

2.setDbDir 设置数据库存放的路径 

3.setDbVersion 设置数据库的版本 

4.setAllowTransaction(true) 设置允许开启事务 

5.setDbUpgradeListener 设置一个版本升级的监听方法 

那么具体我们什么时候创建的表呢?如果我们单纯的调用XUti.getDaoConfig()方法是不能够创建PersonTable这个实体对应的person这张表的,那么如何创建表呢? 

只需要一下几步: 

1.DaoConfig daoConfig=XUtil.getDaoConfig(); 

2.DbManager db = x.getDb(daoConfig); 

这里我要告诉大家的是,数据库里面表的创建的时间,只有在你对数据库里面的操作涉及到这张表的操作时,会先判断当前的表是否存在,如果不存在,才会创建一张表,如果存在,才会进行相应的CRUD操作,但是只要我们想进行一张表的CRUD操作,我们必须先执行上面的2步,通俗点说就是必须拿到一个Dbmanger这个对象,我为什么这么说呢?那么咱们就先看一下DbManger的庐山真面目吧。 

DbManager部分源码如下:


public interface DbManager extends Closeable {


    DaoConfig getDaoConfig();


    SQLiteDatabase getDatabase();


    /**

     * 保存实体类或实体类的List到数据库,

     * 如果该类型的id是自动生成的, 则保存完后会给id赋值.

     *

     * @param entity

     * @return

     * @throws DbException

     */

    boolean saveBindingId(Object entity) throws DbException;


    /**

     * 保存或更新实体类或实体类的List到数据库, 根据id对应的数据是否存在.

     *

     * @param entity

     * @throws DbException

     */

    void saveOrUpdate(Object entity) throws DbException;


    /**

     * 保存实体类或实体类的List到数据库

     *

     * @param entity

     * @throws DbException

     */

    void save(Object entity) throws DbException;


    /**

     * 保存或更新实体类或实体类的List到数据库, 根据id和其他唯一索引判断数据是否存在.

     *

     * @param entity

     * @throws DbException

     */

    void replace(Object entity) throws DbException;


    ///////////// delete

    void deleteById(Class<?> entityType, Object idValue) throws DbException;


    void delete(Object entity) throws DbException;


    void delete(Class<?> entityType) throws DbException;


    void delete(Class<?> entityType, WhereBuilder whereBuilder) throws DbException;


    ///////////// update

    void update(Object entity, String... updateColumnNames) throws DbException;


    void update(Object entity, WhereBuilder whereBuilder, String... updateColumnNames) throws DbException;


    ///////////// find

    <T> T findById(Class<T> entityType, Object idValue) throws DbException;


    <T> T findFirst(Class<T> entityType) throws DbException;


    <T> List<T> findAll(Class<T> entityType) throws DbException;


    <T> Selector<T> selector(Class<T> entityType) throws DbException;


    DbModel findDbModelFirst(SqlInfo sqlInfo) throws DbException;


    List<DbModel> findDbModelAll(SqlInfo sqlInfo) throws DbException;


    ///////////// table


    /**

     * 删除表

     *

     * @param entityType

     * @throws DbException

     */

    void dropTable(Class<?> entityType) throws DbException;


    /**

     * 添加一列,

     * 新的entityType中必须定义了这个列的属性.

     *

     * @param entityType

     * @param column

     * @throws DbException

     */

    void addColumn(Class<?> entityType, String column) throws DbException;


    ///////////// db


    /**

     * 删除库

     *

     * @throws DbException

     */

    void dropDb() throws DbException;


    /**

     * 关闭数据库,

     * xUtils对同一个库的链接是单实例的, 一般不需要关闭它.

     *

     * @throws IOException

     */

    void close() throws IOException;


    ///////////// custom

    void execNonQuery(SqlInfo sqlInfo) throws DbException;


    void execNonQuery(String sql) throws DbException;


    Cursor execQuery(SqlInfo sqlInfo) throws DbException;


    Cursor execQuery(String sql) throws DbException;

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

通过DbManager这个类我们知道主要它做了以下几件事情: 

1.getDaoConfig 获取数据库的配置信息 

2.getDatabase 获取数据库实例 

3.saveBindingId saveOrUpdate save 插入数据的3个方法(保存数据) 

4.replace 只有存在唯一索引时才有用 慎重 

5.delete操作的4种方法(删除数据) 

6.update操作的2种方法(修改数据) 

7.find操作6种方法(查询数据) 

8.dropTable 删除表 

9.addColumn 添加一列 

10.dropDb 删除数据库


插入操作

private void insert() {

        try {

            PersonTable person=new PersonTable();

            person.setName("小丽");

            person.setAge(19);

            person.setSex("woman");

            person.setSalary(4000);

            db.save(person);

          //db.saveOrUpdate(person);

          //db.saveBindingId(person);

        } catch (DbException e) {

            e.printStackTrace();

        }

    }

1

2

3

4

5

6

7

8

9

10

11

12

13

14

结果如下: 

 

3种插入操作所需要的参数都是一个实体bean。save和saveOrUpdate的区别就是当一个实体里面的主键一样时如果使用saveOrUpdate会将当前主键对应的这条数据进行替换,而如果你使用了save就会报错。 

saveBindingId主要是存进去的数据如果当前表有主键回合主键进行绑定关联。 

当你执行完这个方法后,你会看到数据库里面person表里面多了一条数据.


查询操作

当前数据库中的表的效果如下: 

 

1.findById的使用 

该方法主要是通过主键的值来进行查找表里面的数据 

需求:查找上方person表里面id为3的数据


private void query(){

        try {

            PersonTable person = db.findById(PersonTable.class, "2");

            Log.e("person",person.toString());

        } catch (DbException e) {

            e.printStackTrace();

        }

    }

1

2

3

4

5

6

7

8

结果如下: 

 

2.findFirst的使用 

该方法主要是返回当前表里面的第一条数据 

需求:查找上方person表里面的第一条数据


private void query() {

        try {

            PersonTable person = db.findFirst(PersonTable.class);

            Log.e("person", person.toString());

        } catch (DbException e) {

            e.printStackTrace();

        }

    }

1

2

3

4

5

6

7

8

 

3.findAll的使用 

该方法主要是返回当前表里面的所有数据 

需求:查找person表里面的所有数据


private void query() {

        try {

            List<PersonTable> persons = db.findAll(PersonTable.class);

            Log.e("persons", persons.toString());

        } catch (DbException e) {

            e.printStackTrace();

        }

    }

1

2

3

4

5

6

7

8


4.selector的使用 

该方法主要是用来进行一些特定条件的查找 

需求:查找person表里面age大于30并且性别为man的数据


private void query() {

        try {

            List<PersonTable> persons = db.selector(PersonTable.class).where("age", ">", 30).and("sex", "=", "man").findAll();

            for(PersonTable person:persons){

                Log.e("person",person.toString());

            }

        } catch (DbException e) {

            e.printStackTrace();

        }

    }

1

2

3

4

5

6

7

8

9

10

 

5.findDbModelFirst的使用 

说起这个方法,该方法返回一个DbModel对象,那么该对象是什么呢? 

DbModel源码如下:


public final class DbModel {


    /**

     * key: columnName

     * value: valueStr

     */

    private HashMap<String, String> dataMap = new HashMap<String, String>();


    public String getString(String columnName) {

        return dataMap.get(columnName);

    }


    public int getInt(String columnName) {

        return Integer.valueOf(dataMap.get(columnName));

    }


    public boolean getBoolean(String columnName) {

        String value = dataMap.get(columnName);

        if (value != null) {

            return value.length() == 1 ? "1".equals(value) : Boolean.valueOf(value);

        }

        return false;

    }


    public double getDouble(String columnName) {

        return Double.valueOf(dataMap.get(columnName));

    }


    public float getFloat(String columnName) {

        return Float.valueOf(dataMap.get(columnName));

    }


    public long getLong(String columnName) {

        return Long.valueOf(dataMap.get(columnName));

    }


    public Date getDate(String columnName) {

        long date = Long.valueOf(dataMap.get(columnName));

        return new Date(date);

    }


    public java.sql.Date getSqlDate(String columnName) {

        long date = Long.valueOf(dataMap.get(columnName));

        return new java.sql.Date(date);

    }


    public void add(String columnName, String valueStr) {

        dataMap.put(columnName, valueStr);

    }


    /**

     * @return key: columnName

     */

    public HashMap<String, String> getDataMap() {

        return dataMap;

    }


    /**

     * @param columnName

     * @return

     */

    public boolean isEmpty(String columnName) {

        return TextUtils.isEmpty(dataMap.get(columnName));

    }

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

通过源码,我们分析发现DbModel本质就是一个key为当前表的字段,value为当前某条记录的值的一个HashMap. 

需求:查找person表中第一条数据的那个人的年龄age是多少。


private void query() {

        try {

            DbModel model = db.findDbModelFirst(new SqlInfo("select * from person"));

            Log.e("age", model.getString("age"));

        } catch (DbException e) {

            e.printStackTrace(); 

        }

    }

1

2

3

4

5

6

7

8

 

注意上面的sqlInfo对象的创建的构造参数只需要传入一个sql语句即可。 

6.findDbModelAll的用法 

该方法的用途就是返回满足sqlInfo信息的所有数据的字段的一个集合。 

需求:查找person表中年龄age大于25里面的所有人的姓名


private void query() {

        try {

            List<DbModel> persons = db.findDbModelAll(new SqlInfo("select * from person where age > 25"));

            for(DbModel person:persons){

                Log.e("name", person.getString("name"));

            }

        } catch (DbException e) {

            e.printStackTrace();

        }

    }

1

2

3

4

5

6

7

8

9

10



基本把查询的6种方式都说了一遍,当然上面的6种需求不一定完全用上面的查询方法可以查出结果,我这么查询的目的主要是带领大家熟悉一下XUtils3的6种查询方法是如何使用的,会了上面的6种方法,我相信你的查询不会有太大问题,至于复杂的查询无非就是sql语句的基本功力了,大家赶紧动手操练一下吧。


修改操作

当前数据库中的表的效果如下: 

 

修改一共有2种方法: 

第一种: 

需求:我们把上面的id为1的这条记录的age修改为25岁


private void update() {

        try{

            PersonTable person = db.findById(PersonTable.class, 1);

            person.setAge(25);

            db.update(person, "age");

        }catch(Exception e){

            e.printStackTrace();

        }

    }

1

2

3

4

5

6

7

8

9

通过方法,我们知道首先要通过DBManager通过查找的方法先找到id为1的这个实体bean,如果你对里面的哪个字段需要修改,只需要重新set这个属性的值,然后调用DBManager.update方法,第一个参数是需要修改的实体,第二个参数是对应的属性。 

 

第二种: 

需求:将person表中性别为man的工资salary都变成6000。


private void update() {

        try {

            List<PersonTable> persons = db.findAll(PersonTable.class);

            for(PersonTable person:persons){

                person.setSalary(6000);

                db.update(person, WhereBuilder.b("sex", "=", "man"), "salary");

            }

        } catch (Exception e) {

            e.printStackTrace();

        }

    }

1

2

3

4

5

6

7

8

9

10

11



修改数据一共就2种方法,基本都是需要一个实体bean对象去进行操作的,上面的第二种方法无非就是在修改数据时,多了一个限制条件,这样修改数据显得灵活一些。 

上面第二种update的方法的参数简单介绍一下: 

第一个参数:实体bean对象 

第二个参数:一个WhereBuilder对象,主要是通过静态b方法去构造一个where条件语句 

第三个参数:需要修改的字段名,如果你的需求是修改了2个或者更多个字段,只需要在后面加上相应的参数即可,例如第二种方法我不止修改salary还需要修改age统一为40岁,参考如下;


private void update() {

        try {

            List<PersonTable> persons = db.findAll(PersonTable.class);

            for(PersonTable person:persons){

                person.setSalary(6000);

                person.setAge(40);

                db.update(person, WhereBuilder.b("sex", "=", "man"), "salary","age");

            }

        } catch (Exception e) {

            e.printStackTrace();

        }

    }

1

2

3

4

5

6

7

8

9

10

11

12

删除操作

当前数据库中的person表的效果如下: 

 

1.deleteById的用法 

该方法主要是根据表的主键进行单条记录的删除 

需求:删除上方person表中id为5的记录


private void delete() {

        try {

            db.deleteById(PersonTable.class, 5);

        } catch (DbException e) {

            e.printStackTrace();

        }

    }

1

2

3

4

5

6

7

结果如下: 

 

2.delete(Object entity)的用法 

该方法主要是根据实体bean进行对表里面的一条或多条数据进行删除 

需求:删除name为骆驼这条信息的记录


private void delete() {

        try {

            PersonTable person = db.selector(PersonTable.class).where("name", "=", "骆驼").findFirst();

            db.delete(person);

        } catch (DbException e) {

            e.printStackTrace(); 

        }

    }

1

2

3

4

5

6

7

8

 

3.delete(Class<?> entityType) 

该方法主要是用来删除表格里面的所有数据,但是注意:表还会存在,只是表里面数据没有了


private void delete() {

        try {

            db.delete(PersonTable.class);

        } catch (DbException e) {

            e.printStackTrace(); 

        }

    }

1

2

3

4

5

6

7

4.delete(Class<?> entityType, WhereBuilder whereBuilder) 

该方法主要是根据where语句的条件进行删除操作 

需求:将person表总sex为woman并且salary为5000的信息删除


private void delete() {

        try {

            db.delete(PersonTable.class, WhereBuilder.b("sex", "=", "woman").and("salary", "=", "5000"));

        } catch (DbException e) {

            e.printStackTrace();

        }

    }

1

2

3

4

5

6

7

 

5.dropTable(Class<?> entityType) 

该方法是用来删除表


private void delete() {

        try {

            db.dropTable(PersonTable.class);

        } catch (DbException e) {

            e.printStackTrace();

        }

    }

1

2

3

4

5

6

7

6.dropDb() 

该方法是用来删除数据库


    db.dropDb();

1

其他方法

1.addColumn(Class<> entityType, String column) 

需求:在上方表中加入一个country字段 

PersonTable的实体代码如下:


@Table(name="person")

public class PersonTable {

    @Column(name="id",isId=true,autoGen=true)

    private int id;

    //姓名

    @Column(name="name")

    private String name;


    //年龄

    @Column(name="age")

    private int age;


    //性别

    @Column(name="sex")

    private String sex;


    //工资

    @Column(name="salary")

    private int salary;


    //国家

    @Column(name="country",property="中国")

    private String country;


    public int getId() {

        return id;

    }


    public void setId(int id) {

        this.id = id;

    }


    public String getName() {

        return name;

    }


    public void setName(String name) {

        this.name = name;

    }



    public String getSex() {

        return sex;

    }


    public void setSex(String sex) {

        this.sex = sex;

    }


    public int getAge() {

        return age;

    }


    public void setAge(int age) {

        this.age = age;

    }



    public int getSalary() {

        return salary;

    }


    public void setSalary(int salary) {

        this.salary = salary;

    }


    public String getCountry() {

        return country;

    }


    public void setCountry(String country) {

        this.country = country;

    }


    @Override

    public String toString() {

        return "PersonTable [id=" + id + ", name=" + name + ", age=" + age

                + ", sex=" + sex + ", salary=" + salary + ", country="

                + country + "]";

    }

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

private void addColumn() {

        try {

            db.addColumn(PersonTable.class, "country");

        } catch (DbException e) {

            e.printStackTrace();

        }

    }

1

2

3

4

5

6

7

8

执行完addColumn方法,我们看到person表里面多了一个country字段. 

结果如下: 



总结

上面主要介绍了XUtils3的数据库模块,包括如何创建数据库,如何创建表,如何给表进行添加一列,如何对表进行增删查改的操作。说了这么多,相信大家肯定对XUtils3的数据库模块有了一个基本的理解,至于一表对一表,多表对一表,多表对多表等等这类需求,无非就是在某个表里面加入一个字段,或者创建一个第三方表用来维护表与表之间的关系,这种类型的例子我就不举例说明了,原因是那些需求都离不开上面的增删查改的方法,我相信你只要把上面的方法完全会用,你的XUtils3的数据库模块的基本使用就不会有问题了。哇塞,下午2点多了,饿死了。。。。今天就到这里了~


  • 2020-03-06 22:28:05

    git中submodule子模块的添加、使用和删除

    执行成功后,git status会看到项目中修改了.gitmodules,并增加了一个新文件(为刚刚添加的路径) git diff --cached查看修改内容可以看到增加了子模块,并且新文件下为子模块的提交hash摘要 git commit提交即完成子模块的添加

  • 2020-03-09 21:34:48

    Android TV 包安装成功后找不到启动图标

    生成APK文件,用U盘插入到小米盒子上,然后点击安装,提示安装成功。 可是找不到启动图标,安装成功的弹窗也没有打开的选项。 而我之前测试装的一款手机应用是可以找到启动图标的。

  • 2020-03-09 21:37:10

    安卓Tv端App开发与手机端的开发的区别

    因为大部分电视机的配置一般都比手机低,但是电视机一般都是用来看视频的,所以在做视频解码的时候,因为电视机配置比较低,所以大多数手机运行流畅的播放器在电视机上面都会卡顿,或者出现一些其他的问题,经过我同事长时间的测试,认为百度播放器跟小米播放器比较适合电视机作为播放器开发使用。如果你们要选择一个播放器,要先拿一个demo去很多台不同类型的电视机去测试,因为网络上面的播放器在电视机卡的真的很多,先测试好了再使用可以节约大家的时间。

  • 2020-03-09 22:11:39

    聊聊真实的 Android TV 开发技术栈

    智能电视越来越普及了,华为说四月发布智能电视跳票了,一加也说今后要布局智能电视,在智能电视方向,小米已经算是先驱了。但是还有不少开发把智能电视简单的理解成手机屏幕的放大,其实这两者并不一样。