数据库存储数据
https://developer.android.google.cn/training/basics/data-storage/databases.html
SQL 数据库的主要原则之一是架构:数据库如何组织的正式声明。 架构体现于用于创建数据库的 SQL 语句。它有助于创建伴随类,即契约类,其以一种系统性、自记录的方式明确指定您的架构布局。
契约类是用于定义 URI、表格和列名称的常数的容器。 契约类允许您跨同一软件包中的所有其他类使用相同的常数。 您可以在一个位置更改列名称并使其在您整个代码中传播。
一种良好的使用组织契约类的方法是将数据库中的全局性的定义放入类的根级别。 然后为枚举其列的每个表格创建内部类。
通过实现 BaseColumns 接口,内部类可继承名为 _ID 的主键字段,某些 Android 类(比如CursorAdapter)将需要内部类拥有该字段。 这并非必需项,但可帮助数据库与 Android 框架协调工作
新建一张表:
1 public final class FeedReaderContract { 2 // To prevent someone from accidentally instantiating the contract class, 3 // make the constructor private. 4 private FeedReaderContract() {} 5 6 /* Inner class that defines the table contents */ 7 public static class FeedEntry implements BaseColumns { 8 public static final String TABLE_NAME = "entry"; 9 public static final String COLUMN_NAME_TITLE = "title"; 10 public static final String COLUMN_NAME_SUBTITLE = "subtitle"; 11 } 12 }
建立表和删除表:
一旦你决定了数据库的结构,就该引用那些创建和维护数据库与表的方法了。下面是一种建立和删除表的常见代码:
1 private static final String SQL_CREATE_ENTRIES = 2 "CREATE TABLE " + FeedEntry.TABLE_NAME + " (" + 3 FeedEntry._ID + " INTEGER PRIMARY KEY," + 4 FeedEntry.COLUMN_NAME_TITLE + " TEXT," + 5 FeedEntry.COLUMN_NAME_SUBTITLE + " TEXT)"; 6 7 private static final String SQL_DELETE_ENTRIES = 8 "DROP TABLE IF EXISTS " + FeedEntry.TABLE_NAME;
数据库存放的数据默认情况下不开放给任何外部应用访问,相对安全。
默认的数据库建立的数据都为应用内私有,如果希望可以开放给别的APP,可以使用SQLiteOpenHelper的API getWritableDatabase() 和 getReadableDatabase().
处理过程较长,尽量放在后台进程中。
SQLiteOpenHelper使用方法:继承SQLiteOpenHelper类,覆盖 onCreate(), onUpgrade() 和 onOpen() 方法
1 public class FeedReaderDbHelper extends SQLiteOpenHelper { 2 // If you change the database schema, you must increment the database version. 3 public static final int DATABASE_VERSION = 1; 4 public static final String DATABASE_NAME = "FeedReader.db"; 5 6 public FeedReaderDbHelper(Context context) { 7 super(context, DATABASE_NAME, null, DATABASE_VERSION); 8 } 9 public void onCreate(SQLiteDatabase db) { 10 db.execSQL(SQL_CREATE_ENTRIES); 11 } 12 public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { 13 // This database is only a cache for online data, so its upgrade policy is 14 // to simply to discard the data and start over 15 db.execSQL(SQL_DELETE_ENTRIES); 16 onCreate(db); 17 } 18 public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) { 19 onUpgrade(db, oldVersion, newVersion); 20 } 21 }
实例化父类:
1 FeedReaderDbHelper mDbHelper = new FeedReaderDbHelper(getContext())
写入数据:
在insert() 方法中传入一个 ContentValues对象
1 // Gets the data repository in write mode 2 SQLiteDatabase db = mDbHelper.getWritableDatabase(); 3 4 // Create a new map of values, where column names are the keys 5 ContentValues values = new ContentValues(); 6 values.put(FeedEntry.COLUMN_NAME_TITLE, title); 7 values.put(FeedEntry.COLUMN_NAME_SUBTITLE, subtitle); 8 9 // Insert the new row, returning the primary key value of the new row 10 long newRowId = db.insert(FeedEntry.TABLE_NAME, null, values);
传入的第一个参数是表名,第二个参数为如果values为空时ContentValues将要进行的操作。如果指明了列名,则会在此列中插入一行,然后设置整列为空。如记为null则不做任何操作。
读取数据:
使用query() 方法,传入筛选条件和目标列。查询结果返回为一个Cursor对象。
1 SQLiteDatabase db = mDbHelper.getReadableDatabase(); 2 3 // Define a projection that specifies which columns from the database 4 // you will actually use after this query. 5 String[] projection = { 6 FeedEntry._ID, 7 FeedEntry.COLUMN_NAME_TITLE, 8 FeedEntry.COLUMN_NAME_SUBTITLE 9 }; 10 11 // Filter results WHERE "title" = 'My Title' 12 String selection = FeedEntry.COLUMN_NAME_TITLE + " = ?"; 13 String[] selectionArgs = { "My Title" }; 14 15 // How you want the results sorted in the resulting Cursor 16 String sortOrder = 17 FeedEntry.COLUMN_NAME_SUBTITLE + " DESC"; 18 19 Cursor cursor = db.query( 20 FeedEntry.TABLE_NAME, // The table to query 21 projection, // The columns to return 22 selection, // The columns for the WHERE clause 23 selectionArgs, // The values for the WHERE clause 24 null, // don't group the rows 25 null, // don't filter by row groups 26 sortOrder // The sort order 27 );
选中cursor中的一行,在你开始读取值之前你总要先使用Cursor的移动方法。既然cursor的起始位置为-1,先调用 moveToNext() 把“read position”放在结果中的第一个入口,然后不论cursor是否已经把最后的入口传递给结果列都会返回。对于每一行来说,你可以使用Cursor的get方法来读取每一列的值,比如 getString()或者 getLong() 。对于每一种get方法,你必须使用 getColumnIndex() 或者 getColumnIndexOrThrow() 方法可以获取的你想查询那列的索引位置传递过去。当你重复查询完结果后,调用 cursor的 close() 方法释放它的资源。
1 List itemIds = new ArrayList<>(); 2 while(cursor.moveToNext()) { 3 long itemId = cursor.getLong( 4 cursor.getColumnIndexOrThrow(FeedEntry._ID)); 5 itemIds.add(itemId); 6 } 7 cursor.close();
删除数据:
想要删除表里的数据,你必须提供能明确指定行的筛选标准。数据库API提供了一种建立筛选标准的机制来防止SQL注入攻击。这种机制会把筛选标准分割成子句或者参数。子句定义了你要查询的列,同时也允许你合并列的测试。 参数是根据捆绑到子句的项进行测试的值。由于结果并未按照与常规 SQL 语句相同的方式进行处理,它不受 SQL 注入的影响。
1 // Define 'where' part of query. 2 String selection = FeedEntry.COLUMN_NAME_TITLE + " LIKE ?"; 3 // Specify arguments in placeholder order. 4 String[] selectionArgs = { "MyTitle" }; 5 // Issue SQL statement. 6 db.delete(FeedEntry.TABLE_NAME, selection, selectionArgs);
修改数据库:
当您需要修改数据库值的子集时,请使用 update() 方法。
更新表可将 insert() 的内容值语法与 delete() 的 where 语法相结合。
1 SQLiteDatabase db = mDbHelper.getReadableDatabase(); 2 3 // New value for one column 4 ContentValues values = new ContentValues(); 5 values.put(FeedEntry.COLUMN_NAME_TITLE, title); 6 7 // Which row to update, based on the title 8 String selection = FeedEntry.COLUMN_NAME_TITLE + " LIKE ?"; 9 String[] selectionArgs = { "MyTitle" }; 10 11 int count = db.update( 12 FeedReaderDbHelper.FeedEntry.TABLE_NAME, 13 values, 14 selection, 15 selectionArgs);

浙公网安备 33010602011771号