【Android Developers Training】 26. 在SQL数

系统 1629 0

注:本文翻译自Google官方的Android Developers Training文档,译者技术一般,由于喜爱安卓而产生了翻译的念头,纯属个人兴趣爱好。

原文链接: http://developer.android.com/training/basics/data-storage/databases.html


在数据库中保存数据,对于重复性的或者结构化的数据来说是很理想的,比如:联系人信息。这节课我们假定你对SQL数据库有一个大致的了解,并且帮助你在Android上开始使用SQLite数据库。你在Android的数据库上需要使用的APIs在 android.database.sqlite 包中。

 

一). 定义一个架构(Schema)和契约(Contract)

SQL数据库的主要核心之一是:一个数据库是如何组织的正式声明。架构所对应的就是你用来创建数据库的SQL语句声明。你会发现创建一个辅助类( companion class ),即所谓的合同类(contract  class ),它通过一个系统的和自文档化的方式来显示地指定你的架构布局。

一个合同类是一个容器,它包含了那些定义了URI,表和列的名称的常量。合同类允许你在同一个包内所有类之间使用相同的名字。这样可以使你想要改变列名时只需在一个地方修改,就能影响到所有使用到它的代码。

一个良好的组织合同类的方式是:在类的根位置处,放置那些你的数据库的全局定义。然后为每一个表创建一个内部类,来枚举它的列。

Note:

通过实现基列( BaseColumns )接口,你的内部类可以继承一个主键字段,叫做:“ _ID ”。一些Android类,比如光标适配器( cursor adaptors )会期望它能够拥有这个。虽然这个不是必须的,但是它能够帮助你的数据库和Android更协同地工作。

例如,下例为一个简单的表定义了表名和列名:

      
        public
      
      
        final
      
      
        class
      
      
         FeedReaderContract {

    
      
      
        //
      
      
         To prevent someone from accidentally instantiating the contract class,

    
      
      
        //
      
      
         give it an empty constructor.
      
      
        public
      
      
         FeedReaderContract() {}



    
      
      
        /*
      
      
         Inner class that defines the table contents 
      
      
        */
      
      
        public
      
      
        static
      
      
        abstract
      
      
        class
      
       FeedEntry 
      
        implements
      
      
         BaseColumns {

        
      
      
        public
      
      
        static
      
      
        final
      
       String TABLE_NAME = "entry"
      
        ;

        
      
      
        public
      
      
        static
      
      
        final
      
       String COLUMN_NAME_ENTRY_ID = "entryid"
      
        ;

        
      
      
        public
      
      
        static
      
      
        final
      
       String COLUMN_NAME_TITLE = "title"
      
        ;

        
      
      
        public
      
      
        static
      
      
        final
      
       String COLUMN_NAME_SUBTITLE = "subtitle"
      
        ;

        ...

    }

}
      
    

 

 二). 使用SQL助手创建一个数据库

一旦你定义了你的数据库,你应该实现一些方法来创建和维护你的数据库及表。下例是一些标准的创建和删除数据库的声明:

      
        private
      
      
        static
      
      
        final
      
       String TEXT_TYPE = " TEXT"
      
        ;


      
      
        private
      
      
        static
      
      
        final
      
       String COMMA_SEP = ","
      
        ;


      
      
        private
      
      
        static
      
      
        final
      
       String SQL_CREATE_ENTRIES =

    "CREATE TABLE " + FeedEntry.TABLE_NAME + " (" +
      
        

    FeedEntry._ID 
      
      + " INTEGER PRIMARY KEY," +
      
        

    FeedEntry.COLUMN_NAME_ENTRY_ID 
      
      + TEXT_TYPE + COMMA_SEP +
      
        

    FeedEntry.COLUMN_NAME_TITLE 
      
      + TEXT_TYPE + COMMA_SEP +
      
        

    ... 
      
      
        //
      
      
         Any other options for the CREATE command
      
      

    " )"
      
        ;




      
      
        private
      
      
        static
      
      
        final
      
       String SQL_DELETE_ENTRIES =

    "DROP TABLE IF EXISTS " + FeedEntry.TABLE_NAME;
    

就好像在设备内存( internal storage )中所存储的文件一样,Android会将你的数据库存储在一个和应用有关联的私有磁盘空间中。你的数据将是安全的,因为默认情况下这些数据不会被其他应用访问到。

一个有用的APIs集合在 SQLiteOpenHelper 类中。当你使用这个类来获取你的数据库的引用时,系统会仅在需要时(不在应用启动时)执行一些可能需要消耗较长时间的操作,如:创建,更新数据库。所有你需要的是调用 getWritableDatabase() 或者 getReadableDatabase()

Note:

因为它们可能会消耗比较长的时间,所以请确保你在一个后台线程调用 getWritableDatabase() 或者 getReadableDatabase() ,比如: AsyncTask 或者 IntentService

要使用 SQLiteOpenHelper ,创建一个子类,覆写 onCreate() onUpgrade() onOpen() 回调函数。你可能还需要实现 onDowngrade() ,但这不是必须的。

例如,下面是一个 SQLiteOpenHelper 的实现,它使用了之前所列举的一些命令:

      
        public
      
      
        class
      
       FeedReaderDbHelper 
      
        extends
      
      
         SQLiteOpenHelper {

    
      
      
        //
      
      
         If you change the database schema, you must increment the database version.
      
      
        public
      
      
        static
      
      
        final
      
      
        int
      
       DATABASE_VERSION = 1
      
        ;

    
      
      
        public
      
      
        static
      
      
        final
      
       String DATABASE_NAME = "FeedReader.db"
      
        ;



    
      
      
        public
      
      
         FeedReaderDbHelper(Context context) {

        
      
      
        super
      
      (context, DATABASE_NAME, 
      
        null
      
      
        , DATABASE_VERSION);

    }

    
      
      
        public
      
      
        void
      
      
         onCreate(SQLiteDatabase db) {

        db.execSQL(SQL_CREATE_ENTRIES);

    }

    
      
      
        public
      
      
        void
      
       onUpgrade(SQLiteDatabase db, 
      
        int
      
       oldVersion, 
      
        int
      
      
         newVersion) {

        
      
      
        //
      
      
         This database is only a cache for online data, so its upgrade policy is

        
      
      
        //
      
      
         to simply to discard the data and start over
      
      
                db.execSQL(SQL_DELETE_ENTRIES);

        onCreate(db);

    }

    
      
      
        public
      
      
        void
      
       onDowngrade(SQLiteDatabase db, 
      
        int
      
       oldVersion, 
      
        int
      
      
         newVersion) {

        onUpgrade(db, oldVersion, newVersion);

    }

}
      
    

要访问你的数据库,实例化你的 SQLiteOpenHelper 子类:

      FeedReaderDbHelper mDbHelper = 
      
        new
      
       FeedReaderDbHelper(getContext());
    

 

三). 将信息添加到数据库中

可以将一个 ContentValues 对象传入 insert() 方法,来将数据添加到数据库中:

      
        //
      
      
         Gets the data repository in write mode
      
      

SQLiteDatabase db =
      
         mDbHelper.getWritableDatabase();




      
      
        //
      
      
         Create a new map of values, where column names are the keys
      
      

ContentValues values = 
      
        new
      
      
         ContentValues();

values.put(FeedEntry.COLUMN_NAME_ENTRY_ID, id);

values.put(FeedEntry.COLUMN_NAME_TITLE, title);

values.put(FeedEntry.COLUMN_NAME_CONTENT, content);




      
      
        //
      
      
         Insert the new row, returning the primary key value of the new row
      
      
        long
      
      
         newRowId;

newRowId 
      
      =
      
         db.insert(

         FeedEntry.TABLE_NAME,

         FeedEntry.COLUMN_NAME_NULLABLE,

         values);
      
    

insert() 方法的第一个参数就是表名。第二个参数提供了一个列名,当 ContentValues 为空时,框架会插入一个NULL。(如果你将这个参数设置为“ null ”,那么当输入时空时,框架不会添加一个新列)

 

四). 从数据库中读取数据

为了从数据库中读取数据,使用 query() 方法,传递给它你的选择标准和期望查找的列。这个方法结合了 insert() update() ,除了定义了你希望获取数据 (不是你希望插入的数据) 的列清单。查询的结果将会以一个 Cursor 对象返回。

      SQLiteDatabase db =
      
         mDbHelper.getReadableDatabase();




      
      
        //
      
      
         Define a projection that specifies which columns from the database


      
      
        //
      
      
         you will actually use after this query.
      
      

String[] projection =
      
         {

    FeedEntry._ID,

    FeedEntry.COLUMN_NAME_TITLE,

    FeedEntry.COLUMN_NAME_UPDATED,

    ...

    };




      
      
        //
      
      
         How you want the results sorted in the resulting Cursor
      
      

String sortOrder =
      
        

    FeedEntry.COLUMN_NAME_UPDATED 
      
      + " DESC"
      
        ;



Cursor c 
      
      =
      
         db.query(

    FeedEntry.TABLE_NAME,  
      
      
        //
      
      
         The table to query
      
      

    projection,                               
      
        //
      
      
         The columns to return
      
      

    selection,                                
      
        //
      
      
         The columns for the WHERE clause
      
      

    selectionArgs,                            
      
        //
      
      
         The values for the WHERE clause
      
      
        null
      
      ,                                     
      
        //
      
      
         don't group the rows
      
      
        null
      
      ,                                     
      
        //
      
      
         don't filter by row groups
      
      

    sortOrder                                 
      
        //
      
      
         The sort order
      
      

    );
    

为了查询 cursor中的一行,使用 Cursor 中的一个移动方法,这个方法你必须在开始读数据时一直调用。一般地,你应该从调用 moveToFirst() 开始,这样将读取位置放置到结果的第一个记录。对于每一行,你可以你可以读取某一列的值,通过调用 Cursor 的一个get方法,比如: getString() 或者 getLong() 。对于每个get方法,你必须传入你期望的列的索引号,你可以通过调用 getColumnIndex() 或者 getColumnIndexOrThrow() 来得到索引号。

      
        cursor.moveToFirst();


      
      
        long
      
       itemId =
      
         cursor.getLong(

    cursor.getColumnIndexOrThrow(FeedEntry._ID)

);
      
    

 

五). 从数据库中删除数据

为了从数据库中删除一行数据,你需要提供一个选择标准来指定一行。数据库的API提供了一个创建选择标准的机制来防止SQL注入攻击。这个机制将选择语句分为了选择命令段(selection clause)和选择参数。命令段指定了要寻找的列,并且允许你可以结合一些列测试。参数是要测试的值,它是和命令段相对应的。因为这个结果和通常的SQL语句声明处理起来不一样,所以能够方式SQL注入。

      
        //
      
      
         Define 'where' part of query.
      
      

String selection = FeedEntry.COLUMN_NAME_ENTRY_ID + " LIKE ?"
      
        ;


      
      
        //
      
      
         Specify arguments in placeholder order.
      
      

String[] selectionArgs =
      
         { String.valueOf(rowId) };


      
      
        //
      
      
         Issue SQL statement.
      
      

db.delete(table_name, selection, selectionArgs);
    

 

六). 更新一个数据库

当你需要修改一个数据库值的子集,可以使用 update() 方法。

更新表结合了 insert() 的内容语法和 delete() 的“ where ”语法。

      SQLiteDatabase db =
      
         mDbHelper.getReadableDatabase();




      
      
        //
      
      
         New value for one column
      
      

ContentValues values = 
      
        new
      
      
         ContentValues();

values.put(FeedEntry.COLUMN_NAME_TITLE, title);




      
      
        //
      
      
         Which row to update, based on the ID
      
      

String selection = FeedEntry.COLUMN_NAME_ENTRY_ID + " LIKE ?"
      
        ;

String[] selectionArgs 
      
      =
      
         { String.valueOf(rowId) };




      
      
        int
      
       count =
      
         db.update(

    FeedReaderDbHelper.FeedEntry.TABLE_NAME,

    values,

    selection,

    selectionArgs);
      
    

【Android Developers Training】 26. 在SQL数据库中保存数据


更多文章、技术交流、商务合作、联系博主

微信扫码或搜索:z360901061

微信扫一扫加我为好友

QQ号联系: 360901061

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描下面二维码支持博主2元、5元、10元、20元等您想捐的金额吧,狠狠点击下面给点支持吧,站长非常感激您!手机微信长按不能支付解决办法:请将微信支付二维码保存到相册,切换到微信,然后点击微信右上角扫一扫功能,选择支付二维码完成支付。

【本文对您有帮助就好】

您的支持是博主写作最大的动力,如果您喜欢我的文章,感觉我的文章对您有帮助,请用微信扫描上面二维码支持博主2元、5元、10元、自定义金额等您想捐的金额吧,站长会非常 感谢您的哦!!!

发表我的评论
最新评论 总共0条评论