1.定义架构和契约
SQL 数据库的主要原则之一是架构:数据库如何组织的正式声明。 架构体现于您用于创建数据库的 SQL 语句。您会发现它有助于创建伴随类,即契约 类,其以一种系统性、自记录的方式明确指定您的架构布局。
契约类是用于定义 URI、表格和列名称的常数的容器。 契约类允许您跨同一软件包中的所有其他类使用相同的常数。 您可以在一个位置更改列名称并使其在您整个代码中传播。
组织契约类的一种良好方法是将对于您的整个数据库而言是全局性的定义放入类的根级别。 然后为枚举其列的每个表格创建内部类。
注意:通过实现 BaseColumns 接口,您的内部类可继承调用的主键字段_ID ,某些 Android 类(比如光标适配器)将需要内部类拥有该字段。 这并非必需项,但可帮助您的数据库与 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";
...
}
}
2.使用 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;
就像在设备的内部存储中保存文件那样,Android 将您的数据库保存在私人磁盘空间,即关联的应用。 数据是安全的,因为在默认情况下,其他应用无法访问此区域。
SQLiteOpenHelper 类中有一组有用的 API。当您使用此类获取对您数据库的引用时,系统将只在需要之时而不是 应用启动过程中执行可能长期运行的操作:创建和更新数据库。 您只需调用 getWritableDatabase() 或 getReadableDatabase()。
注意:由于它们可能长期运行,因此请确保您在后台线程中调用 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 移动方法之一,您必须在开始读取值之前始终调用这些方法。 一般情况下,您应通过调用 moveToFirst() 开始,其将“读取位置”置于结果中的第一个条目中。 对于每一行,您可以通过调用 Cursor 获取方法之一读取列的值,比如 getString() 或 getLong()。对于每种获取方法,您必须传递所需列的索引位置,您可以通过调用 getColumnIndex() 或 getColumnIndexOrThrow() 获取。例如:
cursor.moveToFirst();
long itemId = cursor.getLong(
cursor.getColumnIndexOrThrow(FeedEntry._ID)
);
3.从数据库删除信息
要从表格中删除行,您需要提供识别行的选择条件。 数据库 API 提供了一种机制,用于创建防止 SQL 注入的选择条件。 该机制将选择规范划分为选择子句和选择参数。 该子句定义要查看的列,还允许您合并列测试。 参数是根据捆绑到子句的项进行测试的值。由于结果并未按照与常规 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);
4.更新数据库
当您需要修改数据库值的子集时,请使用 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);
5.缺点:没有用于SQLite的网络服务器、只能通过网络共享
只能提供数据库级别的锁定;没有用户账户概念(也就是说没有类似Mysql中的管理员、普通账户等),而是根据文件系统确定所有数据库的权限。
在安卓中每一个程序的数据库都是唯一的,默认是互不干扰的。
6.SQLiteOpenHelper
SQLiteOpenHelper是SQliteDatabase的帮助类,用于管理数据库的创建和版本的更新,一般都是建立一个类继承它,并且重写oncreate()和onUpgrade()方法
Oncreate(SQLiteDatabase db)//创建数据库时候调用
OnUpgrade(SQLiteDatabase db)版本更新时候调用
GetReadableDatabase()//创建或打开一个只读数据库
getwriteableDatabase()//创建或打开一个可读写数据库
7.数据类型
SQL ite支持的类型:
NULL(空值),
INTEGER(整形值)、
REAL(浮点值)、
TEXT(字符串值)、
BLOB(二进制对象)
下面是一个例子
Config
package com.example.gpwner.myapplication;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
public class Config {
public static String DATABASE_NAME="neu.db";
public static String TABLE_NAME="student";
public static String COLUMN_NAME="name";
public static String COLUMN_AGE="age";
private static final String TEXT_TYPE = " TEXT";
private static final String COMMA_SEP = ",";
//创建表的语句
public static final String SQL_CREATE_ENTRIES =
"CREATE TABLE " + TABLE_NAME + " (" +
COLUMN_NAME + TEXT_TYPE + COMMA_SEP +
COLUMN_AGE + TEXT_TYPE + " )";
public static final String SQL_DELETE_ENTRIES =
"DROP TABLE IF EXISTS " + TABLE_NAME;
}
DBUtil
package com.example.gpwner.myapplication;
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import static com.example.gpwner.myapplication.Config.SQL_DELETE_ENTRIES;
/**
* Created by Gpwner on 2016/11/5.
*/
public class DBUtil extends SQLiteOpenHelper {
/**
* 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 of {@link #getWritableDatabase} or
* {@link #getReadableDatabase} is called.
* @param context to use to open or create the database
*
*/
public DBUtil(Context context) {
super(context, Config.DATABASE_NAME, null, 1);
}
/**
* 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.
*
* @param db The database.
*/
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL(Config.SQL_CREATE_ENTRIES);
}
/**
* 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.
* <p>
* <p>
* The SQLite ALTER TABLE documentation can be found
* <a href="http://sqlite.org/lang_altertable.html">here</a>. 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.
* </p><p>
* This method executes within a transaction. If an exception is thrown, all changes
* will automatically be rolled back.
* </p>
*
* @param db The database.
* @param oldVersion The old database version.
* @param newVersion The new database version.
*/
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL(SQL_DELETE_ENTRIES);
onCreate(db);
}
}
Main2Activity
package com.example.gpwner.myapplication;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.Button;
public class Main2Activity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
DBUtil dbUtil=new DBUtil(this);
SQLiteDatabase db = dbUtil.getReadableDatabase();
// Define a projection that specifies which columns from the database
// you will actually use after this query.
String[] projection = {
Config.COLUMN_NAME,
Config.COLUMN_AGE
};
// How you want the results sorted in the resulting Cursor
Cursor c = db.query(
Config.TABLE_NAME, // The table to query
projection, // The columns to return
null, // The columns for the WHERE clause
null, // The values for the WHERE clause
null, // don't group the rows
null, // don't filter by row groups
null // The sort order
);
Button button= (Button) findViewById(R.id.button);
c.moveToFirst();
String name=c.getString(c.getColumnIndex(Config.COLUMN_NAME) )+c.getString(c.getColumnIndex(Config.COLUMN_AGE)) ;
button.setText(name);
}
}
MainActivity
package com.example.gpwner.myapplication;
import android.content.ContentValues;
import android.content.Intent;
import android.database.sqlite.SQLiteDatabase;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
DBUtil dbUtil=new DBUtil(this);
SQLiteDatabase database=dbUtil.getWritableDatabase();
ContentValues values=new ContentValues();
values.put(Config.COLUMN_NAME,"tom");
values.put(Config.COLUMN_AGE,"18");
long row=database.insert(Config.TABLE_NAME,null,values);
if (row==-1){
Toast.makeText(MainActivity.this,"出错了",Toast.LENGTH_SHORT).show();
}
else{
Toast.makeText(MainActivity.this,"写入数据库成功",Toast.LENGTH_SHORT).show();
startActivity(new Intent(MainActivity.this,Main2Activity.class));
}
}
}