之前学到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); } }
效果如下
增加和显示
更新和删除