之前学到SQLite的使用,我们注意到在进行增删改查的操作时,每次都要通过书写String类型的SQL语句才能完成操作,通常在这里我们最容易出错,而且出现错误极难找出,原因是SQL语句的对错eclipse是检查不出来的,而且运行的时候它又把错误位置报在别处,所以SQL语句的问题必然困扰很多人。
事实上,SQLiteDataBase类中封装了关于增删改查的方法,可以不写SQL语句来完成对数据库的操作。
——insert(String table, String nullColumnHack, ContentValues values)
第一个参数代表插入数据的表名
第二个参数代表强行插入null值的数据列的列名,当values参数为null或者不包含任何key-value时该参数有效。一般该参数的列名不应该是主键列名,也不应该是非空列的列名,否则会引发异常。通常不需要在这个参数上费心思,填null就可以了。
第三个参数代表一行记录的数据。不管该参数是否包含数据,执行insert方法总会添加一条记录。如果该参数为空,会添加一条除主键之外其他字段值都为null的记录。需要借助ContentValues类,该类通过键值对形式存储数据,使用格式如下
ContentValuescontentValues = new ContentValues();
contentValues.put("username",name);
contentValues.put("password",pass);
db.insert(table,null, contentValues);
——updateString table, ContentValues values, String whereClause, String[] whereArgs)
第一个参数是更新数据的表名
第二个参数项更新的数据
第三个参数是满足where子句的记录将会被更新,如果没有该参数将更新所有数据
第四个参数为where子句传入参数
——delete(String table, String whereClause, String[] whereArgs)
第一个参数是删除数据的表名
第二个参数是满足where子句的记录将会被删除
第三个参数为where子句传入参数
——Cursorquery(boolean distinct,String table,String[] columns,StringwhereClause,String[] selectionArgs,String groupBy,String having,StringorderBy,String limit)
distinct:指定是否去除重复记录
table:执行查询数据的表名
columns:要查询出来的列名,相当于select关键字后面的部分
whereClause:查询条件子句,相当于where关键字后面的部分,在条件子句中允许使用占位符问号(?)
selectionArgs:为whereClause中占位符传入参数值。值在数组中的位置与占位符在语句中的位置必须一致
groupBy:用于控制分组,相当于group by关键字后面的部分
having:用于对分组进行过滤,相当于having关键字后面的部分
orderBy:用于对记录进行排序,相当于order by关键字后面的部分
在Android项目开发中我们也不直接使用SQLiteDataBase类操作数据,而是通过数据库管理类SQLiteOpenHelper。可用于管理数据库的创建和版本更新。
一般的用法是创建SQLiteOpenHelper的子类,并扩展它的onCreate和OnUpgrade方法。
—— onCreate(SQLiteDatabase db)
用于初次使用软件时生成数据库表。当调用SQLiteOpenHelper的getWritableDatabase()或者getReadableDatabase()方法获取用于操作数据库的SQLiteDatabase实例时,如果数据库不存在,Android系统会自动生成一个数据库,接着调用onCreate方法,onCreate方法在初次生成数据库时才会被调用,重写onCreate方法,可以生成数据库表结构及添加一些应用使用到的初始化数据。
——onUpgrade()
用于升级软件时更新数据库表结构,方法在数据库的版本发生变化时会被调用,该方法调用时oldVersion代表数据库之前的版本号,newVersion代表当前的版本号。当程序创建SQLiteOpenHelper对象时,必须指定一个version参数,该参数就决定了所使用的数据库的版本。只要某次创建SqliteOpenHelper对象时指定的数据库的版本高于之前指定的版本号,系统就会自动触发该方法。程序员可以再该方法中根据原版本号和目标版本号进行判断,进行必须的表结构更新。
——getWritableDatabase():该方法以读写方式打开数据库,一旦数据库的磁盘空间满了,数据库就只能读而不能写,倘若使用getWritableDatabase() 方法打开数据库就会出错。
——getReadableDatabase()方法先以读写方式打开数据库,如果数据库的磁盘空间满了,就会打开失败,当打开失败后会继续尝试以只读方式打开数据库。
关于查询SQLite查询语句得到的结果集Cursor操作主要如下:
Cursor类似于JDBC的ResultSet,Cursor提供了如下方法来移动查询结果的记录指针:
moveToFirst():将指针移动到第一行,如果成功返回true
moveToLast():将指针移动到最后一行,如果成功返回true
moveToNext():将指针移动到下一行,如果成功返回true
moveToPosition(int):将指针移动到指定行,如果成功返回true
moveToPrevious():将指针移动到上一行,如果成功返回true
还提供了getXxx()方法获取改行的指定列的数据。
getInt()、getString()等,参数为索引,从0开始
getColumnIndex(columnName)获取某个字段的索引
以下做一个简单的增删改查测试,增加了一个用Cursor方式显示数据的方式。布局文件如下
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.briup.sqlitenosql.MainActivity" >
<EditText
android:id="@+id/username"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="用户名" />
<EditText
android:id="@+id/userpwd"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="密码" />
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="save"
android:text="保存数据" />
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:onClick="read"
android:text="显示所有" />
<TextView
android:id="@+id/show"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
<ListView
android:id="@+id/values_list"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
SQLiteOpenHelper类文件如下
import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
public class MySQLiteOpenHelper extends SQLiteOpenHelper {
public MySQLiteOpenHelper(Context context,String name) {
super(context, name, null, 1);// context,文件名,工厂类,版本
}
// 应用程序首次运行时调用,用以建表
@Override
public void onCreate(SQLiteDatabase db) {
String createSql = "create table user(_id integer primary key autoincrement,username,password)";
db.execSQL(createSql);
}
// 版本号更新后调用,可以增加表或者修改表
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
}
}
Alertdialog.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="姓名" />
<EditText
android:id="@+id/alert_name"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" >
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="密码" />
<EditText
android:id="@+id/alert_pass"
android:layout_width="match_parent"
android:layout_height="wrap_content" />
</LinearLayout>
</LinearLayout>
Values_item.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:padding="10dp" >
<TextView
android:id="@+id/item_id"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:textSize="20sp" />
<TextView
android:id="@+id/item_name"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:textSize="20sp" />
<TextView
android:id="@+id/item_pass"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:textSize="20sp" />
</LinearLayout>
MainActivity类文件如下
import android.app.Activity;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.content.ContentValues;
import android.content.DialogInterface;
import android.content.DialogInterface.OnClickListener;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.os.Bundle;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemLongClickListener;
import android.widget.EditText;
import android.widget.ListView;
import android.widget.SimpleCursorAdapter;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends Activity {
private EditText etName, etPass;
private ListView valuesList;
private TextView show;
private SQLiteDatabase db;
private MySQLiteOpenHelper helper;
private static String table = "user";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
etName = (EditText) findViewById(R.id.username);
etPass = (EditText) findViewById(R.id.userpwd);
valuesList = (ListView) findViewById(R.id.values_list);
show = (TextView) findViewById(R.id.show);
// 通过SQLiteOpenHelper类创建表及操作表
helper = new MySQLiteOpenHelper(this, "infom.db");
// 获取SQLiteDatabase
db = helper.getWritableDatabase();
// 长按删除
valuesList.setOnItemLongClickListener(new OnItemLongClickListener() {
@Override
public boolean onItemLongClick(AdapterView<?> arg0, View arg1,
int arg2, long arg3) {
TextView tvId = (TextView) arg1.findViewById(R.id.item_id);
String itemId = tvId.getText().toString();
delete(itemId);
adapterRepalce();
return true;
}
});
// 点击更新
valuesList.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
long arg3) {
// 获取_id,username,password项
TextView tvId = (TextView) arg1.findViewById(R.id.item_id);
TextView tvName = (TextView) arg1
.findViewById(R.id.item_name);
TextView tvPass = (TextView) arg1
.findViewById(R.id.item_pass);
final String id = tvId.getText().toString();
String username = tvName.getText().toString();
String password = tvPass.getText().toString();
// 通过Dialog弹出修改界面
AlertDialog.Builder builder = new Builder(MainActivity.this);
builder.setTitle("修改");
// 自定义界面包括两个文本输入框
View v = View.inflate(MainActivity.this, R.layout.alertdialog,
null);
final EditText etName = (EditText) v
.findViewById(R.id.alert_name);
final EditText etPass = (EditText) v
.findViewById(R.id.alert_pass);
// Dialog弹出就显示原内容
etName.setText(username);
etPass.setText(password);
builder.setView(v);
// 确定按钮点击事件
builder.setPositiveButton("保存", new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
String newName = etName.getText().toString();
String newPass = etPass.getText().toString();
updata(newName, newPass, id);
adapterRepalce();// 更新后刷新列表
}
});
// 取消按钮点击事件
builder.setNegativeButton("取消", new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
builder.create().show();
}
});
}
// 保存按钮点击事件
public void save(View v) {
String name = etName.getText().toString();
String pass = etPass.getText().toString();
insert(name, pass);
Toast.makeText(MainActivity.this, "保存成功", Toast.LENGTH_SHORT).show();
etName.setText("");
etPass.setText("");
}
// 显示按钮点击事件
public void read(View v) {
adapterRepalce();
cursorWay(select());
}
// 插入
private void insert(String name, String pass) {
ContentValues contentValues = new ContentValues();
contentValues.put("username", name);
contentValues.put("password", pass);
db.insert(table, null, contentValues);
}
// 删除
private void delete(String id) {
db.delete(table, "_id=?", new String[] { id });
}
// 更新
private void updata(String username, String password, String id) {
ContentValues contentValues = new ContentValues();
contentValues.put("username", username);
contentValues.put("password", password);
db.update(table, contentValues, "_id=?", new String[] { id });
}
// 查询
private Cursor select() {
return db.query(table, new String[] { "_id", "username", "password" },
null, null, null, null, null);
}
// 直接通过Cursor来显示数据
private void cursorWay(Cursor cursor) {
StringBuffer buffer = new StringBuffer();
while (cursor.moveToNext()) {
buffer.append(cursor.getString(1) + "***" + cursor.getString(2)
+ "\n");
}
show.setText(buffer);
}
// 列表adapter注册
private void adapterRepalce() {
Cursor cursor = select();
SimpleCursorAdapter adapter = new SimpleCursorAdapter(
MainActivity.this, R.layout.values_item, cursor, new String[] {
"_id", "username", "password" }, new int[] {
R.id.item_id, R.id.item_name, R.id.item_pass },
SimpleCursorAdapter.FLAG_REGISTER_CONTENT_OBSERVER);
valuesList.setAdapter(adapter);
}
}
效果如下
增加和显示
更新和删除