常常听到已经工做的程序员说天天的工做很无聊,老是一些CURD操做,没什么技术含量,对,今天咱们就要勇敢的探索一下这所谓的“无聊工做”--CURD,并想办法让它有趣起来。所谓的CURD,其实就是数据库的基本操做,C表明create,U表明update,R表明read,D则表明delete。写事后台脚本的朋友对这个应该很熟悉,你就能够随便翻翻啦,而不太了解数据库操做的朋友,我在这里抛砖引玉,讲一下怎么将内存中的数据保存到本地数据库中,您看完后能够更加深刻的去寻找一些资料学习,千万要记得无论别人说什么无聊或者没有技术含量,咱们仍是要一步一个脚印,坚持敲下去!java
前面说了咱们要把这简单的操做讲的有趣些,那我就玩点套路,不直接讲API,先来看一个类:android
package com.aristark.note.database; public class NoteDbScheme { public static final class NoteTable{ public static final String name = "notes"; public static final class Cols{ public static final String UUID = "uuid"; public static final String TITLE = "title"; public static final String CONTENT = "content"; public static final String DATE = "date"; public static final String TAG = "tag"; } } }
类的名字叫NoteDbScheme,代表它是一个关于“计划”的类,并且和database少不了干系,再来回忆Note这个类:程序员
public class Note { private UUID uuid; private String title; private String content; private Date date; private String tag; public Note(){ uuid = UUID.randomUUID(); date = new Date(); } public UUID getUuid() { return uuid; } public Date getDate() { return date; } public void setTitle(String title) { this.title = title; } public String getTitle() { return title; } public void setContent(String content) { this.content = content; } public String getContent() { return content; } public void setTag(String tag) { this.tag = tag; } public String getTag() { return tag; } }
很容易看出来Note类里的私有字段和NoteDbScheme里常量的值是一致的,言下之意,咱们能够从数据库里取值赋给Note类中的字段,也能够把Note类中字段的值存入数据库。再回忆一下以前咱们是怎么用Note类的,咱们在NoteLab建立了一个泛型为Note的ArrayList,而后经过NoteListActivity把它渲染到layout,也就是用户的界面上,这样看来,Note类隐隐约约好像做为一个沟通的桥梁(其实了解MVC模式的朋友应该很好理解)。sql
1.sql简介:了解sql知识点这里
了解sqlite知识点这里数据库
懒得看的就直接看这段sql语句,强行接受个人解释就好了:数组
create table note( _int integer primary key autoincrement, uuid text, title text, content text, date text, tag text )
这段SQL语句的意思是,建立一个名叫“note”的表,包含6个字段,以第一个字段为例,_int为字段名,integer为字段类型,primary key autoincrement表示它是主键并自增。请你们记住这个套路。app
2.SQLiteOpenHelper---数据库好帮手
上面已经给出了建立表并定义字段的方法,在别的地方它能够在终端或者脚本中运行,在Android世界里天然要在类中大展宏图。若是你的英语还能够请你打开Android->sdk>doc,在官方文档中搜索SQLiteOpenHelper,你会发现你要作的这个类基本上已经帮你封装好了,你要作的就是继承它,并依照你的需求去敲敲打打就行。好,来写代码:dom
public class NoteBaseHelper extends SQLiteOpenHelper { @Override public void onCreate(SQLiteDatabase db) { } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { } }
这里须要覆写的onCreate方法就是咱们建立表的地方,当NoteBaseHelper被实例化时,它会自动检测数据库中有没有note这个表,若是没有就调用该方法。因此咱们把刚刚的sql语句写进去:ide
@Override public void onCreate(SQLiteDatabase db) { db.execSQL("create table " +NoteDbScheme.NoteTable.name+"(" + "_id integer primary key autoincrement," +NoteDbScheme.NoteTable.Cols.UUID+"," +NoteDbScheme.NoteTable.Cols.TITLE+"," +NoteDbScheme.NoteTable.Cols.CONTENT+"," +NoteDbScheme.NoteTable.Cols.DATE+"," +NoteDbScheme.NoteTable.Cols.TAG +")" ); }
这里写的和上面实际上是彻底同样的,只不过咱们是用NoteDbScheme中的常量代替了字符串而已,这样作的好处是若是之后表中的字段须要变动的话咱们只要在NoteDbScheme中变动就好了,而不须要动这里的代码。另外一个须要覆写的onUpgrade在数据库须要更新的时候调用。咱们再添加两个常量来标记数据库的名字和版本:学习
public class NoteBaseHelper extends SQLiteOpenHelper { public static final int VERSON = 1; public static final String DATABASE_NAME = "NoteBase"; @Override public void onCreate(SQLiteDatabase db) { db.execSQL("create table " +NoteDbScheme.NoteTable.name+"(" + "_id integer primary key autoincrement," +NoteDbScheme.NoteTable.Cols.UUID+"," +NoteDbScheme.NoteTable.Cols.TITLE+"," +NoteDbScheme.NoteTable.Cols.CONTENT+"," +NoteDbScheme.NoteTable.Cols.DATE+"," +NoteDbScheme.NoteTable.Cols.TAG +")" ); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { } }
最后别忘了建立NoteBaseHelper的构造方法:
public NoteBaseHelper(Context context) { super(context,DATABASE_NAME,null,VERSON); }
DATABASE_NAME和VERSON就是咱们刚才定义过的。
3.建立数据库和表
前面咱们分析了,咱们用NoteLab类将数据渲染到前台用户界面,一样的咱们也用它来与后台数据库交互,先来回顾一下NoteLab类:
public class NoteLab { private static NoteLab sNoteLab; //for the global use private ArrayList<Note> notes; private NoteLab(Context context){ notes = new ArrayList<Note>(); //generate 100 Note Objects // for (int i=0;i<100;i++){ // Note note = new Note(); // note.setTitle("this is title "+i); // note.setContent("this is content "+i+"balabalabalabalalabalabalabalabalala\nbalabalabalabalalabalabalabalabalala\nbalabalabalabalalabalabalabalabalala\nbalabalabalabalalabalabalabalabalala\nbalabalabalabalalabalabalabalabalala\n"); // notes.add(note); // } } public static NoteLab getNoteLab(Context context){ if (sNoteLab == null){ sNoteLab = new NoteLab(context); } return sNoteLab; } public ArrayList<Note> getNotes() { return notes; } public void addNote(Note note){ notes.add(note); } public Note getNote(UUID uuid){ for (Note note : notes){ if (note.getUuid().equals(uuid)){ return note; } } return null; } }
每一个方法的用途均可以经过命名来体现,实在看不懂的翻看我前面两篇文章就好了。
public SQLiteDatabase getWritableDatabase ()
Added in API level 1
Create and/or open a database that will be used for reading and writing. The first time this is called, the database will be opened and onCreate(SQLiteDatabase), onUpgrade(SQLiteDatabase, int, int) and/or onOpen(SQLiteDatabase) will be called.
Once opened successfully, the database is cached, so you can call this method every time you need to write to the database. (Make sure to call close() when you no longer need the database.) Errors such as bad permissions or a full disk may cause this method to fail, but future attempts may succeed if the problem is fixed.
Database upgrade may take a long time, you should not call this method from the application main thread, including from ContentProvider.onCreate().
Returns
a read/write database object valid until close() is called
Throws
SQLiteException if the database cannot be opened for writing
这是Google官方文档中关于SQLiteOpenHelper类的一个方法,用来建立或者打开一个数据库,好,咱们就在NoteLab类的构造方法中来使用这个方法:
public class NoteLab { private static NoteLab sNoteLab; //for the global use private ArrayList<Note> notes; private Context context; private SQLiteDatabase database; private NoteLab(Context context){ notes = new ArrayList<Note>(); database = new NoteBaseHelper(context).getWritableDatabase(); //generate 100 Note Objects // for (int i=0;i<100;i++){ // Note note = new Note(); // note.setTitle("this is title "+i); // note.setContent("this is content "+i+"balabalabalabalalabalabalabalabalala\nbalabalabalabalalabalabalabalabalala\nbalabalabalabalalabalabalabalabalala\nbalabalabalabalalabalabalabalabalala\nbalabalabalabalalabalabalabalabalala\n"); // notes.add(note); // } } ...... }
这样咱们在建立NoteLab的同时也就建立了NoteBase数据库和note表。好,编译,运行,这时候打开Android Device Monitor(Android Studio问号左边的小机器人按钮)
在Android中,全部App的本地数据库都在data->data下,找到咱们这个应用的包名之下的databases目录下,咱们看到了NoteBase数据库,说明咱们成功建立了note表!
插入数据无非就是将一组键值对提交给操做数据的API,而这里的键值对就是以ContentValues来组装的(你们在这里必定要去官方文档搜到这个类好好读一下,否则可能会在这里卡住),咱们如今在NoteLab类中添加以下方法:
private ContentValues getValues(Note note){ ContentValues values = new ContentValues(); values.put(NoteDbScheme.NoteTable.Cols.UUID,note.getUuid().toString()![图片描述][5]); values.put(NoteDbScheme.NoteTable.Cols.TITLE,note.getTitle()); values.put(NoteDbScheme.NoteTable.Cols.CONTENT,note.getContent()); values.put(NoteDbScheme.NoteTable.Cols.DATE,note.getDate().toString()); values.put(NoteDbScheme.NoteTable.Cols.TAG,note.getTag()); return values; }
代码很容易读,put方法接受的就是key--value对,这里再一次用到了NoteDbScheme类,是否是以为很奇妙很方便?如今咱们改写以前的addNote方法:
public void addNote(Note note){ // notes.add(note); ContentValues values = getValues(note); database.insert(NoteDbScheme.NoteTable.name,null,values); }
这里着重掌握insert方法,第一个参数接受将要插入的表名,第三个参数就是咱们须要组装的ContentValues,第二个参数是关于插入空记录的相关设置,你们能够去查看文档。好,编译,运行:
点击右上角加号,输入数据几组数据
很遗憾我如今并不会检验数据是否写进表,无论了继续写代码,去把数据库的记录读出来!
写了这么多有点写不下去了,不知道你是否是也看不下去了,你内心确定想这太冗杂了(谁让我们使用java写android呢,随便写写就感受好多的样子,可是换个角度想咱们能够对外吹咱们的代码量不少啊哈哈,虽然并无什么卵用)。扯店犊子,你们回顾一下C语言中的指针和java语言中的引用(句柄?handle?指针?),或者是数组中的索引,咱们会发现这些重要的抽象对于咱们操做数据是颇有用的,对了,在Android咱们有Cursor(中文意思是游标,对,就是游标卡尺的那个游标),咱们能够变相的把它理解为一个带有指针的数组,咱们能够经过操做“指针”来获取其中的数组。每次咱们经过必定的条件进行数据库查询时,返回的就是一个Cursor, 它能够依次指向查询结果记录的每一条。不当心又说多了,来,写代码,在NoteLab中建立以下方法:
private Cursor queryNote(String whereClause,String[] whereArgs){ Cursor cursor = database.query( NoteDbScheme.NoteTable.name, null, whereClause, whereArgs, null, null, null ); return cursor }
咱们须要关注的是query方法,第一个参数是要查询的表名,第三个参数和第四个参数对应SQL语句中的where(少年,去回顾一下sql语句吧)。
但Cursor还不不太利于咱们的操做,来粉饰一波,在Cursor外面再裹上一层,所以就有了CursorWrapper,建立一个类让它继承CursorWrapper:
public class NoteCursorWrapper extends CursorWrapper { public NoteCursorWrapper(Cursor cursor){ super(cursor); } }
变动刚刚的queryNote方法:
private CursorWrapper queryNote(String whereClause, String[] whereArgs){
Cursor cursor = database.query( NoteDbScheme.NoteTable.name, null, whereClause, whereArgs, null, null, null ); return new CursorWrapper(cursor);
}
之因此说CursorWrapper方便,是由于咱们将查询返回的Cursor传入该类以后,能够很方便的把查询的值取出来,仍是看代码:
......
......
别看了,太晚了,写以前没料到会有这么长。明天继续写。