需要测试环境,启动模拟器 不需要对模拟器进行操作 只用junit就能完成本次的练习
一、编写sqlite的助手类 继承SQLiteOpenHelper类 因为父类没有空的构造器 所有要创建
public DBOpenHelp(Context context, CursorFactory factory, int version) {} 构造器
在创建一个 public DBOpenHelp(Context context) {}构造器 方便调用 下面助手类源码
- package com.itcast.service;
- import android.content.Context;
- import android.database.sqlite.SQLiteDatabase;
- import android.database.sqlite.SQLiteDatabase.CursorFactory;
- import android.database.sqlite.SQLiteOpenHelper;
- /**
- * 实现了SQLiteOpenHelper的助手类
- *
- * @author Administrator
- *
- */
- public class DBOpenHelp extends SQLiteOpenHelper {
- private static final String DATABASENAME = "itcast.db";// 数据库名称
- private static final int DATABASEVERSION = 1;// 数据库版本
- public DBOpenHelp(Context context) {
- /**
- * 1<br>
- * 2数据库名称<br>
- * 3游标工厂 一般都不需要 默认就行 null为默认<br>
- * 4数据库版本号<br>
- */
- super(context, DATABASENAME, null, DATABASEVERSION);
- }
- @Override
- /**
- * 该方法只调用一次 就是在数据库被创建的时候<br>
- * 可以完成数据库表的创建<br>
- * 可以通过擦参数SQLiteDatabase的对象 执行sql语句
- */
- public void onCreate(SQLiteDatabase db) {
- /**
- * mysql有5个数据对象可存储 INTEGER TEXT(字符串文本) NULL REAL(浮点数字) BLOB(二进制对象)<br>
- * 但也可以存储其他的数据类型 比如 varchar(n) char(n) decimal(p,s)等数据类型
- * 只不过在保存的时候会转成对应的5中数据类型<br>
- * sqlite 最大特点就是可以把各种数据类型保存到字段中 而不用关心数据库声明字段的类型
- * 比如可以再integer类型存放字符串或者在字符类型中存放日期<br>
- * 但有一种是例外 定义为integer primary key的字段 只能64为整数 当向这种字段保存其他类型数据时 会产生错误<br>
- * sqlite 在创建表( create table )的时候会忽略字段后跟的数据类型 以及 他的长度 所以sqlite数据库中创建的表
- * 是忽略字段类型 和长度的 除了上面说到的integer primary key<br>
- */
- db.execSQL("create table person(id integer primary key autoincrement,name varchar(20))");// 执行有更新行为的sql,比如创建,修改,删除
- }
- @Override
- /**
- * 更新数据库版本的时候调用 可以对数据表结构调整 基本信息添加等
- */
- public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
- db.execSQL("drop table if exists person ");// 真正项目中需要考虑数据的重要性 尽量少对数据库做删除
- onCreate(db);
- }
- }
二、编写增删改查的业务类 android可用资源少 所以不建议面向接口编程 尽量少用接口 接口也只是为了代码的耦合 在android不存在多少代码的耦合 所以不需要 这也是android大多用内部类的一个原因 下面增删改查的业务类代码及注释
- package com.itcast.service;
- import java.util.ArrayList;
- import java.util.List;
- import android.content.Context;
- import android.database.Cursor;
- import android.database.sqlite.SQLiteDatabase;
- import com.itcast.model.Person;
- public class PersonService {
- private DBOpenHelp dbOpenHelp;
- public PersonService(Context context) {
- this.dbOpenHelp = new DBOpenHelp(context);
- }
- /**
- * 添加一个person
- *
- * @param person
- */
- public void savePerson(Person person) {
- // getWritableDatabase()如果磁盘空间满了,就只能以读的方式打开数据库,所以在磁盘空间满了的状态下调用该方法会出错
- SQLiteDatabase db = dbOpenHelp.getWritableDatabase();// 可读可写的方式打开数据库,如果要对数据进行增删改操作,调用该方法的到数据库操作实例
- // getReadableDatabase 该方法是先调用getWritableDatabase 如果磁盘空间满了
- // 调用getWritableDatabase方法会出错 之后就会调用另一开以只读的方法打开数据库
- dbOpenHelp.getReadableDatabase();// 以读的形式打开数据库,如果只对数据进行,就调用该方法
- db.execSQL("insert into person(name) values(?)", new Object[] { person.getName() });// 后面的数组用来填充前面的占位符
- }
- /**
- * 更新person对象
- *
- * @param person
- */
- public void updatePerson(Person person) {
- SQLiteDatabase db = dbOpenHelp.getWritableDatabase();// getWritableDatabase,getReadableDatabase调用后先检测数据库版本号
- // 如果跟上次不一样,就会调用@DBOpenHelp@onUpgrade()
- db.execSQL("update person set name=? where id=?", new Object[] { person.getName(), person.getId() });
- }
- /**
- * 删除一个person对象
- *
- * @param personId
- */
- public void deletePerson(Integer personId) {
- SQLiteDatabase db = dbOpenHelp.getWritableDatabase();
- db.execSQL("delete from person where id=?", new Object[] { personId.toString() });
- }
- /**
- * 查询一个person
- *
- * @param personId
- * @return
- */
- public Person findPerson(Integer personId) {
- SQLiteDatabase db = dbOpenHelp.getReadableDatabase();// 如果磁盘空间没满的话,该对象与上面的对象是相等的,如果满了,该方法会调用另一只读方法,那么他们就不相等了
- Cursor cursor = db.rawQuery("select * from person where id=?", new String[] { personId.toString() });
- if (cursor.moveToFirst()) {
- Person person = new Person();
- person.setId(cursor.getInt(cursor.getColumnIndex("id")));
- person.setName(cursor.getString(cursor.getColumnIndex("name")));
- return person;
- }
- return null;
- }
- /**
- * 查询分页
- *
- * @param offSet
- * 忽略开始的多少条数据
- * @param maxResult
- * 查询的记录数
- * @return
- */
- public List<Person> findPersonForPage(int offset, int maxResult) {
- List<Person> persons = new ArrayList<Person>();
- SQLiteDatabase db = dbOpenHelp.getReadableDatabase();
- Cursor cursor = db.rawQuery("select * from person limit?,?", new String[] { String.valueOf(offset), String.valueOf(maxResult) });
- while (cursor.moveToNext()) {
- Person person = new Person();
- person.setId(cursor.getInt(cursor.getColumnIndex("id")));
- person.setName(cursor.getString(cursor.getColumnIndex("name")));
- persons.add(person);
- }
- cursor.close();
- return persons;
- }
- /**
- * 查询person表的总记录数
- *
- * @return
- */
- public Long countPerson() {
- SQLiteDatabase db = dbOpenHelp.getReadableDatabase();
- Cursor cursor = db.rawQuery("select count(*) from person", null);
- cursor.moveToFirst();// 一定要将光标移动到第一行 因为光标刚开始处于第一条记录的顶部
- // moveToFirst可以判断光标是否可以移到下一行并且移到下一行
- return cursor.getLong(0);
- }
- }
三、测试类;需要测试环境 上面有连接
- package com.itcast.db;
- import java.util.List;
- import android.test.AndroidTestCase;
- import android.util.Log;
- import com.itcast.model.Person;
- import com.itcast.service.DBOpenHelp;
- import com.itcast.service.PersonService;
- public class PersonServiceTest extends AndroidTestCase {
- private static final String TAG = "PersonServiceTest";
- public void testCreateDataBase() throws Throwable {
- DBOpenHelp dbHelp = new DBOpenHelp(getContext());
- dbHelp.getWritableDatabase();
- }
- public void testSavePerson() throws Throwable {
- PersonService personService = new PersonService(getContext());
- Person person = new Person("张三");
- Person person2 = new Person("李四");
- Person person3 = new Person("王五");
- Person person4 = new Person("赵六");
- Person person5 = new Person("黑七");
- Person person6 = new Person("马二");
- personService.savePerson(person);
- personService.savePerson(person2);
- personService.savePerson(person3);
- personService.savePerson(person4);
- personService.savePerson(person5);
- personService.savePerson(person6);
- }
- public void testUpdatePerson() throws Throwable {
- Person person = new Person();
- person.setId(1);
- person.setName("xxx");
- PersonService personService = new PersonService(getContext());
- personService.updatePerson(person);
- }
- public void testDeletePerson() throws Throwable {
- PersonService personService = new PersonService(getContext());
- personService.deletePerson(1);
- }
- public void testFindPerson() throws Throwable {
- PersonService personService = new PersonService(getContext());
- Person person = personService.findPerson(1);
- Log.i(TAG, person.toString());
- }
- public void testFindPersonForPage() throws Throwable {
- PersonService personService = new PersonService(getContext());
- List<Person> persons = personService.findPersonForPage(1, 3);
- for (Person person : persons) {
- Log.i(TAG, person.toString());
- }
- }
- public void testCountPerson() throws Throwable {
- PersonService personService = new PersonService(getContext());
- Long n = personService.countPerson();
- Log.i(TAG, n+"");
- }
- }
四、另一种业务类的写法,这种写法一是为了不熟悉sql,而是如果开发过程中有第三方提供数据或者API符合下面的语句条件 可用下面的增删改查业务的方法实现对数据库的操作 一般情况下不建议下面着用 因为下面的语句都是自己有构造的sql语句 但从性能上说就没有上面的业务类高 为不同的需求 下面贴出源码
- package com.itcast.service;
- import java.util.ArrayList;
- import java.util.List;
- import android.content.ContentValues;
- import android.content.Context;
- import android.database.Cursor;
- import android.database.sqlite.SQLiteDatabase;
- import com.itcast.model.Person;
- public class OtherPersonService {
- private DBOpenHelp dbOpenHelp;
- public OtherPersonService(Context context) {
- this.dbOpenHelp = new DBOpenHelp(context);
- }
- /**
- * 添加一个person
- *
- * @param person
- */
- public void savePerson(Person person) {
- SQLiteDatabase db = dbOpenHelp.getWritableDatabase();
- ContentValues values = new ContentValues();
- values.put("name", person.getName());
- db.insert("person", null, values);// 该方法自己构造sql语句 所以性能比execSQL
- // 参数2表示;如果参数3为空的话,参数2将作为insert语句的字段名插入一个null值,除了主键 其他都为空值
- // 例如 db.insert("person", "name", null);
- // 等价于 insert into person(name) values(null);
- }
- /**
- * 更新person对象
- *
- * @param person
- */
- public void updatePerson(Person person) {
- SQLiteDatabase db = dbOpenHelp.getWritableDatabase();
- ContentValues values = new ContentValues();
- values.put("name", person.getName());
- /**
- * 1:表名<br>
- * 2:要修改的字段和值放在一个类似map的集合里 字段做key<br>
- * 3:sql语句中的条件语句 不带where 值可用占位符表示<br>
- * 4:数组,存放前面的占位符的值
- */
- db.update("person", values, "id=?", new String[] { String.valueOf(person.getId()) });// 该方法构造了自己又构造了sql语句
- // 上面语句等价于 db.execSQL("update person set name=? where id=?", new
- // Object[] {
- // person.getName(), person.getId() });
- }
- /**
- * 删除一个person对象
- *
- * @param personId
- */
- public void deletePerson(Integer personId) {
- SQLiteDatabase db = dbOpenHelp.getWritableDatabase();
- db.delete("person", "id=?", new String[] { personId.toString() });
- // 上面语句等价于 db.execSQL("delete from person where id=?", new Object[] {
- // personId.toString() });
- }
- /**
- * 查询一个person
- *
- * @param personId
- * @return
- */
- public Person findPerson(Integer personId) {
- SQLiteDatabase db = dbOpenHelp.getReadableDatabase();// 如果磁盘空间没满的话,该对象与上面的对象是相等的,如果满了,
- // 该方法会调用另一只读方法,那么他们就不相等了
- /**
- * 1:表名<br>
- * 2:查找表列名的组合 是一个字符串数组 如果为null的话 则表示全部<br>
- * 3:查询的条件,可用占位符<br>
- * 4:是参数3中占位符的值<br>
- * 5:分组依据<br>
- * 6:分组筛选语句<br>
- * 7:排序语句
- */
- Cursor cursor = db.query("person", new String[] { "id", "name" }, "id=?", new String[] { personId.toString() }, null, null, null);
- // 上面语句等价于 Cursor cursor =
- // db.rawQuery("select * from person where id=?", new
- // String[] { personId.toString() });
- if (cursor.moveToFirst()) {
- Person person = new Person();
- person.setId(cursor.getInt(cursor.getColumnIndex("id")));
- person.setName(cursor.getString(cursor.getColumnIndex("name")));
- return person;
- }
- return null;
- }
- /**
- * 查询分页
- *
- * @param offSet
- * 忽略开始的多少条数据
- * @param maxResult
- * 查询的记录数
- * @return
- */
- public List<Person> findPersonForPage(int offset, int maxResult) {
- List<Person> persons = new ArrayList<Person>();
- SQLiteDatabase db = dbOpenHelp.getReadableDatabase();
- /**
- * 1:表名<br>
- * 2:查找表列名的组合 是一个字符串数组 如果为null的话 则表示全部<br>
- * 3:查询的条件,可用占位符<br>
- * 4:是参数3中占位符的值<br>
- * 5:分组依据<br>
- * 6:分组筛选语句<br>
- * 7:排序语句<br>
- * 8:分页语句 传入类似 2,5的字符串<br>
- */
- Cursor cursor = db.query("person", null, null, null, null, null, null, offset + "," + maxResult);
- // 上面语句等价于 Cursor cursor = db.rawQuery("select * from person limit?,?",
- // new
- // String[] { String.valueOf(offset), String.valueOf(maxResult) });
- while (cursor.moveToNext()) {
- Person person = new Person();
- person.setId(cursor.getInt(cursor.getColumnIndex("id")));
- person.setName(cursor.getString(cursor.getColumnIndex("name")));
- persons.add(person);
- }
- cursor.close();
- return persons;
- }
- /**
- * 查询person表的总记录数
- *
- * @return
- */
- public Long countPerson() {
- SQLiteDatabase db = dbOpenHelp.getReadableDatabase();
- Cursor cursor = db.query("person", new String[] { "count(*)" }, null, null, null, null, null);
- // 上面语句等价于 Cursor cursor = db.rawQuery("select count(*) from person",
- // null);
- cursor.moveToFirst();// 一定要将光标移动到第一行 因为光标刚开始处于第一条记录的顶部
- // moveToFirst可以判断光标是否可以移到下一行并且移到下一行
- return cursor.getLong(0);
- }
- }