




已阅读5页,还剩14页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
上次我向大家介绍了SQLite的基本信息和使用过程,相信朋友们对SQLite已经有所了解了,那今天呢,我就和大家分享一下在Android中如何使用SQLite。现在的主流移动设备像Android、iPhone等都使用SQLite作为复杂数据的存储引擎,在我们为移动设备开发应用程序时,也许就要使用到SQLite来存储我们大量的数据,所以我们就需要掌握移动设备上的SQLite开发技巧。对于Android平台来说,系统内置了丰富的API来供开发人员操作SQLite,我们可以轻松的完成对数据的存取。下面就向大家介绍一下SQLite常用的操作方法,为了方便,我将代码写在了Activity的onCreate中:javaview plaincopy1. Override2. protectedvoidonCreate(BundlesavedInstanceState)3. super.onCreate(savedInstanceState);4. 5. /打开或创建test.db数据库6. SQLiteDatabasedb=openOrCreateDatabase(test.db,Context.MODE_PRIVATE,null);7. db.execSQL(DROPTABLEIFEXISTSperson);8. /创建person表9. db.execSQL(CREATETABLEperson(_idINTEGERPRIMARYKEYAUTOINCREMENT,nameVARCHAR,ageSMALLINT);10. Personperson=newPerson();11. =john;12. person.age=30;13. /插入数据14. db.execSQL(INSERTINTOpersonVALUES(NULL,?,?),newO,person.age);15. 16. =david;17. person.age=33;18. /ContentValues以键值对的形式存放数据19. ContentValuescv=newContentValues();20. cv.put(name,);21. cv.put(age,person.age);22. /插入ContentValues中的数据23. db.insert(person,null,cv);24. 25. cv=newContentValues();26. cv.put(age,35);27. /更新数据28. db.update(person,cv,name=?,newStringjohn);29. 30. Cursorc=db.rawQuery(SELECT*FROMpersonWHEREage=?,newString33);31. while(c.moveToNext()32. int_id=c.getInt(c.getColumnIndex(_id);33. Stringname=c.getString(c.getColumnIndex(name);34. intage=c.getInt(c.getColumnIndex(age);35. Log.i(db,_id=+_id+,name=+name+,age=+age);36. 37. c.close();38. 39. /删除数据40. db.delete(person,age ? and age ?”等,最后的whereArgs参数是占位符的实际参数值;delete方法的参数也是一样。下面来说说查询操作。查询操作相对于上面的几种操作要复杂些,因为我们经常要面对着各种各样的查询条件,所以系统也考虑到这种复杂性,为我们提供了较为丰富的查询形式:javaview plaincopy1. db.rawQuery(Stringsql,StringselectionArgs);2. db.query(Stringtable,Stringcolumns,Stringselection,StringselectionArgs,StringgroupBy,Stringhaving,StringorderBy);3. db.query(Stringtable,Stringcolumns,Stringselection,StringselectionArgs,StringgroupBy,Stringhaving,StringorderBy,Stringlimit);4. db.query(Stringdistinct,Stringtable,Stringcolumns,Stringselection,StringselectionArgs,StringgroupBy,Stringhaving,StringorderBy,Stringlimit);上面几种都是常用的查询方法,第一种最为简单,将所有的SQL语句都组织到一个字符串中,使用占位符代替实际参数,selectionArgs就是占位符实际参数集;下面的几种参数都很类似,columns表示要查询的列所有名称集,selection表示WHERE之后的条件语句,可以使用占位符,groupBy指定分组的列名,having指定分组条件,配合groupBy使用,orderBy指定排序的列名,limit指定分页参数,distinct可以指定“true”或“false”表示要不要过滤重复值。需要注意的是,selection、groupBy、having、orderBy、limit这几个参数中不包括“WHERE”、“GROUP BY”、“HAVING”、“ORDER BY”、“LIMIT”等SQL关键字。最后,他们同时返回一个Cursor对象,代表数据集的游标,有点类似于JavaSE中的ResultSet。下面是Cursor对象的常用方法:javaview plaincopy1. c.move(intoffset);/以当前位置为参考,移动到指定行2. c.moveToFirst();/移动到第一行3. c.moveToLast();/移动到最后一行4. c.moveToPosition(intposition);/移动到指定行5. c.moveToPrevious();/移动到前一行6. c.moveToNext();/移动到下一行7. c.isFirst();/是否指向第一条8. c.isLast();/是否指向最后一条9. c.isBeforeFirst();/是否指向第一条之前10. c.isAfterLast();/是否指向最后一条之后11. c.isNull(intcolumnIndex);/指定列是否为空(列基数为0)12. c.isClosed();/游标是否已关闭13. c.getCount();/总数据项数14. c.getPosition();/返回当前游标所指向的行数15. c.getColumnIndex(StringcolumnName);/返回某列名对应的列索引值16. c.getString(intcolumnIndex);/返回当前行指定列的值在上面的代码示例中,已经用到了这几个常用方法中的一些,关于更多的信息,大家可以参考官方文档中的说明。最后当我们完成了对数据库的操作后,记得调用SQLiteDatabase的close()方法释放数据库连接,否则容易出现SQLiteException。上面就是SQLite的基本应用,但在实际开发中,为了能够更好的管理和维护数据库,我们会封装一个继承自SQLiteOpenHelper类的数据库操作类,然后以这个类为基础,再封装我们的业务逻辑方法。下面,我们就以一个实例来讲解具体的用法,我们新建一个名为db的项目,结构如下:其中DBHelper继承了SQLiteOpenHelper,作为维护和管理数据库的基类,DBManager是建立在DBHelper之上,封装了常用的业务方法,Person是我们的person表对应的JavaBean,MainActivity就是我们显示的界面。下面我们先来看一下DBHelper:javaview plaincopy1. packagecom.scott.db;2. 3. importandroid.content.Context;4. importandroid.database.sqlite.SQLiteDatabase;5. importandroid.database.sqlite.SQLiteOpenHelper;6. 7. publicclassDBHelperextendsSQLiteOpenHelper8. 9. privatestaticfinalStringDATABASE_NAME=test.db;10. privatestaticfinalintDATABASE_VERSION=1;11. 12. publicDBHelper(Contextcontext)13. /CursorFactory设置为null,使用默认值14. super(context,DATABASE_NAME,null,DATABASE_VERSION);15. 16. 17. /数据库第一次被创建时onCreate会被调用18. Override19. publicvoidonCreate(SQLiteDatabasedb)20. db.execSQL(CREATETABLEIFNOTEXISTSperson+21. (_idINTEGERPRIMARYKEYAUTOINCREMENT,nameVARCHAR,ageINTEGER,infoTEXT);22. 23. 24. /如果DATABASE_VERSION值被改为2,系统发现现有数据库版本不同,即会调用onUpgrade25. Override26. publicvoidonUpgrade(SQLiteDatabasedb,intoldVersion,intnewVersion)27. db.execSQL(ALTERTABLEpersonADDCOLUMNotherSTRING);28. 29. 正如上面所述,数据库第一次创建时onCreate方法会被调用,我们可以执行创建表的语句,当系统发现版本变化之后,会调用onUpgrade方法,我们可以执行修改表结构等语句。为了方便我们面向对象的使用数据,我们建一个Person类,对应person表中的字段,如下:javaview plaincopy1. packagecom.scott.db;2. 3. publicclassPerson4. publicint_id;5. publicStringname;6. publicintage;7. publicStringinfo;8. 9. publicPerson()10. 11. 12. publicPerson(Stringname,intage,Stringinfo)13. =name;14. this.age=age;15. =info;16. 17. 然后,我们需要一个DBManager,来封装我们所有的业务方法,代码如下:javaview plaincopy1. packagecom.scott.db;2. 3. importjava.util.ArrayList;4. importjava.util.List;5. 6. importandroid.content.ContentValues;7. importandroid.content.Context;8. importandroid.database.Cursor;9. importandroid.database.sqlite.SQLiteDatabase;10. 11. publicclassDBManager12. privateDBHelperhelper;13. privateSQLiteDatabasedb;14. 15. publicDBManager(Contextcontext)16. helper=newDBHelper(context);17. /因为getWritableDatabase内部调用了mContext.openOrCreateDatabase(mName,0,mFactory);18. /所以要确保context已初始化,我们可以把实例化DBManager的步骤放在Activity的onCreate里19. db=helper.getWritableDatabase();20. 21. 22. /*23. *addpersons24. *parampersons25. */26. publicvoidadd(Listpersons)27. db.beginTransaction();/开始事务28. try29. for(Personperson:persons)30. db.execSQL(INSERTINTOpersonVALUES(null,?,?,?),newO,person.age,);31. 32. db.setTransactionSuccessful();/设置事务成功完成33. finally34. db.endTransaction();/结束事务35. 36. 37. 38. /*39. *updatepersonsage40. *paramperson41. */42. publicvoidupdateAge(Personperson)43. ContentValuescv=newContentValues();44. cv.put(age,person.age);45. db.update(person,cv,name=?,newS);46. 47. 48. /*49. *deleteoldperson50. *paramperson51. */52. publicvoiddeleteOldPerson(Personperson)53. db.delete(person,age=?,newStringString.valueOf(person.age);54. 55. 56. /*57. *queryallpersons,returnlist58. *returnList59. */60. publicListquery()61. ArrayListpersons=newArrayList();62. Cursorc=queryTheCursor();63. while(c.moveToNext()64. Personperson=newPerson();65. person._id=c.getInt(c.getColumnIndex(_id);66. =c.getString(c.getColumnIndex(name);67. person.age=c.getInt(c.getColumnIndex(age);68. =c.getString(c.getColumnIndex(info);69. persons.add(person);70. 71. c.close();72. returnpersons;73. 74. 75. /*76. *queryallpersons,returncursor77. *returnCursor78. */79. publicCursorqueryTheCursor()80. Cursorc=db.rawQuery(SELECT*FROMperson,null);81. returnc;82. 83. 84. /*85. *closedatabase86. */87. publicvoidcloseDB()88. db.close();89. 90. 我们在DBManager构造方法中实例化DBHelper并获取一个SQLiteDatabase对象,作为整个应用的数据库实例;在添加多个Person信息时,我们采用了事务处理,确保数据完整性;最后我们提供了一个closeDB方法,释放数据库资源,这一个步骤在我们整个应用关闭时执行,这个环节容易被忘记,所以朋友们要注意。我们获取数据库实例时使用了getWritableDatabase()方法,也许朋友们会有疑问,在getWritableDatabase()和getReadableDatabase()中,你为什么选择前者作为整个应用的数据库实例呢?在这里我想和大家着重分析一下这一点。我们来看一下SQLiteOpenHelper中的getReadableDatabase()方法:javaview plaincopy1. publicsynchronizedSQLiteDatabasegetReadableDatabase()2. if(mDatabase!=null&mDatabase.isOpen()3. /如果发现mDatabase不为空并且已经打开则直接返回4. returnmDatabase;5. 6. 7. if(mIsInitializing)8. /如果正在初始化则抛出异常9. thrownewIllegalStateException(getReadableDatabasecalledrecursively);10. 11. 12. /开始实例化数据库mDatabase13. 14. try15. /注意这里是调用了getWritableDatabase()方法16. returngetWritableDatabase();17. catch(SQLiteExceptione)18. if(mName=null)19. throwe;/Cantopenatempdatabaseread-only!20. Log.e(TAG,Couldntopen+mName+forwriting(willtryread-only):,e);21. 22. 23. /如果无法以可读写模式打开数据库则以只读方式打开24. 25. SQLiteDatabasedb=null;26. try27. mIsInitializing=true;28. Stringpath=mContext.getDatabasePath(mName).getPath();/获取数据库路径29. /以只读方式打开数据库30. db=SQLiteDatabase.openDatabase(path,mFactory,SQLiteDatabase.OPEN_READONLY);31. if(db.getVersion()!=mNewVersion)32. thrownewSQLiteException(Cantupgraderead-onlydatabasefromversion+db.getVersion()+to33. +mNewVersion+:+path);34. 35. 36. onOpen(db);37. Log.w(TAG,Opened+mName+inread-onlymode);38. mDatabase=db;/为mDatabase指定新打开的数据库39. returnmDatabase;/返回打开的数据库40. finally41. mIsInitializing=false;42. if(db!=null&db!=mDatabase)43. db.close();44. 45. 在getReadableDatabase()方法中,首先判断是否已存在数据库实例并且是打开状态,如果是,则直接返回该实例,否则试图获取一个可读写模式的数据库实例,如果遇到磁盘空间已满等情况获取失败的话,再以只读模式打开数据库,获取数据库实例并返回,然后为mDatabase赋值为最新打开的数据库实例。既然有可能调用到getWritableDatabase()方法,我们就要看一下了:javaview plaincopy1. publicsynchronizedSQLiteDatabasegetWritableDatabase()2. if(mDatabase!=null&mDatabase.isOpen()&!mDatabase.isReadOnly()3. /如果mDatabase不为空已打开并且不是只读模式则返回该实例4. returnmDatabase;5. 6. 7. if(mIsInitializing)8. thrownewIllegalStateException(getWritableDatabasecalledrecursively);9. 10. 11. /Ifwehavearead-onlydatabaseopen,someonecouldbeusingit12. /(thoughtheyshouldnt),whichwouldcausealocktobeheldon13. /thefile,andourattemptstoopenthedatabaseread-writewould14. /failwaitingforthefilelock.Topreventthat,weacquirethe15. /lockontheread-onlydatabase,whichshutsoutotherusers.16. 17. booleansuccess=false;18. SQLiteDatabasedb=null;19. /如果mDatabase不为空则加锁阻止其他的操作20. if(mDatabase!=null)21. mDatabase.lock();22. try23. mIsInitializing=true;24. if(mName=null)25. db=SQLiteDatabase.create(null);26. else27. /打开或创建数据库28. db=mContext.openOrCreateDatabase(mName,0,mFactory);29. 30. /获取数据库版本(如果刚创建的数据库,版本为0)31. intversion=db.getVersion();32. /比较版本(我们代码中的版本mNewVersion为1)33. if(version!=mNewVersion)34. db.beginTransaction();/开始事务35. try36. if(version=0)37. /执行我们的onCreate方法38. onCreate(db);39. else40. /如果我们应用升级了mNewVersion为2,而原版本为1则执行onUpgrade方法41. onUpgrade(db,version,mNewVersion);42. 43. db.setVersion(mNewVersion);/设置最新版本44. db.setTransactionSuccessful();/设置事务成功45. finally46. db.endTransaction();/结束事务47. 48. 49. 50. onOpen(db);51. success=true;52. returndb;/返回可读写模式的数据库实例53. finally54. mIsInitializing=false;55. if(success)56. /打开成功57. if(mDatabase!=null)58. /如果mDatabase有值则先关闭59. try60. mDatabase.close();61. catch(Exceptione)62. 63. mDatabase.unlock();/解锁64. 65. mDatabase=db;/赋值给mDatabase66. else67. /打开失败的情况:解锁、关闭68. if(mDatabase!=null)69. mDatabase.unlock();70. if(db!=null)71. db.close();72. 73. 74. 大家可以看到,几个关键步骤是,首先判断mDatabase如果不为空已打开并不是只读模式则直接返回,否则如果mDatabase不为空则加锁,然后开始打开或创建数据库,比较版本,根据版本号来调用相应的方法,为数据库设置新版本号,最后释放旧的不为空的mDatabase并解锁,把新打开的数据库实例赋予mDatabase,并返回最新实例。看完上面的过程之后,大家或许就清楚了许多,如果不是在遇到磁盘空间已满等情况,getReadableDatabase()一般都会返回和getWritableDatabase()一样的数据库实例,所以我们在DBManager构造方法中使用getWritableDatabase()获取整个应用所使用的数据库实例是可行的。当然如果你真的担心这种情况会发生,那么你可以先用getWritableDatabase()获取数据实例,如果遇到异常,再试图用getReadableDatabase()获取实例,当然这个时候你获取的实例只能读不能写了。最后,让我们看一下如何使用这些数据操作方法来显示数据,下面是MainActivity.java的布局文件和代码:htmlview plaincopy1. 2. 6. 11. 16. 21. 26. 31. 35. javaview plaincopy1. packagecom.scott.db;2. 3. importjava.util.ArrayList;4. importjava.util.HashMap;5. importjava.util.List;6. importjava.util.Map;7. 8. importandroid.app.Activity;9. importandroid.database.Cursor;10. importandroid.database.CursorWrapper;11. importandroid.os.Bundle;12. importandroid.view.View;13. importandroid.widget.ListView;14. importandroid.widget.SimpleAdapter;15. importandroid.widget.SimpleCursorAdapter;16. 17. 18. publicclassMainActivityext
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 服装架出租行业供需趋势及投资风险研究报告
- 海口硼铁合金项目可行性研究报告
- 2024-2030年中国医药批发行业市场全景监测及投资策略研究报告
- 2025年中国中型载货车未来趋势预测分析及投资规划研究建议报告
- 传媒行业市场深度分析及发展前景预测报告
- 2025年女式整皮羊皮手套行业深度研究分析报告
- 2025-2030年中国产销包装装潢行业深度研究分析报告
- 威县三顺哥商贸有限公司介绍企业发展分析报告模板
- 直管进水装置行业深度研究报告
- 2025年中国氚在线测量仪行业市场深度研究及投资规划建议报告
- 《道路建筑材料绪论》课件
- 医学遗传学教案-山东大学医学遗传学
- 2025年湖南现代物流职业技术学院高职单招职业技能测试近5年常考版参考题库含答案解析
- 第二十章手术减肥及体形塑造美容手术美容外科学概论讲解
- 2025年苏州卫生职业技术学院高职单招职业技能测试近5年常考版参考题库含答案解析
- 履带式剪叉高空作业平台安全操作规程
- 《水稻育秧技术新》课件
- 2024-2025年第一学期初中德育工作总结
- 围手术期手术患者护理要点
- 2025年大连长兴开发建设限公司工作人员公开招聘高频重点提升(共500题)附带答案详解
- 货物学 课件1.3货物的计量
评论
0/150
提交评论