最近開始在某個項目中實習,充分認識到了自己的不足,包括能力和性格等各種方面的缺陷。如何快速掌握開發環境,如何與其他程序員溝通交流,如何准確知道分配給自己的模塊具體實現的功能等等,都是大問題,更重要的是,自己不能僅僅只是寫代碼而已,還要清楚自己的代碼的應用環境,別人是怎樣用的,自己應該提供哪些接口。這就屬於擴展性的問題,不是一個新手能夠馬上明白的,但卻是我們是否能夠“脫農”的關鍵。
廢話不多說,本文講訴的是我在項目中使用到的新知識---android數據庫的操作。以前並沒有任何關於android數據庫的開發經歷,所有的東西都是現學現用,所以特意總結一下。
如果想要在android中使用數據庫,使用SQLite是一個非常好的選擇,因為它是android內置的數據庫,提供了很多支持。
數據庫的使用無非就是CRUD,也就是"Create,Read,Update,Delete"這四個基本操作。
一.Create
Create就是創建表,而要想創建表,首先必須要創建或者打開數據庫。
有兩種方式可以做到這點:
1.手動創建或者打開數據庫
SQLiteDatabase database = openOrCreateDatabase("Student.db", MODE_PRIVATE, null);
調用openOrCreateDatabase()方法,如果有該數據庫,就打開,沒有就創建一個。該方法的具體信息還是得看源碼,但一般我們使用的時候,只要指定數據庫的名字和指定該數據庫是私有的就行。
2.使用SQLiteOpenHelper
public class SQLHelper extends SQLiteOpenHelper { public SQLHelper(Context context, String name, CursorFactory factory, int version) { super(context, name, factory, version); } @Override public void onCreate(SQLiteDatabase db) {} @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {} }
然后我們再在Activity這樣使用:
SQLHelper helper = new SQLHelper(this, "Student.db", null, 1);
版本號(不能為負數)是為了方便以后升級數據庫,由於是初版,版本號就是1。
SQLiteOpenHelper是一個抽象的數據庫操作類,首先執行的是OnCreate,這里我們可以執行創建表等動作,但該方法並沒有真正創建數據庫,創建數據庫是在以下的情況:
SQLiteDatabase database = helper.getWritableDatabase();
調用getWritableDatabase()或者getReadableDatabase()時,就會真正創建數據庫。
創建或打開數據庫后,我們就可以建表。
使用數據庫並不是一件難事,難就難在如何建模。這里我們就只建三個簡單的表:
Teacher(teacherId, name, classId), Student(studentId,name,classId),Class(classId,className,studentId,teacherId),其中teacherId,studentId,classId分別是Teacher,Student和Class的主鍵。
SQLite可以直接執行SQL語句,所以,我們可以這樣建表:
String CREATE_CLASS = "Create Table If Not Exists Class(classId integer primary key,"
+ "className varchar(100),"
+ "studentId integer References Student(studentId),"
+ "teacherId integer References Teacher(teacherId))";
SQLiteDatabase db = helper.getWritableDatabase();
db.execSQL(CREATE_CLASS);
每次使用完數據庫都要記得及時關閉數據庫:
db.close();
按照上面的方法,我們可以很快的建好三個表。
二.Updata
更新這部分包括:插入,修改這兩個動作。
先講最基本的動作:插入。
我們現在要想將學生插入到班級中,像是這樣:
ClassInfoProvider provider = new ClassInfoProvider(this); Student student = new Student(2857, "鄭文彪"); ClassInfo classInfo = new ClassInfo("電信1班", 1); provider.addStudent(student, classInfo);
這里我們有三個類:
public class ClassInfo { private String name; private int id; public ClassInfo() { } public ClassInfo(String name, int id) { this.id = id; this.name = name; } public int getId() { return this.id; } public void setId(int id) { this.id = id; } public String getName() { return this.name; } public void setName(String name) { this.name = name; } }
public class Teacher { private int teacherId; private String name; private String className; public Teacher() { } public Teacher(int teacherId, String name) { this.name = name; this.teacherId = teacherId; } public int getTeacherId() { return this.teacherId; } public void setTeacherId(int teacherId) { this.teacherId = teacherId; } public String getName() { return this.name; } public void setName(String name) { this.name = name; } public String getClassName() { return this.className; } public void setClassName(String name) { this.className = name; } }
public class Student { private int studendtd; private String name; private String className; public Student() { } public Student(int studentId, String name) { this.name = name; this.studentId = studentId; } public int getStudentId() { return this.studentId; } public void setStudendId(int studentId) { this.studentId = studendtd; } public String getName() { return this.name; } public void setName(String name) { this.name = name; } public String getClassName() { return this.className; } public void setClassName(String name) { this.className = name; } }
這三個類就是存放Student,Teacher和Class的基本信息。
然后我們開始將學生插入到班級中:
public void addStudent(Student student, ClassInfo classInfo) { String INSERT_STUDENT_INTO_CLASS = "Insert Into Class(className, studentId, classId) Values('" + classInfo.getName() + "'," + student.getStudentId() + "," + classInfo.getId() + ")"; String INSERT_STUDENT = "Insert Into Student(studentId, name, classId) Values(" + student.getStudentId() + "," + "'" + student.getName() + "'," + classInfo.getId() + ")"; SQLiteDatabase db = helper.getWritableDatabase(); db.execSQL(INSERT_STUDENT); db.execSQL(INSERT_STUDENT_INTO_CLASS); db.close(); }
這是直接執行SQL語句的做法。
SQLiteOpenHelper封裝了一個insert方法可以方便我們執行插入行為:
SQLiteDatabase db = helper.getWritableDatabase(); ContentValues values = new ContentValues(); values.put("className", classInfo.getName()); values.put("studentId", student.getStudentId()); values.put("classId", classInfo.getId()); db.insert("Class", null, values); ContentValues values1 = new ContentValues(); values1.put("studentId", student.getStudentId()); values1.put("name", student.getName()); values1.put("classId", classInfo.getId()); db.insert("Student", null, values1); db.close();
ContentValues其實就是一個字典Map,key值就是表中的列值,而value就是對應的字段。insert方法的第一個參數是要插入的表名,第二個參數就是相應的列,這里我們用null表示所有的列,然后就是我們要插入的字段。
這樣的方法確實可以簡化我們的操作,至少不用在我們的代碼中寫那么長的SQL語句,容易犯錯,又很煩,尤其是在插入的動作不斷執行的時候。但有個地方值得注意:如果我們的數據庫是提供接口方法給其他模塊使用,而且以后要修改的人或者查看的人並不是我們自己,他們可能就必須知道這些方法的參數是什么,但直接執行SQL語句,只要他有數據庫的基礎知識,就會明白這是在干嘛,也知道如何修改。更糟糕的情況就是以后android的接口方法發生變化的話,那么,這些代碼可能就會出現問題。當然,我們願意相信他們不會修改接口,因為對接口的修改是一種錯誤的行為,尤其在接口已經發布的情況下。
現在我們的表已經有數據了,如果我們想要修改的話,像是將學生的姓名進行更改,可以這樣操作:
public void updateStudent(int id, String name) { SQLiteDatabase db = helper.getWritableDatabase(); String UPDATE_STUDENT = "Update Student Set name =" + "'" + name + "' Where id=" + id + ""; db.execSQL(UPDATE_STUDENT); db.close(); }
當然,我們同樣可以簡化:
public void updateStudent(int id, String name) { SQLiteDatabase db = helper.getWritableDatabase(); ContentValues values = new ContentValues();
values.put("name", name);
db.update("Student", values, "studentId=?", new String[]{id + ""}); db.close(); }
update方法中,值得注意的是最后面兩個參數,whereClause和whereArgs。whereClause表示要修改哪里,whereArgs表示修改的字段,無論我們是要修改一個字段還是一個以上,這里都需要一個String[]。
三.Read
所謂的Read,就是一系列查詢動作。
我們要在Student這個表中查詢名為"鄭文彪"的學號,就是studentId:
public int getStudentId(String name) { int id = 0; String SELECT_STUDENTID = "Select studentId From Student Where name=?"; SQLiteDatabase db = helper.getWritableDatabase(); Cursor cursor = db.rawQuery(SELECT_STUDENTID, new String[]{name}); if (cursor.moveToNext()) { id = cursor.getInt(0); } cursor.close();
db.close();
return id; }
這里我們需要利用光標Cursor。Cursor指向當前的數據記錄,然后我們可以從光標中獲取相應的數據。
四.Delete
Delete包括表的刪除,數據記錄的刪除。
首先是數據記錄的刪除。現在我們想要刪除姓名為"鄭文彪"的學生的記錄:
public void deleteStudent(Student student) { SQLiteDatabase db = helper.getWritableDatabase(); String DELETE_STUDENT = "Delete From Class Where studentId=?"; db.execSQL(DELETE_STUDENT, new String[]{student.getStudentId() + ""}); db.close(); }
然后這樣調用該方法:
Student student = new Student(2857, "鄭文彪"); ClassInfo classInfo = new ClassInfo("電信1班", 1); provider.addStudent(student, classInfo); provider.deleteStudent(student1);
同樣可以簡化:
db.delete("Class", "studentId=?", new String[]{student.getStudentId() + ""});
接着是刪除表,這個很簡單:
String DROP_CLASS = "Drop Table Class"; SQLiteDatabase db = helper.getWritableDatabase(); db.execSQL(DROP_CLASS);
在做測試的時候,由於需要經常運行,所以數據庫中表的數據會非常冗余,尤其是將鍵值設為自增的時候。所以,我們需要在每次測試后刪除表,這樣下次測試的時候就不會受到影響。
五.結語
SQLite完全是現學現做,所以了解得並不是很深,寫得是一般,但還請各位能夠指出不足之處。
