Android学习之SQLite练习(一)

来源:互联网 发布:计算机加密软件 编辑:程序博客网 时间:2024/05/16 12:46

上次练习了ContentProvider,知道了一些基本原理,这次接着学习关于里面的SQLite部分。

这次练习的大致内容:SQLite的增,删,查询功能(这次是存放一个Programmer类的数据)。

大致实现思路:(借鉴了其他人的CSDN博客)

1.一个封装数据的Programmer类(包含,id,name,age,level,info信息)

2.数据库帮助管理类:DBHelpManager(继承自SQLiteOpenHelper类,里面负责数据库的创建以及更新,外部可以通过此类的getWritableDatabase()方法来创建或得到一个具有写入权限的SQLiteDatabase,通过getReadableDatabase()来得到一个具有读取权限的SQLiteDatabase)

3.一个数据库操作的规范接口SQLOperate:(里面声明一些对数据库的操作方法)

4.一个数据库操作的具体实现类SQLOperateEntity(实现SQLOperate接口):(具体定义数据库的增,删,查询等功能)

5.一个存放数据库操作的常量的类: SQLMetaData(里面定义一些静态常量,如数据库名,表名,表中的具体属性等)

6.测试所需的Activity:SqlDemoActivity(添加文本输入框,按钮,显示列表等,然后将按钮功能与具体数据库的操作绑定)

错误小结以及解决方法:

1.一些容易出错的 地方要常用try...exception(最好指明具体的错误类型,如SQLException).比如获取EditText里面的文本并且转换为int型时.

2.list<T>里面如果添加了一个null,那么在对List里面的成员进行具体操作时会出错。

未来展望:

1.这次的数据库是使用了OpenHelper类的自动创建方法,所以会创建在(data/data/packagename/)目录下,下次自己定义创建路径(SD卡)

    方法(1.1):继承并重写ContextWrapper的方法,使得创建的时候自定义选择路径

     方法(1.2):放弃使用OpenHelper,自定义数据库的创建,删除等操作方法

2.放弃使用OpenHelper类,自己定义数据库插入,删除等方法(灵活,而且可以用statement,事务支持等)

编程有感:一个小小的程序都得耗费N多时间。

总结:不积跬步无以至千里,继续努力吧!

10/28日更新内容:

1.完成了自定义数据库创建路径,通过继承ContextWrapper并改写Context行为

2.优化了EditText组件

新的工程路径:http://download.csdn.net/detail/u010979495/8091361

附录(关键代码以及效果图以及完整工程):

1.Programmer类

/**该类的作用是封装数据,与对应的表格相应*/public class Programmer {    private int _id;//与所建立的表对应,与SQLite中的主键完全一致    private String name;    private int age;    private int level;    private String info;    public Programmer(int _id,String name,int age,int level,String info)    {        this._id=_id;        this.name=name;        this.age=age;        this.level=level;        if(info!=null) this.info=info;    }    //默认构造,全为空值    public Programmer()    {        this._id=0;        this.name="";        this.age=0;        this.level=0;        this.info="";    }    public int get_id() {        return _id;    }    public void set_id(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 int getLevel() {        return level;    }    public void setLevel(int level) {        this.level = level;    }    public String getInfo() {        return info;    }    public void setInfo(String info) {        this.info = info;    }}


2.DBHelpManager类

/**数据库操作的帮助类*/public class DBHelpManager extends SQLiteOpenHelper{private static final String TAG="DBHelpManager";//定义创建数据库的SQL语句private static final String CREATE_TABLE="CREATE TABLE "+SQLMetaData.P1_TABLE_NAME+" ("+TableMetaData._ID+" INTEGER PRIMARY KEY, "+TableMetaData.PROGRAMMER_NAME+" TEXT, "+TableMetaData.PROGRAMMER_AGE+" INTEGER, "+TableMetaData.PROGRAMMER_LEVEL+" INTEGER, "+TableMetaData.PROGRAMMER_INFO+" TEXT"+");";public DBHelpManager(Context context) {super(context, SQLMetaData.DATABASE_NAME,null, SQLMetaData.DATABASE_VERSION);}//数据库第一次被创建时调用//会默认创建在"/data/data/packagename/"目录下@Overridepublic void onCreate(SQLiteDatabase db) {Log.i(TAG,"创建表:"+db.getPath());db.execSQL(CREATE_TABLE);}//版本升级时调用@Overridepublic void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {Log.i(TAG,"更新数据库,从"+oldVersion+"到"+newVersion+",以前的数据会被销毁");//销毁的sql语句String sql="DROP TABLE IF EXISTS"+SQLMetaData.P1_TABLE_NAME;//执行db.execSQL(sql);//重新创建dbonCreate(db);}}


3.SQLOperate接口

/**定义一个SQLite操作规范的接口---采用接口单一原则*/public interface SQLOperate {public abstract void add(Programmer p);//只有id具有唯一性public abstract void delete(int id);public abstract void update(Programmer p);//查询,全部,单一public abstract List<Programmer> find();public abstract Programmer fingById(int id);}


4.SQLOperateEntity

/**数据库操作的具体类,实现操作规范的接口*/public class SQLOperateEntity implements SQLOperate{private static final String TAG="SQLOperateEntity";//数据库帮助对象的引用private DBHelpManager dbOpenHelper;/**构造方法*/public SQLOperateEntity(Context context){//产生一个DB帮助对象,里面创建一个SQLite数据库Log.i(TAG,TAG+"中创建数据库帮助类对象dbOpenHelper");dbOpenHelper=new DBHelpManager(context);}/**       * 增,用insert向数据库中插入数据       */  @Overridepublic void add(Programmer p) {Log.i(TAG,TAG+"中插入数据");//其实在执行getWritableDatabase()时,dbOpenHelper会进行判定(打开还是创建数据库)SQLiteDatabase db=dbOpenHelper.getWritableDatabase();ContentValues values=new ContentValues();values.put(TableMetaData._ID,p.get_id());values.put(TableMetaData.PROGRAMMER_NAME, p.getName());values.put(TableMetaData.PROGRAMMER_AGE, p.getAge());values.put(TableMetaData.PROGRAMMER_LEVEL, p.getLevel());values.put(TableMetaData.PROGRAMMER_INFO, p.getInfo());//其实这种错误捕获方法是没用的,因为底层的SQLiteDatabase已经自动进行了错误捕获   db.insert(SQLMetaData.P1_TABLE_NAME, null, values);}  /**       * 删,通过id删除数据       */  @Overridepublic void delete(int id) {Log.i(TAG,TAG+"中删除数据");SQLiteDatabase db=dbOpenHelper.getWritableDatabase();String whereClause=TableMetaData._ID+"=?";//删除某个键值的判断String[] whereArgs=new String[]{String.valueOf(id)};//得到ID的stringdb.delete(SQLMetaData.P1_TABLE_NAME, whereClause, whereArgs);} /**       * 改,修改指定id的数据       */  @Overridepublic void update(Programmer p) {Log.i(TAG,TAG+"中更新数据");SQLiteDatabase db=dbOpenHelper.getWritableDatabase();ContentValues values = new ContentValues();  values.put(TableMetaData._ID,p.get_id());values.put(TableMetaData.PROGRAMMER_NAME, p.getName());values.put(TableMetaData.PROGRAMMER_AGE, p.getAge());values.put(TableMetaData.PROGRAMMER_LEVEL, p.getLevel());values.put(TableMetaData.PROGRAMMER_INFO, p.getInfo());//根据id进行更新的String whereClause=TableMetaData._ID+"=?";//删除某个键值的判断String[] whereArgs=new String[]{String.valueOf(p.get_id())};//得到ID的stringdb.update(SQLMetaData.P1_TABLE_NAME, values, whereClause, whereArgs);} /**       * 查,查询表中所有的数据       * 查询时不使用etWritableDatabase()而是ReadableDatabase()     */  @Overridepublic List<Programmer> find() {Log.i(TAG,TAG+"中查询全部数据");List<Programmer> programmers=null;SQLiteDatabase db=dbOpenHelper.getReadableDatabase(); Cursor cursor=null;//得到整个表的Cursor   cursor = db.query(SQLMetaData.P1_TABLE_NAME,   null, null, null, null, null, null);    if(cursor !=null)  {  programmers=new ArrayList<Programmer>();  //循环完所有的记录  for(cursor.moveToFirst();!cursor.isAfterLast();cursor.moveToNext())  {  Programmer programmer=new Programmer();  //得到id的对应索引和值  int _id=cursor.getInt(cursor.getColumnIndex  (TableMetaData._ID));  //得到name的对应索引和值  String name=cursor.getString(cursor.getColumnIndex  (TableMetaData.PROGRAMMER_NAME));  //得到age的对应索引和值  int age=cursor.getInt(cursor.getColumnIndex  (TableMetaData.PROGRAMMER_AGE));  //得到level的对应索引和值  int level=cursor.getInt(cursor.getColumnIndex  (TableMetaData.PROGRAMMER_LEVEL));  //得到info的对应索引和值  String info=cursor.getString(cursor.getColumnIndex  (TableMetaData.PROGRAMMER_INFO));  programmer.set_id(_id);  programmer.setName(name);  programmer.setAge(age);  programmer.setLevel(level);  programmer.setInfo(info);  //添加进对应的list  programmers.add(programmer);  }  }return programmers;}  /**       * 查询指定id的数据       */  @Overridepublic Programmer fingById(int id) {Log.i(TAG,TAG+"中查询单个数据:id="+id);SQLiteDatabase db=dbOpenHelper.getReadableDatabase();//得到某一条数据的CursorString selection=TableMetaData._ID+"=?";String[] selectionArgs=new String[]{String.valueOf(id)};Cursor cursor=null;try {  cursor = db.query(SQLMetaData.P1_TABLE_NAME,   null,selection, selectionArgs, null, null, null);  } catch (Exception e) {Log.i(TAG,"单个查询错误!"+e.getMessage());}  Programmer programmer=null;  //只有一条记录  if(cursor!=null&&cursor.moveToFirst())  {  programmer=new Programmer();  //得到id的对应索引和值  int _id=cursor.getInt(cursor.getColumnIndex  (TableMetaData._ID));  //得到name的对应索引和值  String name=cursor.getString(cursor.getColumnIndex  (TableMetaData.PROGRAMMER_NAME));  //得到age的对应索引和值  int age=cursor.getInt(cursor.getColumnIndex  (TableMetaData.PROGRAMMER_AGE));  //得到level的对应索引和值  int level=cursor.getInt(cursor.getColumnIndex  (TableMetaData.PROGRAMMER_LEVEL));  //得到info的对应索引和值  String info=cursor.getString(cursor.getColumnIndex  (TableMetaData.PROGRAMMER_INFO));  programmer.set_id(_id);  programmer.setName(name);  programmer.setAge(age);  programmer.setLevel(level);  programmer.setInfo(info);  }  if(programmer==null)  Log.i(TAG,"单个查询结果为空!");return programmer;}}


5.SQLMetaData

/**定义一些常用的量*/public class SQLMetaData {//数据库名public static final String DATABASE_NAME="Programmer_dlc.db";//版本号public static final int DATABASE_VERSION=1;//表名,一下是所有需要用到的表的名字public static final String P1_TABLE_NAME="ProgrammerTable";/**内部类,封装关于表的字段信息,实现BaseColumns接口 * 开发人员不必在定义字段_ID和_Count了(因为实现了BaseColumns) * static声明--只属于类而不是属于对象 * */public static final class TableMetaData implements BaseColumns{//某一个表中的所有属性的定义public static final String _ID="_id";//表中的主键public static final String PROGRAMMER_NAME="name";public static final String PROGRAMMER_AGE="age";public static final String PROGRAMMER_LEVEL="level";public static final String PROGRAMMER_INFO="info";//DESC(降序),ASC(升序),这句话的意思为按ID升序public static final String DEFAULT_SORT_ORDER=_ID+" ASC";}}


6.SqlDemoActivity

/**测试数据库操作的Activity*/public class SqlDemoActivity extends Activity implements OnClickListener{private static final String TAG="SqlDemoActivity";//数据库操作对象SQLOperateEntity sqlOperateEntity;private Button btn_insert;private Button btn_delete;private Button btn_query;private EditText edt_id;private EditText edt_name;private EditText edt_age;private EditText edt_level;private EditText edt_info;private ListView listViewContent;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.sqldemo_view);init();}/**功能函数*/private void init(){sqlOperateEntity=new SQLOperateEntity(this);bindWidgets();setListeners();}private void bindWidgets(){Log.i(TAG,"Widget绑定");edt_id=(EditText) findViewById(R.id.edt_id);edt_name=(EditText) findViewById(R.id.edt_name);edt_age=(EditText) findViewById(R.id.edt_age);edt_level=(EditText) findViewById(R.id.edt_level);edt_info=(EditText) findViewById(R.id.edt_info);btn_insert=(Button) findViewById(R.id.btn_insert);btn_delete=(Button) findViewById(R.id.btn_delete);btn_query=(Button) findViewById(R.id.btn_query);listViewContent=(ListView) findViewById(R.id.list_content);}private void setListeners(){Log.i(TAG,"设置监听函数");btn_insert.setOnClickListener(this);btn_delete.setOnClickListener(this);btn_query.setOnClickListener(this);}/**插入*/private void onInsert(Programmer p){Log.i(TAG,"开始插入数据");if(p.get_id()==-1&&p.getAge()==-1&&p.getLevel()==-1)//发现为默认数据时{Log.w(TAG,"没有输入数据,插入无效!");}else{sqlOperateEntity.add(p);}}/**删除*/private void onDelete(int _id){Log.i(TAG,"开始删除记录");sqlOperateEntity.delete(_id);}/**查询*/private List<Programmer> onQuery(int _id){List<Programmer> promrammers=new ArrayList<Programmer>();if(_id==-1)//默认为-1,代表查询全部{Log.i(TAG,"开始查询全部数据!");promrammers=sqlOperateEntity.find();}else{Log.i(TAG,"开始查询单条数据!");Programmer p;p=sqlOperateEntity.fingById(_id);if(p!=null)promrammers.add(p);elseLog.w(TAG,"没有查询到数据!");}return promrammers;}/**这里用到集合类的组合 * ArrayList<HashMap<String,Object>>  * *//***/private void onRefreshView(List<Programmer> programmers){ if(!programmers.isEmpty()) {Log.i(TAG,"开始刷新查询数据!"); } else { Log.i(TAG,"空数据不能刷新查询!"); } List<HashMap<String, String>> items = onFillMaps(programmers); //查询添加到列表 ListAdapter listAdapter = new SimpleAdapter(                 this,items,R.layout.list,                 new String[]{"_id","name","age","level","info"},                 new int[]{R.id.list_id,R.id.list_name,                 R.id.list_age,R.id.list_level,R.id.list_info}); listViewContent.setAdapter(listAdapter); }/**刷新*/private List<HashMap<String, String>> onFillMaps(List<Programmer> programmers){Log.i(TAG,"正在刷新查询数据!");List<HashMap<String, String>> items=new ArrayList<HashMap<String,String>>();//循环for(Programmer p:programmers){HashMap<String,String> map=new HashMap<String,String>();map.put("_id",String.valueOf(p.get_id()));map.put("name", p.getName());map.put("age",String.valueOf(p.getAge()));map.put("level",String.valueOf(p.getLevel()));map.put("info", p.getInfo());items.add(map);}return items;}@Overridepublic void onClick(View v) {int _id=-1;String name="";int age=-1;int level=-1;String info="";try { _id=Integer.parseInt(edt_id.getText().toString().trim()); name=edt_name.getText().toString().trim(); age=Integer.parseInt(edt_age.getText().toString().trim()); level=Integer.parseInt(edt_level.getText().toString().trim()); info=edt_info.getText().toString().trim();} catch (NumberFormatException e) {Log.i(TAG,"得到editText数据时出错!"+e.getMessage());}Programmer p=new Programmer(_id,name,age,level,info);switch(v.getId()){case R.id.btn_insert:onInsert(p);onRefreshView(onQuery(_id));break;case R.id.btn_delete:onDelete(_id);onRefreshView(onQuery(_id));break;case R.id.btn_query:onRefreshView(onQuery(_id));break;default:break;}}}


效果图1:(查询单条记录,程序里面填写好相应的ID)


效果图2:(查询全部记录,不填ID)

完整工程:http://download.csdn.net/detail/u010979495/8088497

0 0