需要测试环境,启动模拟器 不需要对模拟器进行操作 只用junit就能完成本次的练习
一:
创建简单的person bean 有id和name属性 生成getset方法 在有一name的构造器 最好在有一空的构造器
二:
搭建JUnit测试环境 http://blog.csdn.net/hxy01245120/article/details/7897947
三:
编写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, CursorFactory factory, int version) {
/**
* 1<br>
* 2数据库名称<br>
* 3游标工厂 一般都不需要 默认就行 null为默认<br>
* 4数据库版本号<br>
*/
super(context, DATABASENAME, null, DATABASEVERSION);
}
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);
}
}
这俩个测试类都是一样的 只是实现业务的实例对象不一样 方法都是一样 就不在放源码了 还有sqlite的一个工具
下载地址:http://download.csdn.net/detail/hxy01245120/4546917
用法:
安装好软件之后 先把数据库文件导出来 打开软件