当前位置:   article > 正文

android实现mysql数据库存储_android菜鸟学习笔记20----Android数据存储(四))Android数据库操作...

mysql数据库留在手机里

Android内置了一个名为SQLite的关系型数据库,这是一款轻量型的数据库,操作十分简便。SQLite与别的数据库不同的是,它没有数据类型。可以保存任何类型的数据到你所想要保存的任何表的任何列中。但它又支持常见的类型比如: NULL, VARCHAR, TEXT, INTEGER, BLOB, CLOB...等。

唯一的例外是:integer primary key 此字段只能存储64位整数。

在JAVA项目中,要使用JDBC操作数据库需要加载数据库驱动,连接数据库等操作。Android简化了我们的数据库操作,无需由我们进行数据库驱动加载、连接等操作。

Android中进行数据库操作,需要涉及到如下几个类:

1)SQLiteOpenHelper:

在android.database.sqlite包下,这是一个抽象的帮助类,用于管理数据库的创建及版本维护操作。

我们在需要获取该类的对象时,需要自定义类继承自SQLiteOpenHelper类,并实现其中的onCreate(SQLiteDatabase), onUpgrade(SQLiteDatabase, int, int),可以选择性地实现 onOpen(SQLiteDatabase)。这个类会自动帮助我们在需要时打开数据库,在不存在时创建数据库,在必要时更新数据库。

常用方法:

9f379749771ef51bbe2621099a28e680.png

一般,在自定义的子类中调用父类中第一个构造方法即可。

构造函数的参数说明:

context:应用的上下文对象

name:要操作的数据库的名称

factory:cursor工厂类对象,一般指定为null

version:数据库的版本号,必须大于等于1,由于控制数据库的升级。

17870f70f7e116e4326c090216aa20c6.png

注意到,只有onCreate()和onUpgrade()是抽象方法,所以自定义子类继承SQLiteOpenHelper时,一定要实现这两个方法。

其中:

onCreate()方法会在数据库不存在,第一次创建时调用,所以数据库中的初始化操作,如创建表等操作需要在该方法中完成。

onUpgrade()方法,新的版本号比原来有提升时,调用,用以完成数据库的升级操作,如新版本的app中,需要添加一张表,或者修改某个表,就需要在新版本的app创建SQLiteOpenHelper对象时,向其构造函数传入一个更大的版本号,这个版本号会被newVersion接收。

6e6c12f9b7a1fbac45cc43954a2edb50.png

getReadaleDatabase()方法,创建或打开一个数据库,返回代表该数据库的只读的SQLiteDatabase对象

getWritableDatabase()方法,创建或打开一个数据库,返回代表该数据库的可读可写的SQLiteDatabase对象。

625ee915d08c05a8dc9b41dc71a8fb66.png

close()方法,用于关闭打开的数据库对象。

2)SQLiteDatabase:

通过SQLiteOpenHelper对象获取SQLiteDatabase对象后,便可以调用SQLiteDatabase类的相关方法进行数据库的增删改查操作了。

该类的常用方法有:

fe085b376e841c90f9b07452e3f65e58.png

execSQL()方法用于执行SQL语句,可以用于执行不需要返回值的一些数据库操作。

3057aa665cea5242685d43340b4f90ff.png

rawQuery()方法一般被用于执行需要返回值的查询操作,查询的结果保存在Cursor对象中。

除了直接执行SQL语句进行数据库操作的方法之外,该类还封装几个更易用的增删改查方法。

a95f8f14b682e81507c4addbbddfd412.png

insert()方法,用于向数据库中插入数据,参数说明:

table:指定要插入数据的表明

nullColumnHack:一般指定为null即可

注意:当values也为null,表示想向数据库中插入一条空记录时,该方法实际执行的SQL语句为insert into table(null) values(null);这样一条sql语句是没法执行的,所以,需要将nullColumnHack指定为任意一个可以为空的字段的字段名。如:nullColumnHack指定为”name”,values为null,此时SQL语句为insert into table(name) values(null);则可以正常执行了。

values:是一个ContentValues对象,用于存放要插入的各个字段名与值的对应关系。

1baa02842f5d101fe9240ad15ac212fd.png

delete()方法,用于删除表中的记录,参数说明:

table指定要操作的表名

whereClause指定where字句,可以包含占位符”?”,如“name = ?”,实际执行时,占位符会被第三个参数中对应索引的值替换

whereArgs:指定where字句中,占位符对应的值,如new String[]{“zhangsan”}

实际执行的语句就是delete from table where name = “zhangsan”

a3a42e0cba14dd064ebf8d1bcab69983.png

update()方法,用于执行表中记录的更新操作,参数说明:

table,whereClause,whereArgs与delete相同含义

values用于指定对应字段名要更新的值的映射关系。

4fa13f2ef02c69af360920a7ae1edc6c.png

query()记录查询方法,最简单的一个重载形式也有七个参数,都是select中的各个字句部分,如where子句部分,group by子句部分,having,order by等。参数说明:

table指定要查询的表名

colmns指定要查询的字段

selection:可以带占位符的where子句部分

slectionArgs:where子句占位符对应的值

groupBy:group by子句部分

having:having子句部分

orderBy:order by 子句部分

等等

a9d263049d7dca28d8d782b1b45e46d1.png

isOpen()判断数据库是否已打开。

0905afbb36022a99649dc989f9bcd172.png

beginTransaction()用于开启事务操作

f488b516456d200b6be4aeb752aa13ac.png

setTransactionSuccessful()方法用于标记事务操作成功

4193936689d944886694db8d333eadc0.png

endTransaction()方法用于关闭事务,若事务标记成功,则提交事务操作,否则,则回滚失败的事务操作。

其他方法,在需要时,可以查询API帮助手册。

3)Cursor:

Cursor是一个接口,其实现类用于存放SQL语句查询的结果集。SQLiteDatabase的rawQuery()及query()方法均会返回该接口的对象,用以存储操作查询返回的结果集。

Cursor对象维持一个游标,默认指向结果集第一条记录之前的位置,可以通过下面几个方法,来移动游标,从而取得需要的记录。当游标已在第一条记录之前,调用moveToPreious(),或者已指向最后一条记录,调用moveToNext()方法时,均会返回false()标识移动失败。

267d81d7e05ea40be4d0a5f2d9b667db.png

bd0a597e52d8cf61cd847cfeda8a9c14.png

getShort()、getString()、getInt()等getXXX()方法,用于根据当前记录的字段的索引获取字段的值。

aa747e820deeabc1a7f5e6ed01f0acc8.png

getColumnName()用于根据索引获取字段名

getColumnNames()用于获取所有的字段名,其顺序与在Cursor中保存的顺序相同。

getCount()用于获取当前Cursor对象中保存的记录数。

7ec236bbabf0039991e02e4662cbdd6b.png

getColumnCount()方法用于获取记录的字段总数

getColumnIndex()用于根据字段名获取其索引,不存在时返回-1。

70ca313fb7530fa24ed24daf91ef198f.png

close()方法,用于关闭当前Cursor对象。

4)ContentValues:

该类用于存放键值对的数据,在数据库的插入更新等操作中,可以使用字段名作为键,使用要插入或更新的字段值作为值。

常用的是put()方法,向ContentValues对象中存储数据。

如:put(“name”,”zhangsan”);等

以上便是数据库操作所涉及的几个主要的类和接口。

下面通过一个具体的代码,来学习使用这些个API:

第一步:

自定义类继承SQLiteOpenHelper类,实现onCreate()和onUpgrade()方法:

1 public class MySqliteHelper extendsSQLiteOpenHelper {2

3 public static final String TAG = "MYSQLITEHELPER";4

5 public static final String CREATE_STUDENT = "create table t_student (" +

6

7 "id integer primary key, name varchar(20), gender varchar(10), age integer)";8

9 publicMySqliteHelper(Context context, String name, CursorFactory factory,10

11 intversion) {12

13 super(context, name, factory, version);14

15 }16

17 @Override18

19 public voidonOpen(SQLiteDatabase db) {20

21 Log.i(TAG,"open db");22

23 super.onOpen(db);24

25 }26

27 @Override28

29 public voidonCreate(SQLiteDatabase db) {30

31 Log.i(TAG,"create db");32

33 Log.i(TAG,"before excSql");34

35 db.execSQL(CREATE_STUDENT);36

37 Log.i(TAG,"after excSql");38

39 }40

41 @Override42

43 public void onUpgrade(SQLiteDatabase db, int oldVersion, intnewVersion) {44

45

46 }47

48 }

第二步,定义实体类:

1 packagecn.csc.sqlite.bean;2

3

4

5 public classStudent {6

7 private intid;8

9 privateString name;10

11 privateString gender;12

13 private intage;14

15

16

17 public intgetId() {18

19 returnid;20

21 }22

23 public void setId(intid) {24

25 this.id =id;26

27 }28

29 publicString getName() {30

31 returnname;32

33 }34

35 public voidsetName(String name) {36

37 this.name =name;38

39 }40

41 publicString getGender() {42

43 returngender;44

45 }46

47 public voidsetGender(String gender) {48

49 this.gender =gender;50

51 }52

53 public intgetAge() {54

55 returnage;56

57 }58

59 public void setAge(intage) {60

61 this.age =age;62

63 }64

65

66

67 publicStudent() {68

69 super();70

71 }72

73 public Student(int id, String name, String gender, intage) {74

75 super();76

77 this.id =id;78

79 this.name =name;80

81 this.gender =gender;82

83 this.age =age;84

85 }86

87 @Override88

89 publicString toString() {90

91 return "Student [id=" + id + ", name=" + name + ", gender=" +gender92

93 + ", age=" + age + "]";94

95 }96

97 }

第三步,定义数据库操作类:

1 public classStudentDao {2

3 privateSQLiteOpenHelper helper;4

5 privateContext context;6

7 publicStudentDao(Context context){8

9 this.context =context;10

11 }12

13 public voidinsert(Student stu){14

15 helper = new MySqliteHelper(context,"students.db", null, 1);16

17 Log.i("MYSQLITEHELPER","before get db");18

19 SQLiteDatabase db =helper.getWritableDatabase();20

21 Log.i("MYSQLITEHELPER","after get db");22

23 db.execSQL("insert into t_student(name, gender, age) values(?,?,?)" , newObject[]{stu.getName(),stu.getGender(),stu.getAge()});24

25 db.close();26

27 }28

29 }

第四步,定义测试类,测试StudentDao的insert()方法:

1 public class TestDao extendsAndroidTestCase {2

3 public voidtestInsert(){4

5 StudentDao dao = newStudentDao(getContext());6

7 dao.insert(new Student(0,"zhangsan", "male", 23));8

9 }10

11 }

运行该测试方法,运行结果如下:

704ced8ec449290d28fb3fea2703742e.png

注意到,定义SQLiteOpenHelper对象,并不会创建数据库,只有调用getWritableDatabase()或者getReadableDatabase()才会调用onCreate()方法,onCreate()内部执行了execSQL()方法,但是并没有调用onOpen()方法。onCreate()方法执行完成后,才接着调用了onOpen()方法。

06a87dfe5a87d9e128086fefe51f2b86.png

从File Explorer中可以看出,students.db存放在/data/data/应用包名/databases/下。

再次运行,由于数据库已经存在,onCreate()方法就没再被调用。

可以通过sqlite3命令来查看数据库内容:

e810cfa22ef1bf17f37e07169a439d68.png

sqlite的简单使用说明:

adb shell挂载虚拟机控制台

cd /data/data/cn.csc.sqlite/databases进入数据库文件所在目录

sqlite3 数据库文件名: 管理数据库文件名所指定的数据库,如sqlite3  students.db,然后光标变为sqlite>,表示进入sqlite操作模式。

.tables 查看数据库中所有的表

可以直接输入sql语句并执行

.exit 退出sqlite操作模式

.schema 查看查看库中所有表的DDL语句

.mode list|column|insert|line|tabs|tcl|csv 改变输出格式

a0d1ed78f8d3c39e773cb1d4c566876a.png

若觉得命令行用着不习惯,可以从File Explorer中把数据库文件导出到电脑中,然后使用图形化工具,如sqlite expert来查看管理数据库。

下载地址:http://pan.baidu.com/s/1jG8G7QY

StudentDao中添加getAllStudents()方法:

1 public ListgetAllStudents(){2

3 List list = new ArrayList();4

5 helper = new MySqliteHelper(context,"students.db", null, 1);6

7 SQLiteDatabase db =helper.getWritableDatabase();8

9 Cursor cursor = db.rawQuery("select id,name,gender,age from t_student", null);10

11 if(cursor == null){12

13 return null;14

15 }16

17 while(cursor.moveToNext()){18

19 Student stu = new Student(cursor.getInt(0),cursor.getString(1),cursor.getString(2),cursor.getInt(3));20

21 Log.i("MYSQLITEHELPER",stu.toString());22

23 list.add(stu);24

25 }26

27

28

29 returnlist;30

31 }

测试,输出:

c2a94ab7876845e9aa9d8f6a4e7dd655.png

上面用的都是直接写完整的SQL语句,下面添加几个方法,调用SQLiteDatabase封装的几个简单操作的API:

update()方法的使用

StudentDao类添加:修改指定id的学生的姓名:

1 public void updateNameById(intid, String newName){2

3 helper = new MySqliteHelper(context,"students.db", null, 1);4

5 SQLiteDatabase db =helper.getWritableDatabase();6

7 ContentValues values = newContentValues();8

9 values.put("name", newName);10

11 db.update("t_student", values, "id=?", new String[]{id+""});12

13 }

测试代码:

1 public voidtestUpdate(){2

3 StudentDao dao = newStudentDao(getContext());4

5 dao.updateNameById(1, "dqrcsc");6

7 }

运行前后:

9d3b7021d51f7a4ea2194258a7078c2b.png

delete()方法的使用:

StudentDao类添加:删除指定id的学生

1 public void deleteById(intid){2

3 helper = new MySqliteHelper(context,"students.db", null, 1);4

5 SQLiteDatabase db =helper.getWritableDatabase();6

7 db.delete("t_student", "id=?", new String[]{id+""});8

9 }

测试代码:

1 public voidtestDelete(){2

3 StudentDao dao = newStudentDao(getContext());4

5 dao.deleteById(2);6

7 }

运行前后:

703054ddc5bea268cdf0df3c3f760e57.png

insert()方法的使用:

StudentDao类中添加如下方法:

1 public voidaddStudent(Student stu){2

3 helper = new MySqliteHelper(context,"students.db", null, 1);4

5 SQLiteDatabase db =helper.getWritableDatabase();6

7 ContentValues values = newContentValues();8

9 values.put("name", stu.getName());10

11 values.put("gender", stu.getGender());12

13 values.put("age", stu.getAge());14

15 db.insert("t_student", null, values);16

17 }

测试代码:

1 public voidtestAddStudent(){2

3 StudentDao dao = newStudentDao(getContext());4

5 dao.addStudent(new Student(0,"csc","male",24));6

7 }

运行前后:

d37c12df59c5720a10d74cbd398b0588.png

query()方法的使用:

1 public Student getStudentById(intid){2

3 Student stu = null;4

5 helper = new MySqliteHelper(context,"students.db", null, 1);6

7 SQLiteDatabase db =helper.getWritableDatabase();8

9 Cursor cursor = db.query("t_student", new String[]{"id","name","gender","age"}, "id=?", new String[]{id+""}, null, null, null);10

11 if(cursor == null){12

13 return null;14

15 }16

17 if(cursor.moveToFirst()){18

19 stu = new Student(cursor.getInt(0),cursor.getString(1),cursor.getString(2),cursor.getInt(3));20

21 }22

23 returnstu;24

25 }

测试代码:

1 public voidtestGetStudentById(){2

3 StudentDao dao = newStudentDao(getContext());4

5 Student stu = dao.getStudentById(1);6

7 Log.i("MYSQLITEHELPER",stu.toString());8

9 }

输出:

3204ee3a0326e5b505625eac478740b4.png

关于事务的操作:

被用烂来的例子,就是银行转账问题,一个账户转出,一个账户转入,两个操作要么同时成功,要么同时失败。

这里懒得再建一张表了,就转年龄吧,其实换汤不换药,原理完全一样。

假设年龄可以在学生之间转换,我要把自己的年龄转10岁给lisi这个同学,要保证这整个操作的原子性,就需要用到事务。

在StudentDao中添加转账年龄的方法:

1 public voidtransAge(){2

3 helper = new MySqliteHelper(context,"students.db", null, 1);4

5 SQLiteDatabase db =helper.getWritableDatabase();6

7 db.execSQL("update t_student set age = age - 10 where name = ?", new String[]{"dqrcsc"});8

9 int i = 1/0;10

11 db.execSQL("update t_student set age = age + 10 where name = ?", new String[]{"lisi"});12

13 }

注意两条update语句之间有个1/0的操作,会导致程序异常终止,只有第一条被执行。

执行前后:

070840bb111d4f90eed7664c01532c57.png

可以看到,我的年龄减去10岁,而lisi的年龄并没有加上10岁。

修改代码,改用事务处理:

1 public voidtransAge(){2

3 helper = new MySqliteHelper(context,"students.db", null, 1);4

5 SQLiteDatabase db =helper.getWritableDatabase();6

7 db.beginTransaction();8

9 try{10

11 db.execSQL("update t_student set age = age - 10 where name = ?", new String[]{"dqrcsc"});12

13 int i = 1/0;14

15 db.execSQL("update t_student set age = age + 10 where name = ?", new String[]{"lisi"});16

17 db.setTransactionSuccessful();18

19 }finally{20

21 db.endTransaction();22

23 }24

25 }

这一次,我的年龄没有减少,lisi的年龄也没有增加,保证了一致性。

关于更新数据库版本的简单示例:

如,由于业务需要,更新了APP,新版本的APP在数据库中增加了一张教师表,现在修改onCreate()方法:

1 public static final String CREATE_TEACHER = "create table t_teacher(id integer primary key, name varchar(20))";2

3 public voidonCreate(SQLiteDatabase db) {4

5 //TODO Auto-generated method stub

6

7 db.execSQL(CREATE_STUDENT);8

9 db.execSQL(CREATE_TEACHER);10

11 }

运行,发现根本没有增加t_teacher这张表,因为数据库已存在,onCreate()方法不会被运行,这时,就需要用到onUpgrade()方法了:

1 public void onUpgrade(SQLiteDatabase db, int oldVersion, intnewVersion) {2

3 //TODO Auto-generated method stub

4

5 if(oldVersion == 1 && newVersion == 2){6

7 db.execSQL(CREATE_TEACHER);8

9 }10

11 }

在StudentDao中添加addTeacher()方法:

1 public voidaddTeacher(){2

3 helper = new MySqliteHelper(context,"students.db", null, 2);4

5 SQLiteDatabase db =helper.getWritableDatabase();6

7 db.execSQL("insert into t_teacher(name) values(?)",new String[]{"wanger"});8

9 }

注意,这里指定的版本号为2。

测试运行结果:

004ac50affca2bc79a8eded0b246fd48.png

数据库操作的学习,就简单学到这里。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/知新_RL/article/detail/764844
推荐阅读
相关标签
  

闽ICP备14008679号