前段时间写了个安卓平台下SQLite数据库操作的实例 ,一直没得时间总结 ,今天把它弄出来了。
在Android 运行时环境包含了完整的 SQLite。
首先介绍一下SQLite这个数据库:
SQLite,是一款轻型的数据库,是遵守ACID的关联式数据库管理系统,它的设计目标是嵌入式的,而且目前已经在很多嵌入式产品中使用了它,它占用资源非常的低,在嵌入式设备中,可能只需要几百K的内存就够了。它能够支持Windows/Linux/Unix等等主流的操作系统,同时能够跟很多程序语言相结合,比如 Tcl、C#、PHP、Java等,还有ODBC接口,同样比起Mysql、PostgreSQL这两款开源世界著名的数据库管理系统来讲,它的处理速度比他们都快。
有一点相对其他数据库来说比较特殊的是:SQLite是无类型的. 这意味着你可以保存任何类型的数据到你所想要保存的任何表的任何列中,意思就是说话你可以在创建数据库表的时候任意定义数据类型,却不影响实际使用时的数据存储。
举个例子说就是你可以在创建表时定义username字段为varchar类型,但是实时使用时你可以向这个字段存入1、2.5、2012-6-6.。。这样的整型,单精,以及时间等其他类型,在SQLite里没有这种限制。
但是有一种情况例外:当字段类型为 ”Integer Primary Key” 时,就是定义表主键,这个就只能是integer类型。和普通数据库相同 。
SQLite 不支持一些标准的 SQL 功能,特别是外键约束(FOREIGN KEY constrains),嵌套 transcaction 和 RIGHT OUTER JOIN 和 FULL OUTER JOIN, 还有一些 ALTER TABLE 功能。
需要注意一点: SQLite不支持存储过程!
我这里就简单介绍,如需要可自行去了解关于SQLite的更多知识,
然后是我的Demo(一个简单的完成数据库增删查改操作):
首先是项目目录结构:
在本项目中我们使用JUnit测试,就要在AndroidManifest.xml配置JUnit
AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="org.yzsoft.sqlitedemo.test" android:versionCode="1" android:versionName="1.0" > <!-- 为了方便测试,我直接把上面包位置改成我项目的测试包下 --> <uses-sdk android:minSdkVersion="8" android:targetSdkVersion="15" /> <application android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <!-- 因为我们开发项目的时候,包会比较多,所以最好在下面这个activity的配置( android:name="org.yzsoft.sqlitedemo.activity.MainActivity" )这句这里打上完整的 包名.类名 ,虽然可以直接用 .类名,但是这个.类名是建立在 <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="org.yzsoft.sqlitedemo.test" 之上的,用package+.类名也刚好可以组合成完整路径。但是我们保险一点写完整去。 --> <activity android:name="org.yzsoft.sqlitedemo.activity.MainActivity" android:label="@string/title_activity_main" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <!-- JUnit要加这句 --> <uses-library android:name="android.test.runner" /> </application> <!-- JUnit还要加这段 (android:targetPackage测试类所在包名 ) --> <instrumentation android:name="android.test.InstrumentationTestRunner" android:label="Test Unit Tests" android:targetPackage="org.yzsoft.sqlitedemo.test" > </instrumentation> </manifest>
1、MainActivity.java(因为本项目中使用JUnit进行测试,就不需要Activity了,留着不用写它)
package org.yzsoft.sqlitedemo.activity; import org.yzsoft.sqlitedemo.util.R; import org.yzsoft.sqlitedemo.util.R.layout; import org.yzsoft.sqlitedemo.util.R.menu; import android.os.Bundle; import android.app.Activity; import android.view.Menu; public class MainActivity extends Activity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.activity_main, menu); return true; } }
2、DBOpenHandler.java
package org.yzsoft.sqlitedemo.util; import android.content.Context; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteDatabase.CursorFactory; import android.database.sqlite.SQLiteOpenHelper; public class DBOpenHandler extends SQLiteOpenHelper { /** * * @param context * 上下文 * @param name * 数据库名 * @param factory * 可选的数据库游标工厂类,当查询(query)被提交时,该对象会被调用来实例化一个游标。默认为null。 * @param version * 数据库版本号 */ public DBOpenHandler(Context context, String name, CursorFactory factory, int version) { super(context, name, factory, version); } @Override public void onCreate(SQLiteDatabase db) {// 覆写onCreate方法,当数据库创建时就用SQL命令创建一个表 // 创建一个t_users表,id主键,自动增长,字符类型的username和pass; db.execSQL("create table t_users(id integer primary key autoincrement,username varchar(200),pass varchar(200) )"); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { // TODO Auto-generated method stub } }
3、TUsers.java(实体类,习惯了WEB开发,总会加个实体类,方便)
package org.yzsoft.sqlitedemo.vo; public class TUsers { private int id ; private String username; private String pass; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getUsername() { return username; } public void setUsername(String username) { this.username = username; } public String getPass() { return pass; } public void setPass(String pass) { this.pass = pass; } }
4、SQLiteDAOImpl.java(数据库操作实现类)
package org.yzsoft.sqlitedemo.util; import java.util.ArrayList; import java.util.List; import org.yzsoft.sqlitedemo.vo.TUsers; import android.content.Context; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; public class SQLiteDAOImpl { private DBOpenHandler dbOpenHandler; public SQLiteDAOImpl(Context context) { this.dbOpenHandler = new DBOpenHandler(context, "dbtest.db", null, 1); } public void save(TUsers tusers) {// 插入记录 SQLiteDatabase db = dbOpenHandler.getWritableDatabase();// 取得数据库操作 db.execSQL("insert into t_users (username,pass) values(?,?)", new Object[] { tusers.getUsername(), tusers.getPass() }); db.close();// 记得关闭数据库操作 } public void delete(Integer id) {// 删除纪录 SQLiteDatabase db = dbOpenHandler.getWritableDatabase(); db.execSQL("delete from t_users where id=?", new Object[] { id.toString() }); db.close(); } public void update(TUsers tusers) {// 修改纪录 SQLiteDatabase db = dbOpenHandler.getWritableDatabase(); db.execSQL("update t_users set username=?,pass=? where" + " id=?", new Object[] { tusers.getUsername(), tusers.getPass(), tusers.getId() }); db.close(); } public TUsers find(Integer id) {// 根据ID查找纪录 TUsers tusers = null; SQLiteDatabase db = dbOpenHandler.getReadableDatabase(); // 用游标Cursor接收从数据库检索到的数据 Cursor cursor = db.rawQuery("select * from t_users where id=?", new String[] { id.toString() }); if (cursor.moveToFirst()) {// 依次取出数据 tusers = new TUsers(); tusers.setId(cursor.getInt(cursor.getColumnIndex("id"))); tusers.setUsername(cursor.getString(cursor.getColumnIndex("username"))); tusers.setPass(cursor.getString(cursor.getColumnIndex("pass"))); } db.close(); return tusers; } public List<TUsers> findAll() {// 查询所有记录 List<TUsers> lists = new ArrayList<TUsers>(); TUsers tusers = null; SQLiteDatabase db = dbOpenHandler.getReadableDatabase(); // Cursor cursor=db.rawQuery("select * from t_users limit ?,?", new // String[]{offset.toString(),maxLength.toString()}); // //这里支持类型MYSQL的limit分页操作 Cursor cursor = db.rawQuery("select * from t_users ", null); while (cursor.moveToNext()) { tusers = new TUsers(); tusers.setId(cursor.getInt(cursor.getColumnIndex("id"))); tusers.setUsername(cursor.getString(cursor.getColumnIndex("username"))); tusers.setPass(cursor.getString(cursor.getColumnIndex("pass"))); lists.add(tusers); } db.close(); return lists; } public long getCount() {//统计所有记录数 SQLiteDatabase db = dbOpenHandler.getReadableDatabase(); Cursor cursor = db.rawQuery("select count(*) from t_users ", null); cursor.moveToFirst(); db.close(); return cursor.getLong(0); } }
5、TUsersTest.java(JUnit测试类)
package org.yzsoft.sqlitedemo.test; import java.util.List; import org.yzsoft.sqlitedemo.util.DBOpenHandler; import org.yzsoft.sqlitedemo.util.SQLiteDAOImpl; import org.yzsoft.sqlitedemo.vo.TUsers; import android.test.AndroidTestCase; import android.util.Log; public class TUsersTest extends AndroidTestCase { private static final String TAG = "这个是测试类";// 准备好TAG标识用于LOG输出,方便我们用LogCat进行调试 public void testCreate() { DBOpenHandler dbHandler = new DBOpenHandler(this.getContext(), "dbtest.db", null, 1);// 创建数据库文件 dbHandler.getWritableDatabase(); } public void testSave() throws Throwable { SQLiteDAOImpl p = new SQLiteDAOImpl(this.getContext()); TUsers tuser = new TUsers(); tuser.setUsername("用户"); tuser.setPass("密码"); p.save(tuser); Log.i(TAG, "插入成功");// 用日志记录一个我们自定义的输出。可以在LogCat窗口中查看,方便调试 } public void testUpate() throws Throwable { SQLiteDAOImpl p = new SQLiteDAOImpl(this.getContext()); TUsers tuser = p.find(1); tuser.setUsername("张三"); p.update(tuser); Log.i(TAG, "修改成功"); } public void testDelete() throws Throwable { SQLiteDAOImpl p = new SQLiteDAOImpl(this.getContext()); p.delete(2); Log.i(TAG, "删除成功"); } public void testFind() throws Throwable { SQLiteDAOImpl p = new SQLiteDAOImpl(this.getContext()); TUsers tuser = p.find(1); Log.i(TAG, tuser.getUsername() + " 用户名"); } public void testGetCount() throws Throwable { SQLiteDAOImpl p = new SQLiteDAOImpl(this.getContext()); Log.i(TAG, p.getCount() + " 总记录数"); } public void testFindAll() throws Throwable { SQLiteDAOImpl p = new SQLiteDAOImpl(this.getContext()); List<TUsers> tusers = p.findAll(); for (TUsers tuser : tusers) { Log.i(TAG, tuser.getUsername() + " 用户名"); } } }
然后是测试中的一些截图:
最后我们把File Exploer中data/data/项目包名/databases/dbtest.db 导出来,用Navicat Premium等数据库管理工具查看里面的数据:
导出来看看:
虽然安卓平台中SQLite是个小型的本地数据库,但是有些地方使用起来会比文件存储更方便,本文只是对它作一个简单的操作实例 ,有这方面兴趣的童鞋可以自己去深入研究。也希望大家能多交流交流~~~~
最最后~附上项目源码: