原文出自:author:conowen
* E-mail:conowen@hotmail.com
* http://blog.csdn.net/conowen
1、sqliteOpenHelper介绍
通过上篇博文,http://www.jb51.cc/article/p-hzhgfvjf-gp.html,了解了sqlite数据库的相关操作方法,但是一般在实际开发中,为了更加方便地管理、维护、升级数据库,需要通过继承sqliteOpenHelper类来管理sqlite数据库。
关于sqliteOpenHelper的官方说明如下:
A helper class to manage database creation and version management.
You create a subclass implementing onCreate(SQLiteDatabase)
,onUpgrade(SQLiteDatabase,int,int)
and optionallyonOpen(SQLiteDatabase)
,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.
This class makes it easy for ContentProvider
implementations to defer opening and upgrading the database until first use,to avoid blocking application startup with long-running database upgrades.
For an example,see the NotePadProvider class in the NotePad sample application,in thesamples/ directory of the SDK.
简单翻译:sqliteOpenHelper可以创建数据库,和管理数据库的版本。
在继承sqliteOpenHelper的类(extends
sqliteOpenHelper
)里面,通过复写
onCreate(SQLiteDatabase)
,int) 和onOpen(SQLiteDatabase)
(可选)来操作数据库。
创建一个新的class如下所示,onCreate(sqliteDatabase db)和onUpgrade(sqliteDatabase db,int oldVersion,int newVersion)方法会被自动添加。
- /*
- *@author:conowen
- *@date:12.2.29
- */
- packagecom.conowen.sqlite;
- importandroid.content.Context;
- importandroid.database.sqlite.sqliteDatabase;
- importandroid.database.sqlite.sqliteDatabase.CursorFactory;
- importandroid.database.sqlite.sqliteOpenHelper;
- publicclassDbHelperextendssqliteOpenHelper{
- publicDbHelper(Contextcontext,Stringname,CursorFactoryfactory,
- intversion){
- super(context,name,factory,version);
- //TODOAuto-generatedconstructorstub
- }
- @Override
- publicvoidonCreate(sqliteDatabasedb){
- //TODOAuto-generatedmethodstub
- }
- @Override
- publicvoidonUpgrade(sqliteDatabasedb,intoldVersion,intnewVersion){
- //TODOAuto-generatedmethodstub
- }
- }
- /*
- *@author:conowen
- *@date:12.2.29
- */
- packagecom.conowen.sqlite;
- importandroid.content.Context;
- importandroid.database.sqlite.sqliteDatabase;
- importandroid.database.sqlite.sqliteDatabase.CursorFactory;
- importandroid.database.sqlite.sqliteOpenHelper;
- publicclassDbHelperextendssqliteOpenHelper{
- publicDbHelper(Contextcontext,
- intversion){
- super(context,version);
- //TODOAuto-generatedconstructorstub
- }
- @Override
- publicvoidonCreate(sqliteDatabasedb){
- //TODOAuto-generatedmethodstub
- }
- @Override
- publicvoidonUpgrade(sqliteDatabasedb,intnewVersion){
- //TODOAuto-generatedmethodstub
- }
- }
方法详解
- publicsqliteOpenHelper(Contextcontext,intversion)
- publicsqliteOpenHelper(Contextcontext,intversion)
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 ofgetWritableDatabase()
orgetReadableDatabase()
is called.
Parameters
context | to use to open or create the database | @H_502_630@name | of the database file,or null for an in-memory database | @H_502_630@factory | to use for creating cursor objects,or null for the default | @H_502_630@version | number of the database (starting at 1); if the database is older,onDowngrade(SQLiteDatabase,int) will be used to downgrade the database |
---|
参数简述:
name————表示数据库文件名(不包括文件路径),sqliteOpenHelper类会根据这个文件名来创建数据库文件。
version————表示数据库的版本号。如果当前传入的数据库版本号比上一次创建的版本高,sqliteOpenHelper就会调用onUpgrade()方法。
- publicDbHelper(Contextcontext,
- intversion){
- super(context,version);
- //TODOAuto-generatedconstructorstub
- }
- publicDbHelper(Contextcontext,version);
- //TODOAuto-generatedconstructorstub
- }
以上是sqliteOpenHelper 的构造函数,当数据库不存在时, 就会创建数据库,然后打开数据库(过程已经被封装起来了),再调用onCreate (sqliteDatabase db)方法来执行创建表之类的操作。当数据库存在时,sqliteOpenHelper 就不会调用onCreate (sqliteDatabase db)方法了,它会检测版本号,若传入的版本号高于当前的,就会执行onUpgrade()方法来更新数据库和版本号。
3.1、onCreate方法
- publicabstractvoidonCreate(sqliteDatabasedb)<spanclass="normal"></span>
- publicabstractvoidonCreate(sqliteDatabasedb)<spanclass="normal"></span>
- publicabstractvoidonCreate(sqliteDatabasedb)<spanclass="normal"></span>
- publicabstractvoidonCreate(sqliteDatabasedb)<spanclass="normal"></span>
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.
Parameters
db | The database. |
---|
3.2、onUpgrade方法
- publicabstractvoidonUpgrade(sqliteDatabasedb,intnewVersion)
- publicabstractvoidonUpgrade(sqliteDatabasedb,intnewVersion)
- publicabstractvoidonUpgrade(sqliteDatabasedb,intnewVersion)
- publicabstractvoidonUpgrade(sqliteDatabasedb,intnewVersion)
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.
The sqlite ALTER TABLE documentation can be found here. 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.
Parameters
db | The database. | @H_502_630@oldVersion | The old database version. | @H_502_630@newVersion | The new database version. |
---|
更新数据库,包括删除表,添加表等各种操作。若版本是第一版,也就是刚刚建立数据库,onUpgrade()方法里面就不用写东西,因为第一版数据库何来更新之说,以后发布的版本,数据库更新的话,可以在onUpgrade()方法添加各种更新的操作。
4、注意事项
getWritableDatabase() 方法————以读写方式打开数据库,如果数据库所在磁盘空间满了,而使用的又是getWritableDatabase() 方法就会出错。
因为此时数据库就只能读而不能写,
getReadableDatabase()方法————则是先以读写方式打开数据库,如果数据库的磁盘空间满了,就会打开失败,但是当打开失败后会继续尝试以只读
方式打开数据库。而不会报错
=========================================================================================================
下面演示一个以sqlite的数据库为adapter的listview例子(也可以当做通讯录小工具)
效果图如下
- /*主activity
- *@author:conowen
- *@date:12.3.1
- */
- packagecom.conowen.sqlite;
- importandroid.app.Activity;
- importandroid.content.ContentValues;
- importandroid.database.Cursor;
- importandroid.database.sqlite.sqliteDatabase;
- importandroid.os.Bundle;
- importandroid.view.View;
- importandroid.view.View.OnClickListener;
- importandroid.widget.Button;
- importandroid.widget.EditText;
- importandroid.widget.ListAdapter;
- importandroid.widget.ListView;
- importandroid.widget.SimpleCursorAdapter;
- importandroid.widget.Toast;
- publicclasssqliteActivityextendsActivity{
- sqliteDatabasesqldb;
- publicStringDB_NAME="sql.db";
- publicStringDB_TABLE="num";
- publicintDB_VERSION=1;
- finalDbHelperhelper=newDbHelper(this,DB_NAME,null,DB_VERSION);
- //DbHelper类在DbHelper.java文件里面创建的
- /**Calledwhentheactivityisfirstcreated.*/
- @Override
- publicvoidonCreate(BundlesavedInstanceState){
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
- sqldb=helper.getWritableDatabase();
- //通过helper的getWritableDatabase()得到sqliteOpenHelper所创建的数据库
- Buttoninsert=(Button)findViewById(R.id.insert);
- Buttondelete=(Button)findViewById(R.id.delete);
- Buttonupdate=(Button)findViewById(R.id.update);
- Buttonquery=(Button)findViewById(R.id.query);
- finalContentValuescv=newContentValues();
- //ContentValues是“添加”和“更新”两个操作的数据载体
- updatelistview();//更新listview
- //添加insert
- insert.setOnClickListener(newOnClickListener(){
- @Override
- publicvoidonClick(Viewv){
- //TODOAuto-generatedmethodstub
- EditTextet_name=(EditText)findViewById(R.id.name);
- EditTextet_phone=(EditText)findViewById(R.id.phone);
- cv.put("name",et_name.getText().toString());
- cv.put("phone",et_phone.getText().toString());
- //name和phone为列名
- longres=sqldb.insert("addressbook",cv);//插入数据
- if(res==-1){
- Toast.makeText(sqliteActivity.this,"添加失败",
- Toast.LENGTH_SHORT).show();
- }else{
- Toast.makeText(sqliteActivity.this,"添加成功",
- Toast.LENGTH_SHORT).show();
- }
- updatelistview();//更新listview
- }
- });
- //删除
- delete.setOnClickListener(newOnClickListener(){
- @Override
- publicvoidonClick(Viewv){
- //TODOAuto-generatedmethodstub
- intres=sqldb.delete("addressbook","name='大钟'",null);
- //删除列名name,行名为“大钟”的,这一行的所有数据,null表示这一行的所有数据
- //若第二个参数为null,则删除表中所有列对应的所有行的数据,也就是把table清空了。
- //name='大钟',大钟要单引号的
- //返回值为删除的行数
- if(res==0){
- Toast.makeText(sqliteActivity.this,"删除失败",
- Toast.LENGTH_SHORT).show();
- }else{
- Toast.makeText(sqliteActivity.this,"成删除了"+res+"行的数据",
- Toast.LENGTH_SHORT).show();
- }
- updatelistview();//更新listview
- }
- });
- //更改
- update.setOnClickListener(newOnClickListener(){
- @Override
- publicvoidonClick(Viewv){
- //TODOAuto-generatedmethodstub
- cv.put("name","大钟");
- cv.put("phone","1361234567");
- intres=sqldb.update("addressbook",cv,"name='张三'",null);
- //把name=张三所在行的数据,全部更新为ContentValues所对应的数据
- //返回时为成功更新的行数
- Toast.makeText(sqliteActivity.this,"成功更新了"+res+"行的数据",
- Toast.LENGTH_SHORT).show();
- updatelistview();//更新listview
- }
- });
- //查询
- query.setOnClickListener(newOnClickListener(){
- @Override
- publicvoidonClick(Viewv){
- //TODOAuto-generatedmethodstub
- Cursorcr=sqldb.query("addressbook",
- null,null);
- //返回名为addressbook的表的所有数据
- Toast.makeText(sqliteActivity.this,
- "一共有"+cr.getCount()+"条记录",Toast.LENGTH_SHORT)
- .show();
- updatelistview();//更新listview
- }
- });
- }
- //更新listview
- publicvoidupdatelistview(){
- ListViewlv=(ListView)findViewById(R.id.lv);
- finalCursorcr=sqldb.query("addressbook",
- null,null);
- String[]ColumnNames=cr.getColumnNames();
- //ColumnNames为数据库的表的列名,getColumnNames()为得到指定table的所有列名
- ListAdapteradapter=newSimpleCursorAdapter(this,R.layout.layout,
- cr,ColumnNames,newint[]{R.id.tv1,R.id.tv2,R.id.tv3});
- //layout为listView的布局文件,包括三个TextView,用来显示三个列名所对应的值
- //ColumnNames为数据库的表的列名
- //最后一个参数是int[]类型的,为view类型的id,用来显示ColumnNames列名所对应的值。view的类型为TextView
- lv.setAdapter(adapter);
- }
- }
- /*主activity
- *@author:conowen
- *@date:12.3.1
- */
- packagecom.conowen.sqlite;
- importandroid.app.Activity;
- importandroid.content.ContentValues;
- importandroid.database.Cursor;
- importandroid.database.sqlite.sqliteDatabase;
- importandroid.os.Bundle;
- importandroid.view.View;
- importandroid.view.View.OnClickListener;
- importandroid.widget.Button;
- importandroid.widget.EditText;
- importandroid.widget.ListAdapter;
- importandroid.widget.ListView;
- importandroid.widget.SimpleCursorAdapter;
- importandroid.widget.Toast;
- publicclasssqliteActivityextendsActivity{
- sqliteDatabasesqldb;
- publicStringDB_NAME="sql.db";
- publicStringDB_TABLE="num";
- publicintDB_VERSION=1;
- finalDbHelperhelper=newDbHelper(this,DB_VERSION);
- //DbHelper类在DbHelper.java文件里面创建的
- /**Calledwhentheactivityisfirstcreated.*/
- @Override
- publicvoidonCreate(BundlesavedInstanceState){
- super.onCreate(savedInstanceState);
- setContentView(R.layout.main);
- sqldb=helper.getWritableDatabase();
- //通过helper的getWritableDatabase()得到sqliteOpenHelper所创建的数据库
- Buttoninsert=(Button)findViewById(R.id.insert);
- Buttondelete=(Button)findViewById(R.id.delete);
- Buttonupdate=(Button)findViewById(R.id.update);
- Buttonquery=(Button)findViewById(R.id.query);
- finalContentValuescv=newContentValues();
- //ContentValues是“添加”和“更新”两个操作的数据载体
- updatelistview();//更新listview
- //添加insert
- insert.setOnClickListener(newOnClickListener(){
- @Override
- publicvoidonClick(Viewv){
- //TODOAuto-generatedmethodstub
- EditTextet_name=(EditText)findViewById(R.id.name);
- EditTextet_phone=(EditText)findViewById(R.id.phone);
- cv.put("name",et_name.getText().toString());
- cv.put("phone",et_phone.getText().toString());
- //name和phone为列名
- longres=sqldb.insert("addressbook",cv);//插入数据
- if(res==-1){
- Toast.makeText(sqliteActivity.this,
- Toast.LENGTH_SHORT).show();
- }else{
- Toast.makeText(sqliteActivity.this,
- Toast.LENGTH_SHORT).show();
- }
- updatelistview();//更新listview
- }
- });
- //删除
- delete.setOnClickListener(newOnClickListener(){
- @Override
- publicvoidonClick(Viewv){
- //TODOAuto-generatedmethodstub
- intres=sqldb.delete("addressbook",null);
- //删除列名name,行名为“大钟”的,这一行的所有数据,null表示这一行的所有数据
- //若第二个参数为null,则删除表中所有列对应的所有行的数据,也就是把table清空了。
- //name='大钟',大钟要单引号的
- //返回值为删除的行数
- if(res==0){
- Toast.makeText(sqliteActivity.this,
- Toast.LENGTH_SHORT).show();
- }else{
- Toast.makeText(sqliteActivity.this,
- Toast.LENGTH_SHORT).show();
- }
- updatelistview();//更新listview
- }
- });
- //更改
- update.setOnClickListener(newOnClickListener(){
- @Override
- publicvoidonClick(Viewv){
- //TODOAuto-generatedmethodstub
- cv.put("name","大钟");
- cv.put("phone","1361234567");
- intres=sqldb.update("addressbook",null);
- //把name=张三所在行的数据,全部更新为ContentValues所对应的数据
- //返回时为成功更新的行数
- Toast.makeText(sqliteActivity.this,
- Toast.LENGTH_SHORT).show();
- updatelistview();//更新listview
- }
- });
- //查询
- query.setOnClickListener(newOnClickListener(){
- @Override
- publicvoidonClick(Viewv){
- //TODOAuto-generatedmethodstub
- Cursorcr=sqldb.query("addressbook",
- null,null);
- //返回名为addressbook的表的所有数据
- Toast.makeText(sqliteActivity.this,
- "一共有"+cr.getCount()+"条记录",Toast.LENGTH_SHORT)
- .show();
- updatelistview();//更新listview
- }
- });
- }
- //更新listview
- publicvoidupdatelistview(){
- ListViewlv=(ListView)findViewById(R.id.lv);
- finalCursorcr=sqldb.query("addressbook",
- null,null);
- String[]ColumnNames=cr.getColumnNames();
- //ColumnNames为数据库的表的列名,getColumnNames()为得到指定table的所有列名
- ListAdapteradapter=newSimpleCursorAdapter(this,
- cr,newint[]{R.id.tv1,R.id.tv3});
- //layout为listView的布局文件,包括三个TextView,用来显示三个列名所对应的值
- //ColumnNames为数据库的表的列名
- //最后一个参数是int[]类型的,为view类型的id,用来显示ColumnNames列名所对应的值。view的类型为TextView
- lv.setAdapter(adapter);
- }
- }
- /*sqliteOpenHelper类
- *@author:conowen
- *@date:12.3.1
- */
- packagecom.conowen.sqlite;
- importandroid.content.Context;
- importandroid.database.sqlite.sqliteDatabase;
- importandroid.database.sqlite.sqliteDatabase.CursorFactory;
- importandroid.database.sqlite.sqliteOpenHelper;
- publicclassDbHelperextendssqliteOpenHelper{
- publicDbHelper(Contextcontext,
- intversion){
- super(context,version);
- //TODOAuto-generatedconstructorstub
- }
- @Override
- publicvoidonCreate(sqliteDatabasedb){
- //TODOAuto-generatedmethodstub
- Stringsql="CREATETABLEaddressbook(_idINTEGERPRIMARYKEY,nameVARCHAR,phoneVARCHAR)";
- db.execsql(sql);
- }
- @Override
- publicvoidonUpgrade(sqliteDatabasedb,intnewVersion){
- //TODOAuto-generatedmethodstub
- }
- }
- /*sqliteOpenHelper类
- *@author:conowen
- *@date:12.3.1
- */
- packagecom.conowen.sqlite;
- importandroid.content.Context;
- importandroid.database.sqlite.sqliteDatabase;
- importandroid.database.sqlite.sqliteDatabase.CursorFactory;
- importandroid.database.sqlite.sqliteOpenHelper;
- publicclassDbHelperextendssqliteOpenHelper{
- publicDbHelper(Contextcontext,
- intversion){
- super(context,version);
- //TODOAuto-generatedconstructorstub
- }
- @Override
- publicvoidonCreate(sqliteDatabasedb){
- //TODOAuto-generatedmethodstub
- Stringsql="CREATETABLEaddressbook(_idINTEGERPRIMARYKEY,phoneVARCHAR)";
- db.execsql(sql);
- }
- @Override
- publicvoidonUpgrade(sqliteDatabasedb,intnewVersion){
- //TODOAuto-generatedmethodstub
- }
- }
main.xml
- <?xmlversion="1.0"encoding="utf-8"?>
- <LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:orientation="vertical">
- <EditText
- android:id="@+id/name"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"/>
- <EditText
- android:id="@+id/phone"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"/>
- <LinearLayout
- android:id="@+id/linearLayout1"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content">
- <Button
- android:id="@+id/insert"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="增加"/>
- <Button
- android:id="@+id/delete"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="删除"/>
- <Button
- android:id="@+id/update"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="更改"/>
- <Button
- android:id="@+id/query"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="查询"/>
- </LinearLayout>
- <ListView
- android:id="@+id/lv"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content">
- </ListView>
- </LinearLayout>
- <?xmlversion="1.0"encoding="utf-8"?>
- <LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:orientation="vertical">
- <EditText
- android:id="@+id/name"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"/>
- <EditText
- android:id="@+id/phone"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"/>
- <LinearLayout
- android:id="@+id/linearLayout1"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content">
- <Button
- android:id="@+id/insert"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="增加"/>
- <Button
- android:id="@+id/delete"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="删除"/>
- <Button
- android:id="@+id/update"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="更改"/>
- <Button
- android:id="@+id/query"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="查询"/>
- </LinearLayout>
- <ListView
- android:id="@+id/lv"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content">
- </ListView>
- </LinearLayout>
ListView的布局文件layout.xml
- <?xmlversion="1.0"encoding="utf-8"?>
- <LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:orientation="horizontal">
- <TextView
- android:id="@+id/tv1"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textSize="20sp"
- android:width="50px"/>
- <TextView
- android:id="@+id/tv2"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textSize="20sp"
- android:width="50px"
- />
- <TextView
- android:id="@+id/tv3"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textSize="20sp"
- android:width="150px"/>
- </LinearLayout>
- <?xmlversion="1.0"encoding="utf-8"?>
- <LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_height="fill_parent"
- android:orientation="horizontal">
- <TextView
- android:id="@+id/tv1"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textSize="20sp"
- android:width="50px"/>
- <TextView
- android:id="@+id/tv2"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textSize="20sp"
- android:width="50px"
- />
- <TextView
- android:id="@+id/tv3"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:textSize="20sp"
- android:width="150px"/>
- </LinearLayout>