Android学习之SQLite练习(一)

上次练习了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里面如果添加了一个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/"目录下
	@Override
	public void onCreate(SQLiteDatabase db) {
		Log.i(TAG,"创建表:"+db.getPath());
		db.execSQL(CREATE_TABLE);
	}
	//版本升级时调用
	@Override
	public 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);
		//重新创建db
		onCreate(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 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向数据库中插入数据  
     */  
	@Override
	public 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删除数据  
     */  
	@Override
	public void delete(int id) {
		Log.i(TAG,TAG+"中删除数据");
		SQLiteDatabase db=dbOpenHelper.getWritableDatabase();
		String whereClause=TableMetaData._ID+"=?";//删除某个键值的判断
		String[] whereArgs=new String[]{String.valueOf(id)};//得到ID的string
			db.delete(SQLMetaData.P1_TABLE_NAME, whereClause, whereArgs);
	}
	 /**  
     * 改,修改指定id的数据  
     */  
	@Override
	public 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的string
			db.update(SQLMetaData.P1_TABLE_NAME, values, whereClause, whereArgs);
		
	}
	 /**  
     * 查,查询表中所有的数据  
     * 查询时不使用etWritableDatabase()而是ReadableDatabase()
     */  
	@Override
	public List find() {
		Log.i(TAG,TAG+"中查询全部数据");
		List 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();
			  //循环完所有的记录
			  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的数据  
     */  
	@Override
	public Programmer fingById(int id) {
		Log.i(TAG,TAG+"中查询单个数据:id="+id);
		SQLiteDatabase db=dbOpenHelper.getReadableDatabase();
		//得到某一条数据的Cursor
		String 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;
	@Override
	protected 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 onQuery(int _id)
	{
		List promrammers=new ArrayList();
		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);
		else
		Log.w(TAG,"没有查询到数据!");
		}
		return promrammers;
	}
	/**这里用到集合类的组合
	 * ArrayList> 
	 * */
	/***/
	private void onRefreshView(List programmers)
	{
		 if(!programmers.isEmpty())
		 {
		Log.i(TAG,"开始刷新查询数据!");
		 }
		 else
		 {
			 Log.i(TAG,"空数据不能刷新查询!");
		 }
		 List> 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> onFillMaps(List programmers)
	{
		Log.i(TAG,"正在刷新查询数据!");
		List> items=new ArrayList>();
		//循环
		for(Programmer p:programmers)
		{
			HashMap map=new HashMap();
			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;
	}
	@Override
	public 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

你可能感兴趣的:(Android学习)