第一步:新建一个Android工程命名为db目录结构如下图:

Android开发入门之数据库例子_第1张图片

第二步:在cn.leigo.service包下新建DBOpenHelper类,该类继承自DBOpenHelper如下:

package cn.leigo.service;import android.content.Context;import android.database.sqlite.SQLiteDatabase;import android.database.sqlite.SQLiteOpenHelper;public class DBOpenHelper extends SQLiteOpenHelper {public DBOpenHelper(Context context) {super(context, "leigo.db", null, 2);  //<包>/databases/}@Overridepublic void onCreate(SQLiteDatabase db) {// 数据库第一次被创建的时候调用的db.execSQL("CREATE TABLE person (personid integer primary key autoincrement, name varchar(20))");}@Overridepublic void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {db.execSQL("ALTER TABLE person ADD phone VARCHAR(12) NULL");}}

第三步:引入测试类,在cn.leigo.test包下新建PersonServiceTest类,该类继承AndroidTestCase:

package cn.leigo.test;import cn.leigo.service.DBOpenHelper;import android.test.AndroidTestCase;public class PersonServiceTest extends AndroidTestCase {public void testCreateDB() throws Exception {DBOpenHelper dbOpenHelper = new DBOpenHelper(getContext());dbOpenHelper.getWritableDatabase();}}

右键Outline视图中的PersonServiceTest,Run as ->Android JUnit Test

Android开发入门之数据库例子_第2张图片

运行成功!


在File Explorer中找到该数据库文件


我们可以看到数据库字段已经创建成功了,将数据库文件导出到桌面上然后打开

Android开发入门之数据库例子_第3张图片

同时android自动帮你生成了一张名为android_metadata的表,该表存储了所使用的语言信息


现在我们将数据库的版本升级为2,然后再进行测试,此时只会调用onUpgrade方法,我们看到结果如下:


Android开发入门之数据库例子_第4张图片


下面到SQLiteOpenHelper源码下查看它是怎样实现的

/* * Copyright (C) 2007 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * *      http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */package android.database.sqlite;import android.content.Context;import android.database.sqlite.SQLiteDatabase.CursorFactory;import android.util.Log;/** * A helper class to manage database creation and version management. * * <p>You create a subclass implementing {@link #onCreate}, {@link #onUpgrade} and * optionally {@link #onOpen}, and this class takes care of opening the database * if it exists, creating it if it does not, and upgrading it as necessary. * Transactions are used to make sure the database is always in a sensible state. * * <p>This class makes it easy for {@link android.content.ContentProvider} * implementations to defer opening and upgrading the database until first use, * to avoid blocking application startup with long-running database upgrades. * * <p>For an example, see the NotePadProvider class in the NotePad sample application, * in the <em>samples/</em> directory of the SDK.</p> * * <p class="note"><strong>Note:</strong> this class assumes * monotonically increasing version numbers for upgrades.  Also, there * is no concept of a database downgrade; installing a new version of * your app which uses a lower version number than a * previously-installed version will result in undefined behavior.</p> */public abstract class SQLiteOpenHelper {    private static final String TAG = SQLiteOpenHelper.class.getSimpleName();    private final Context mContext;    private final String mName;    private final CursorFactory mFactory;    private final int mNewVersion;    private SQLiteDatabase mDatabase = null;    private boolean mIsInitializing = false;    /**     * Create a helper object to create, open, and/or manage a database.     * This method always returns very quickly.  The database is not actually     * created or opened until one of {@link #getWritableDatabase} or     * {@link #getReadableDatabase} is called.     *     * @param context to use to open or create the database     * @param name of the database file, or null for an in-memory database     * @param factory to use for creating cursor objects, or null for the default     * @param version number of the database (starting at 1); if the database is older,     *     {@link #onUpgrade} will be used to upgrade the database     */    public SQLiteOpenHelper(Context context, String name, CursorFactory factory, int version) {        if (version < 1) throw new IllegalArgumentException("Version must be >= 1, was " + version);        mContext = context;        mName = name;        mFactory = factory;        mNewVersion = version;    }    /**     * 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     * {@link #onCreate}, {@link #onUpgrade} and/or {@link #onOpen} will be     * called.     *     * <p>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 {@link #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.</p>     *     * <p class="caution">Database upgrade may take a long time, you     * should not call this method from the application main thread, including     * from {@link android.content.ContentProvider#onCreate ContentProvider.onCreate()}.     *     * @throws SQLiteException if the database cannot be opened for writing     * @return a read/write database object valid until {@link #close} is called     */    public synchronized SQLiteDatabase getWritableDatabase() {        if (mDatabase != null && mDatabase.isOpen() && !mDatabase.isReadOnly()) {            return mDatabase;  // The database is already open for business        }        if (mIsInitializing) {            throw new IllegalStateException("getWritableDatabase called recursively");        }        // If we have a read-only database open, someone could be using it        // (though they shouldn't), which would cause a lock to be held on        // the file, and our attempts to open the database read-write would        // fail waiting for the file lock.  To prevent that, we acquire the        // lock on the read-only database, which shuts out other users.        boolean success = false;        SQLiteDatabase db = null;        if (mDatabase != null) mDatabase.lock();        try {            mIsInitializing = true;            if (mName == null) {                db = SQLiteDatabase.create(null);            } else {                db = mContext.openOrCreateDatabase(mName, 0, mFactory);            }            int version = db.getVersion();            if (version != mNewVersion) {                db.beginTransaction();                try {                    if (version == 0) {                        onCreate(db);                    } else {                        if (version > mNewVersion) {                            Log.wtf(TAG, "Can't downgrade read-only database from version " +                                    version + " to " + mNewVersion + ": " + db.getPath());                        }                        onUpgrade(db, version, mNewVersion);                    }                    db.setVersion(mNewVersion);                    db.setTransactionSuccessful();                } finally {                    db.endTransaction();                }            }            onOpen(db);            success = true;            return db;        } finally {            mIsInitializing = false;            if (success) {                if (mDatabase != null) {                    try { mDatabase.close(); } catch (Exception e) { }                    mDatabase.unlock();                }                mDatabase = db;            } else {                if (mDatabase != null) mDatabase.unlock();                if (db != null) db.close();            }        }    }    /**     * Create and/or open a database.  This will be the same object returned by     * {@link #getWritableDatabase} unless some problem, such as a full disk,     * requires the database to be opened read-only.  In that case, a read-only     * database object will be returned.  If the problem is fixed, a future call     * to {@link #getWritableDatabase} may succeed, in which case the read-only     * database object will be closed and the read/write object will be returned     * in the future.     *     * <p class="caution">Like {@link #getWritableDatabase}, this method may     * take a long time to return, so you should not call it from the     * application main thread, including from     * {@link android.content.ContentProvider#onCreate ContentProvider.onCreate()}.     *     * @throws SQLiteException if the database cannot be opened     * @return a database object valid until {@link #getWritableDatabase}     *     or {@link #close} is called.     */    public synchronized SQLiteDatabase getReadableDatabase() {        if (mDatabase != null && mDatabase.isOpen()) {            return mDatabase;  // The database is already open for business        }        if (mIsInitializing) {            throw new IllegalStateException("getReadableDatabase called recursively");        }        try {            return getWritableDatabase();        } catch (SQLiteException e) {            if (mName == null) throw e;  // Can't open a temp database read-only!            Log.e(TAG, "Couldn't open " + mName + " for writing (will try read-only):", e);        }        SQLiteDatabase db = null;        try {            mIsInitializing = true;            String path = mContext.getDatabasePath(mName).getPath();            db = SQLiteDatabase.openDatabase(path, mFactory, SQLiteDatabase.OPEN_READONLY);            if (db.getVersion() != mNewVersion) {                throw new SQLiteException("Can't upgrade read-only database from version " +                        db.getVersion() + " to " + mNewVersion + ": " + path);            }            onOpen(db);            Log.w(TAG, "Opened " + mName + " in read-only mode");            mDatabase = db;            return mDatabase;        } finally {            mIsInitializing = false;            if (db != null && db != mDatabase) db.close();        }    }    /**     * Close any open database object.     */    public synchronized void close() {        if (mIsInitializing) throw new IllegalStateException("Closed during initialization");        if (mDatabase != null && mDatabase.isOpen()) {            mDatabase.close();            mDatabase = null;        }    }    /**     * Called when the database is created for the first time. This is where the     * creation of tables and the initial population of the tables should happen.     *     * @param db The database.     */    public abstract void onCreate(SQLiteDatabase db);    /**     * Called when the database needs to be upgraded. The implementation     * should use this method to drop tables, add tables, or do anything else it     * needs to upgrade to the new schema version.     *     * <p>The SQLite ALTER TABLE documentation can be found     * <a href="http://sqlite.org/lang_altertable.html">here</a>. If you add new columns     * you can use ALTER TABLE to insert them into a live table. If you rename or remove columns     * you can use ALTER TABLE to rename the old table, then create the new table and then     * populate the new table with the contents of the old table.     *     * @param db The database.     * @param oldVersion The old database version.     * @param newVersion The new database version.     */    public abstract void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion);    /**     * Called when the database has been opened.  The implementation     * should check {@link SQLiteDatabase#isReadOnly} before updating the     * database.     *     * @param db The database.     */    public void onOpen(SQLiteDatabase db) {}}

以m开头的蓝色变量都是成员(member)变量


在源码getWritableDatabase()方法中

if (mName == null) {                db = SQLiteDatabase.create(null);            } else {                db = mContext.openOrCreateDatabase(mName, 0, mFactory);            }

判断数据库的名称是否为空,如果是则调用create()方法,否则调用
openOrCreateDatabase(mName, 0, mFactory)

方法,第二个参数为模式

第一次调用时,数据库默认版本为0,而我们传入的版本为1,调用onCreate(db);这个方法

,这里还用到了数据库事务。


下面来实现数据的增删改查操作,新建Person类,该类在cn.leigo.domain包下

package cn.leigo.domain;public class Person {private Integer id;private String name;private String phone;public Person() {}public Person(String name, String phone) {super();this.name = name;this.phone = phone;}public Person(Integer id, String name, String phone) {super();this.id = id;this.name = name;this.phone = phone;}public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public String getPhone() {return phone;}public void setPhone(String phone) {this.phone = phone;}@Overridepublic String toString() {return "Person [id=" + id + ", name=" + name + ", phone=" + phone + "]";}}
在cn.leigo.service下新建PersonService类,此业务类处理增删改查

package cn.leigo.service;import java.util.ArrayList;import java.util.List;import android.content.Context;import android.database.Cursor;import android.database.sqlite.SQLiteDatabase;import cn.leigo.domain.Person;public class PersonService {private DBOpenHelper dbOpenHelper;public PersonService(Context context) {this.dbOpenHelper = new DBOpenHelper(context);}/** * 添加记录 * @param person */public void save(Person person) {SQLiteDatabase db = dbOpenHelper.getWritableDatabase();db.execSQL("INSERT INTO person(name, phone) VALUES(?,?)", new Object[] {person.getName(), person.getPhone() });db.close();}/** * 删除记录 * @param id 记录ID */public void delete(Integer id) {SQLiteDatabase db = dbOpenHelper.getWritableDatabase();db.execSQL("DELETE FROM person WHERE personid=?", new Object[] { id });db.close();}/** * 更新记录 * @param person */public void update(Person person) {SQLiteDatabase db = dbOpenHelper.getWritableDatabase();db.execSQL("UPDATE person SET name=?,phone=? WHERE personid=?",new Object[] { person.getName(), person.getPhone(),person.getId() });db.close();}/** * 查找记录 * @param id  记录ID * @return */public Person find(Integer id) {Person person = null;SQLiteDatabase db = dbOpenHelper.getReadableDatabase();Cursor cursor = db.rawQuery("SELECT * FROM person WHERE personid=?",new String[] { id + "" });if (cursor.moveToFirst()) {String name = cursor.getString(cursor.getColumnIndex("name"));String phone = cursor.getString(cursor.getColumnIndex("phone"));person = new Person(id, name, phone);}cursor.close();db.close();return person;}/** * 分页获取记录 * @param offset  跳过前面多少条记录 * @param maxResult每页获取多少条记录 * @return */public List<Person> getScrollData(int offset, int maxResult) {Person person = null;List<Person> persons = new ArrayList<Person>();;SQLiteDatabase db = dbOpenHelper.getReadableDatabase();Cursor cursor = db.rawQuery("SELECT * FROM person order by personid asc limit ?,?",new String[] { offset + "", maxResult + "" });while (cursor.moveToNext()) {int id = cursor.getInt(cursor.getColumnIndex("personid"));String name = cursor.getString(cursor.getColumnIndex("name"));String phone = cursor.getString(cursor.getColumnIndex("phone"));person = new Person(id, name, phone);persons.add(person);}cursor.close();db.close();return persons;}/** * 获取记录总数 * @return */public long getCount() {SQLiteDatabase db = dbOpenHelper.getReadableDatabase();Cursor cursor = db.rawQuery("SELECT count(*) FROM person", null);cursor.moveToFirst();long count = cursor.getLong(0);cursor.close();db.close();return count;}}

package cn.leigo.service;import java.util.ArrayList;import java.util.List;import android.content.Context;import android.database.Cursor;import android.database.sqlite.SQLiteDatabase;import cn.leigo.domain.Person;public class PersonService {private DBOpenHelper dbOpenHelper;public PersonService(Context context) {this.dbOpenHelper = new DBOpenHelper(context);}/** * 添加记录 * @param person */public void save(Person person) {SQLiteDatabase db = dbOpenHelper.getWritableDatabase();db.execSQL("INSERT INTO person(name, phone) VALUES(?,?)", new Object[] {person.getName(), person.getPhone() });db.close();}/** * 删除记录 * @param id 记录ID */public void delete(Integer id) {SQLiteDatabase db = dbOpenHelper.getWritableDatabase();db.execSQL("DELETE FROM person WHERE personid=?", new Object[] { id });db.close();}/** * 更新记录 * @param person */public void update(Person person) {SQLiteDatabase db = dbOpenHelper.getWritableDatabase();db.execSQL("UPDATE person SET name=?,phone=? WHERE personid=?",new Object[] { person.getName(), person.getPhone(),person.getId() });db.close();}/** * 查找记录 * @param id  记录ID * @return */public Person find(Integer id) {Person person = null;SQLiteDatabase db = dbOpenHelper.getReadableDatabase();Cursor cursor = db.rawQuery("SELECT * FROM person WHERE personid=?",new String[] { id + "" });if (cursor.moveToFirst()) {String name = cursor.getString(cursor.getColumnIndex("name"));String phone = cursor.getString(cursor.getColumnIndex("phone"));person = new Person(id, name, phone);}cursor.close();db.close();return person;}/** * 分页获取记录 * @param offset  跳过前面多少条记录 * @param maxResult每页获取多少条记录 * @return */public List<Person> getScrollData(int offset, int maxResult) {Person person = null;List<Person> persons = new ArrayList<Person>();;SQLiteDatabase db = dbOpenHelper.getReadableDatabase();Cursor cursor = db.rawQuery("SELECT * FROM person order by personid asc limit ?,?",new String[] { offset + "", maxResult + "" });while (cursor.moveToNext()) {int id = cursor.getInt(cursor.getColumnIndex("personid"));String name = cursor.getString(cursor.getColumnIndex("name"));String phone = cursor.getString(cursor.getColumnIndex("phone"));person = new Person(id, name, phone);persons.add(person);}cursor.close();db.close();return persons;}/** * 获取记录总数 * @return */public long getCount() {SQLiteDatabase db = dbOpenHelper.getReadableDatabase();Cursor cursor = db.rawQuery("SELECT count(*) FROM person", null);cursor.moveToFirst();long count = cursor.getLong(0);cursor.close();db.close();return count;}}

然后进行测试:

增:

public void testSave() throws Exception {PersonService service = new PersonService(getContext());Person person = new Person("zhangsan", "18900000000");service.save(person);}


查:

public void testFind() throws Exception {PersonService service = new PersonService(getContext());Person person = service.find(1);Log.d(TAG, person.toString());}



改:

public void testUpdate() throws Exception {PersonService service = new PersonService(getContext());Person person = service.find(1);person.setPhone("15100000000");service.update(person);}


统计条数:

public void testGetCount() throws Exception {PersonService service = new PersonService(getContext());long count = service.getCount();Log.d(TAG, count + "");}



public void testSave() throws Exception {PersonService service = new PersonService(getContext());for (int i = 0; i < 20; i++) {Person person = new Person("test" + i, "1890000000" + i);service.save(person);}}

再来进行一次统计


分页:

public void testGetScrollData() throws Exception {PersonService service = new PersonService(getContext());List<Person> persons = service.getScrollData(0, 5);for (Person person : persons) {Log.d(TAG, person.toString());}}


删:

public void testDelete() throws Exception {PersonService service = new PersonService(getContext());service.delete(21);}


增删改查另外一种方法:

package cn.leigo.service;import java.util.ArrayList;import java.util.List;import android.content.ContentValues;import android.content.Context;import android.database.Cursor;import android.database.sqlite.SQLiteDatabase;import cn.leigo.domain.Person;public class OtherPersonService {private DBOpenHelper dbOpenHelper;public OtherPersonService(Context context) {this.dbOpenHelper = new DBOpenHelper(context);}/** * 添加记录 *  * @param person */public void save(Person person) {SQLiteDatabase db = dbOpenHelper.getWritableDatabase();// db.execSQL("INSERT INTO person(name, phone) VALUES(?,?)", new// Object[] {// person.getName(), person.getPhone() });ContentValues values = new ContentValues();values.put("name", person.getName());values.put("phone", person.getPhone());db.insert("person", null, values);db.close();}/** * 删除记录 *  * @param id *            记录ID */public void delete(Integer id) {SQLiteDatabase db = dbOpenHelper.getWritableDatabase();// db.execSQL("DELETE FROM person WHERE personid=?", new Object[] { id// });db.delete("person", "personid=?", new String[] { id + "" });db.close();}/** * 更新记录 *  * @param person */public void update(Person person) {SQLiteDatabase db = dbOpenHelper.getWritableDatabase();// db.execSQL(// "UPDATE person SET name=?,phone=? WHERE personid=?",// new Object[] { person.getName(), person.getPhone(),// person.getId() });ContentValues values = new ContentValues();values.put("name", person.getName());values.put("phone", person.getPhone());db.update("person", values, "personid=?", new String[] { person.getId()+ "" });db.close();}/** * 查找记录 *  * @param id *            记录ID * @return */public Person find(Integer id) {Person person = null;SQLiteDatabase db = dbOpenHelper.getReadableDatabase();// Cursor cursor = db.rawQuery("SELECT * FROM person WHERE personid=?",// new String[] { id + "" });Cursor cursor = db.query("person", null, "personid=?",new String[] { id + "" }, null, null, null);if (cursor.moveToFirst()) {String name = cursor.getString(cursor.getColumnIndex("name"));String phone = cursor.getString(cursor.getColumnIndex("phone"));person = new Person(id, name, phone);}cursor.close();db.close();return person;}/** * 分页获取记录 *  * @param offset *            跳过前面多少条记录 * @param maxResult每页获取多少条记录 * @return */public List<Person> getScrollData(int offset, int maxResult) {Person person = null;List<Person> persons = new ArrayList<Person>();SQLiteDatabase db = dbOpenHelper.getReadableDatabase();// Cursor cursor = db.rawQuery(// "SELECT * FROM person order by personid asc limit ?,?",// new String[] { offset + "", maxResult + "" });Cursor cursor = db.query("person", null, null, null, null, null,"personid asc", offset + "," + maxResult);while (cursor.moveToNext()) {int id = cursor.getInt(cursor.getColumnIndex("personid"));String name = cursor.getString(cursor.getColumnIndex("name"));String phone = cursor.getString(cursor.getColumnIndex("phone"));person = new Person(id, name, phone);persons.add(person);}cursor.close();db.close();return persons;}/** * 获取记录总数 *  * @return */public long getCount() {SQLiteDatabase db = dbOpenHelper.getReadableDatabase();// Cursor cursor = db.rawQuery("SELECT count(*) FROM person", null);Cursor cursor = db.query("person", new String[] { "count(*)" }, null,null, null, null, null);cursor.moveToFirst();long count = cursor.getLong(0);cursor.close();db.close();return count;}}


测试类:

package cn.leigo.test;import java.util.List;import android.test.AndroidTestCase;import android.util.Log;import cn.leigo.domain.Person;import cn.leigo.service.DBOpenHelper;import cn.leigo.service.OtherPersonService;public class OtherPersonServiceTest extends AndroidTestCase {private static final String TAG = "OtherPersonServiceTest";public void testCreateDB() throws Exception {DBOpenHelper dbOpenHelper = new DBOpenHelper(getContext());dbOpenHelper.getWritableDatabase();}public void testSave() throws Exception {OtherPersonService service = new OtherPersonService(getContext());Person person = new Person("leigo", "13500000000");service.save(person);}public void testDelete() throws Exception {OtherPersonService service = new OtherPersonService(getContext());service.delete(22);}public void testUpdate() throws Exception {OtherPersonService service = new OtherPersonService(getContext());Person person = service.find(1);person.setPhone("151023000000");service.update(person);}public void testFind() throws Exception {OtherPersonService service = new OtherPersonService(getContext());Person person = service.find(22);Log.d(TAG, person.toString());}public void testGetScrollData() throws Exception {OtherPersonService service = new OtherPersonService(getContext());List<Person> persons = service.getScrollData(5, 5);for (Person person : persons) {Log.d(TAG, person.toString());}}public void testGetCount() throws Exception {OtherPersonService service = new OtherPersonService(getContext());long count = service.getCount();Log.d(TAG, count + "");}}



更多相关文章

  1. Android Repo 超时的解决方法
  2. android的sqlite主键设置方法。
  3. java中Arraylist复制方法
  4. Android中完全退出APP的方法
  5. android中动态给EditText获得焦点并弹起键盘的方法
  6. Android 7.0以上和7.0以下获取USB,sdcard路径的方法
  7. android 图片处理方法(整理)
  8. Android 方法调用堆栈信息显示

随机推荐

  1. Android 点击空白区域 软键盘消失
  2. Android EditText 不可编辑到可编辑状态
  3. 一些databinding 赋值小技巧
  4. Android与服务器端数据交互(基于SOAP协议
  5. android如何用代码实现界面ui
  6. android studio 签名配置
  7. Android页面跳转是如何传递参数的
  8. 分享一个Android左右侧滑的效果实现 slid
  9. android 操作路由表
  10. Android 之 LayoutInflater