设为首页 加入收藏

TOP

SQLite应用详解(三)
2015-07-24 10:15:57 来源: 作者: 【 】 浏览:9
Tags:SQLite 应用 详解
etAge(32); // ContentValues以键值对的形式存放数据 ContentValues values = new ContentValues(); values.put("name", person.getName()); values.put("age", person.getAge()); // 插入ContentValues中的数据 db.insert("person", null, values); values = new ContentValues(); values.put("age", "40"); // 更新数据 db.update("person", values, "name = ? ", new String[] { "zhangsan" }); Cursor c = db.rawQuery("select * from person where age>= ?", new String[] { "32" }); while (c.moveToNext()) { int _id = c.getInt(c.getColumnIndex("_id")); String name = c.getString(c.getColumnIndex("name")); int age = c.getInt(c.getColumnIndex("age")); Log.i("leo", "_id = " + _id + " ,name = " + name + " ,age = " + age); } c.close(); // 删除数据 // db.delete("person", "age < ?", new String[] { "36" }); // 关闭当前数据库 db.close(); // 删除test.db数据库 // deleteDatabase("test.db"); } } 在Android手机或模拟器上运行后,系统就会在/data/data/[项目包名]databases目录下生成一个"test.db"的数据库文件,我们可以用手机下载一个名为Root Explorer的软件进行查看,如图:

?

\
同时可以看到,控制台打印了log信息:

\

上面的示例代码基本上囊括了数据库大部分操作,对于添加、更新和删除,我们都可以使用

1.db.executeSQL(String sql);
2.db.executeSQL(String sql, Object[] bindArgs);//sql语句中使用占位符,然后第二个参数是实际的参数数组

除了统一的形式之外,它们还有各自的操作方法:

1.db.insert(String table, String nullColumnHack, ContentValues values);
2.db.update(String table, Contentvalues values, String whereClause, String whereArgs);
3.db.delete(String table, String whereClause, String whereArgs);

参数说明:以上3个方法的第一个参数都是要操作的表名;①insert中的第二个参数表示要插入的数据每一列都为空的话,需要指定此行中某一列的名称,系统将此列设置为null,不至于出现错误;insert的第三个参数为ContentValues类型的变量,是键值对组成的Map,key代表列名,value代表要插入的值。②update的第二个参数也很类似,只不过它是更新该字段key为最新的value值,第三个参数表示where的表达式,比如:"age > ? and age < ? "等,最后一个参数是占位符的实际参数值。③delete方法同上。

下面说说查询操作,查询操作相对于上面的几种操作要复杂一些,因为我们要经常面对各种各样的查询条件,所以系统也考虑到这种复杂性,为我们提供了较为丰富的查询形式:

1.db.rawQuery(String sql, String[] selectionArgs);
2.db.query(String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy);
3.db.query(String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit);
4.db.query(String distinct, String table, String[] columns, String selection, String[] selectionArgs, String groupBy, String having, String orderBy, String limit);

参数说明:上面几种都是常用的查询方法,第一种最为简单,将所有的SQL语句都组织到一个字符串中,使用占位符代替实际参数,selectionArgs就是占位符实际参数集;下面的几种参数都很类似,columns表示要查询的列所有名称集,selection表示WHERE之后的条件语句,可以使用占位符,groupBy指定分组的列名,having指定分组条件,配合groupBy使用,orderBy指定排序的列名,limit指定分页参数,distinct可以指定“true”或“false”表示要不要过滤重复值。

最后,他们同时返回一个Cursor对象,代表数据集的游标,有点类似于JDBC里面的的ResultSet结果集。对于Cursor对象,常用的方法有很多(大家也可以通过查考官方API文档进行查阅),常用方法如下:

1.c.move(int offset); //以当前位置为参考,移动到指定行
2.c.moveToFirst(); //移动到第一行
3.c.moveToLast(); //移动到最后一行
4.c.moveToPosition(int position); //移动到指定行
5.c.moveToPrevious(); //移动到前一行
6.c.moveToNext(); //移动到下一行
7.c.isFirst(); //是否指向第一条
8.c.isLast(); //是否指向最后一条
9.c.isBeforeFirst(); //是否指向第一条之前
10.c.isAfterLast(); //是否指向最后一条之后
11.c.isNull(int columnIndex); //指定列是否为空(列基数为0)
12.c.isClosed(); //游标是否已关闭
13.c.getCount(); //总数据项数
14.c.getPosition(); //返回当前游标所指向的行数
15.c.getColumnIndex(String columnName);//返回某列名对应的列索引值
16.c.getString(int columnIndex); //返回当前行指定列的值

最后当我们完成了对数据库的操作后,记得调用SQLiteDatabase的close()方法释放数据库连接,否则容易出现SQLiteException。
上面就是SQLite的基本应用,但在实际开发中,为了能够更好的管理和维护数据库,我们会封装一个继承自SQLiteOpenHelper类的数据库操作类,然后以这个类为基础,再封装我们的业务逻辑方法。下面,我们就以一个实例来讲解具体的用法,我们新建一个名为db的项目:

\

其中DBHelper继承了SQLiteOpenHelper,作为维护和管理数据库的基类,DBManager是建立在DBHelper之上,封装了常用的业务方法,Person是我们的person表对应的JavaBean,MainActivity就是我们显示的界面。

下面我们先来看一下DBHelper:

?

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;

/**
 * 维护和管理数据库
 * 
 * @author [*昨日重现*] lhy_ycu@163.com
 * @since version 1.0
 */

public class DBHelper extends SQLiteOpenHelper {

	private static final String DATABASE_NAME = "test.db";
	private static final int DATABASE_VERSION = 1;

	public DBHelper(Context context) {
		super(context, DATABASE_NAME, null, DATABASE_VERSION);
	}

	// 数据库第一次被创建时onCreate会被调用??
	/**
	 * @param db
	 * @see android.database.sqlite.SQLiteOpenHelper#onCreate(android.database.sqlite.SQLiteDatabase)
	 */
	@Override
	public void onCreate(SQLiteDatabase db) {
		// TODO Auto-generated method stub
		db.execSQL("create table student(_id integer primary key autoincrement, name text, age integer, info text);");
	}

	// 如果DATABASE_VERSION值改变了,系统发现现有数据库版本不同,即会调用onUpgrade??
	/**
	 * @param db
	 * @param oldVersion
	 * @param newVersion
	 * @see android.database.sqlite.SQLiteOpenHelper#onUpgrade(android.database.sqlite.SQLiteDatabase,
	 *      int, int)
	 */
	@Override
	public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
		// TODO Auto-generated method stub
		db.execSQL("alter?table?student?ADD?COLUMN?other?text");
	}
}

?

正如上面所述,数据库第一次创建时onCreate方法会被调用,我们可以执行创建表的语句,当系统发现版本变化之后,会调用onUpgrade方法,我们可以执行修改表结构等语句。
为了方便我们面向对象的使用数据,我们建一个Student类,对应student表中的字段,如下:

?

public class Student {
	private int id;
	private String name;
	private int age;
	private String info;

	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public int getAge() {
		return age;
	}

	public void setAge(int age) {
		this.age = age;
	}

	public String getInfo() {
		return info;
	}

	public void setInfo(String info) {
		this.info = info;
	}

	@Override
	public String toString() {
		return "Student [id=" + id + ", name=" + name + ", age=" + age
				+ ", info=" + info + "]";
	}
}

然后,我们需要一个DBManager,来封装我们所有的业务方法,代码如下:

?

?

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;

/**
 * DBManager是建立在DBHelper之上,封装了常用的业务方法
 * 
 * @author [*昨日重现*] lhy_ycu@163.com
 * @since version 1.0
 */

public class DBManager {
	private DBHelper helper;
	private SQLiteDatabase db;

	public DBManager(Context context) {
		helper = new DBHelper(context);
		// 因为getWritableDatabase内部调用了mContext.openOrCreateDatabase(mName,?0,?mFactory);??
		// 所以要确保context已初始化,我们可以把实例化DBManager的步骤放在Activity的onCreate里
		db = helper.getWritableDatabase();
	}

	/**
	 * 添加学生
	 * 
	 * @param student
	 */
	public void add(Student student) {
		db.beginTransaction();// 开启事务
		try {
			db.execSQL("insert into student values(null, ?, ?,?)", new Object[] {
					student.getName(), student.getAge(), student.getInfo() });
			db.setTransactionSuccessful();// 设置事务成功完成
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			db.endTransaction();// 结束事务
		}
	}

	/**
	 * 更新年龄和基本信息
	 * 
	 * @param student
	 */
	public void update(Student student) {
		ContentValues values = new ContentValues();
		values.put("age", student.getAge());
		values.put("info", student.getInfo());
		db.update("student", values, "name = ?",
				new String[] { student.getName() });
		values.clear();
	}

	/**
	 * 删除年龄大的
	 * 
	 * @param student
	 */
	public void delete(Student student) {
		db.delete("student", "age >= ?", new String[] { student.getAge() + "" });
	}

	/**
	 * 查询所有学生
	 * 
	 * @return
	 */
	public List
  
    query() {
		List
   
     list = new ArrayList
    
     (); Cursor c = db.rawQuery("select * from student", null); while (c.moveToNext()) { Student student = new Student(); student.setId(c.getInt(c.getColumnIndex("_id"))); student.setName(c.getString(c.getColumnIndex("name"))); student.setAge(c.getInt(c.getColumnIndex("age"))); student.setInfo(c.getString(c.getColumnIndex("info"))); list.add(student); } c.close(); return list; } /** * 关闭数据库 */ public void closeDB() { db.close(); } }
    
   
  

?

我们在DBManager构造方法中实例化DBHelper并获取一个SQLiteDatabase对象,作为整个应用的数据库实例;在添加Student信息时,我们采用了事务处理,确保数据完整性;最后我们提供了一个closeDB方法,释放数据库资源,这一个步骤在我们整个应用关闭时执行,这个环节容易被忘记,所以大家要注意。下面开始编写我们的布局文件和MainActivity界面:

  
  
    

?

public class MainActivity extends Activity {
	private DBManager mgr;
	private ListView listView;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);

		listView = (ListView) findViewById(R.id.listview);
		mgr = new DBManager(this);// 初始化DBManager
	}

	public void add(View view) {
		Student student = new Student();
		student.setName("张三");
		student.setAge(22);
		student.setInfo("good boy");
		mgr.add(student);
	}

	public void update(View view) {
		Student student = new Student();
		student.setAge(21);
		student.setName("张三");
		student.setInfo("bad boy");
		mgr.update(student);
	}

	public void delete(View view) {
		Student student = new Student();
		student.setAge(18);
		mgr.delete(student);
	}

	public void query(View view) {
		List
  
    students = mgr.query();
		List
   
    > list = new ArrayList
    
     >(); for (Student student : students) { HashMap
     
       map = new HashMap
      
       (); map.put("name", student.getName()); map.put("info", student.getAge() + " years old, " + student.getInfo()); list.add(map); } SimpleAdapter adapter = new SimpleAdapter(this, list, android.R.layout.simple_list_item_2, new String[] { "name", "info" }, new int[] { android.R.id.text1, android.R.id.text2 }); listView.setAdapter(adapter); } @Override protected void onDestroy() { // TODO Auto-generated method stub super.onDestroy(); // 应用的最后一个Activity关闭时释放DB?? mgr.closeDB(); } }
      
     
    
   
  
最后我们来看下运行结果:

?

\

如果是在手机上运行,我们可以使用Root Explorer查看test.db数据库详情;如果在运行在模拟器上,可以使用SQLite Expert查看;当然你也可以用开始讲的SQLite命令行操作,这里就不再演示了。

结束语

首页 上一页 1 2 3 4 下一页 尾页 3/4/4
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
分享到: 
上一篇润乾集算报表用脚本实现动态SQL传.. 下一篇SqlServerINSTEADOFUPDATE视图触..

评论

帐  号: 密码: (新用户注册)
验 证 码:
表  情:
内  容:

·如何从内核协议栈到 (2025-12-27 03:19:09)
·什么是网络协议?有哪 (2025-12-27 03:19:06)
·TCP/ IP协议有哪些 (2025-12-27 03:19:03)
·怎样用 Python 写一 (2025-12-27 02:49:19)
·如何学习python数据 (2025-12-27 02:49:16)