Android數據庫編程

小朋友,你是不是有很多問號???

數據庫編程

一、SQLite數據庫簡介

  • SQLite是一個輕量級數據庫,第一個版本誕生於2000年5月。它最初是爲嵌入式設計的,佔用資源非常低,在內存中只需要佔用幾百KB的存儲空間。 My sql structure query language
  • SQLite是遵守ACID關聯式的數據庫管理系統。ACID是指數據庫事務正確執行的基本要素,即原子性(Atomicity)、一致性(Consistency)、隔離性(Isolation)、持久性(Durability)。
  • SQLite沒有服務器進程,它通過文件保存數據,該文件是跨平臺的,可以放在其他平臺中使用。並且支持 NULL、INTEGER、REAL(浮點數字)、TEXT(字符串文本)和BLOB(二進制對象)五種數據類型。

1、相關sql語句

//增刪改查
insert into info (name,phone) values ("王五","138");
update info set phone="13856675089" where name = "王五";
delete from info where name ="王五";
select name,phone from info;
//創建一個表
create table info2(
     _id int primary key ,
     name varchar(20)
     );
//id一般爲_d,自增創建表格
db.execSQL("create table info(_id integer primary key autoincrement,name varchar(20))");
//修改表格
db.execSQL("alter table info add phone varchar(20)");

2、什麼時候使用數據庫

有大量相似結構的數據需要存儲的時候

id 一般爲寫爲_id

這些類型在底層都是String,不區分數據類型,但是寫sql還是要按照標準的sql語句寫

二、創建數據庫,並對其操作

1、創建一個類繼承抽象類SQLiteOpenHelper

實現其中的三個方法

/**
* context 上下文 
* name:數據庫的名字 
* factory:創建cursor(光標,指針)對象 ,相當於Resultset(結果集)
 * version:數據庫的版本 從1開始,只能變大,不能變小
 */
1、 實現其構造方法
 super(context, "ZQ.db", null, 4);
2、onCreate方法,用於創建數據庫		//當數據庫第一次被創建的時候被調用 這個方法特別適合做表結構的初始化 創建表就是寫sql語句
3、onUpgrade方法,用於數據庫版本的更新		//當數據庫版本升級的時候調用,這個方法適合做表結構的更新
4、使用SQLite Expert這個工具可以打開我們創建的數據庫

2、使用sql語句對數據庫進行增刪改查

缺點:sql語句容易寫錯

​ 執行sql語句沒有返回值,不容易進行判斷 void

優點:容易多表查詢

	private void insert() {
		// 獲取數據庫對象
		SQLiteDatabase writableDatabase = myOpenHelpernew.getWritableDatabase();
		// 執行insert的sql語句
        //有兩種execSQL方法
		writableDatabase.execSQL("insert into info (name,phone) values (?,?)",
				new Object[] { "張三", "13856676089" });
		// 數據庫用完需要關閉
		writableDatabase.close();
		Toast.makeText(getApplicationContext(), "插入成功", 0).show();
	}

	private void delete() {
		// 獲取數據庫對象
		SQLiteDatabase writableDatabase = myOpenHelpernew.getWritableDatabase();
		// 執行delete的sql語句
		writableDatabase.execSQL("delete from info where name =?",
				new Object[] { "張三" });
		// 數據庫用完需要關閉
		writableDatabase.close();
		Toast.makeText(getApplicationContext(), "刪除成功", 0).show();
	}

	private void update() {
		// 獲取數據庫對象
		SQLiteDatabase writableDatabase = myOpenHelpernew.getWritableDatabase();
		// 執行update的sql語句
		writableDatabase.execSQL("update info set phone=? where name = ?",
				new Object[] { "110", "張三" });
		// 數據庫用完需要關閉
		writableDatabase.close();
		Toast.makeText(getApplicationContext(), "更新成功", 0).show();
	}

	private void select() {
		// 獲取數據庫對象
		SQLiteDatabase writableDatabase = myOpenHelpernew.getWritableDatabase();
		// 執行select的sql語句
		// 返回類型cursor(Resultset)
		Cursor cursor = writableDatabase.rawQuery("select * from info", null);
		if (cursor != null && cursor.getCount() > 0) {
			while(cursor.moveToNext()){
			// columnIndex代表列的索引
			int id = cursor.getInt(0);
			String name = cursor.getString(1);
			String phone = cursor.getString(2);
			System.out.println("id="+id+" name="+name+" phone="+phone);
			}	
		}
		// 數據庫用完需要關閉
		writableDatabase.close();
	}

//創建或者打開數據庫,如果是第一次就是創建
getWritableDatabase
//創建或者打開數據庫,如果是第一次就是創建 如果磁盤滿了,返回只讀的對象
getReadableDatabase

Cursor接口是一個遊標接口,在數據庫操作中作爲返回值,相當於結果集ResultSet。

3、sqlite3工具

  • 說明:sqlite3.exe是一個簡單的SQLite數據庫管理工具,位於Android ADT Eclipse中的sdk/tools目錄下。
  • 在Windows的cmd中(如果配置了環境變量,直接就可以adb shell就可進入root@android:/ #模式;如果事先沒有配置環境變量,則需C:\adt-bundle-windows-x86_64-20140702\sdk\platform-tools>adb shell)
//改變dos編碼方式
1、chcp	936		//GBK
2、chcp	65001	//utf-8

C:\Users\趙啓>adb shell
root@android:/ # cd /data/data/com.example.sqlite/databases
cd /data/data/com.example.sqlite/databases
root@android:/data/data/com.example.sqlite/databases # ls
ls
ZQ.db
ZQ.db-journal
root@android:/data/data/com.example.sqlite/databases # sqlite3 ZQ.db
sqlite3 ZQ.db
SQLite version 3.7.11 2012-03-20 11:35:50
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite> select * from info;
select * from info;
138|寮犱笁|13856676089		//亂碼了,因爲默認編碼方式是GBK
139|寮犱笁|13856676089

//將dos編碼方式改爲utf-8
C:\Users\趙啓>chcp 65001
Active code page: 65001
.
.
.
sqlite> select * from info;
select * from info;
138|張三|13856676089
139|張三|13856676089

三、使用谷歌封裝好的API進行增刪改查

優點:寫法簡單,不需要寫複雜的sql語句,不容易寫錯

​ 有返回值,方便開發者進行開發

缺點:如果有多張表,使用谷歌封裝的API不容易進行查詢

private void insert() {
		// 獲取數據庫對象
		SQLiteDatabase writableDatabase = myOpenHelpernew.getWritableDatabase();
		/**
		 * table:表名
		 * nullColumnHack:可以爲空
		 * ContentValues:內部封裝了一個map;key:列名,values:值
		 */
		ContentValues values = new ContentValues();
		values.put("name", "王五");
		values.put("phone", "119");
		//返回值代表插入新行的id
		long insert = writableDatabase.insert("info", null, values);//底層在組拼sql語句
		writableDatabase.close();
		if(insert>0){
			Toast.makeText(getApplicationContext(), "添加成功", 0).show();
		}else{
			Toast.makeText(getApplicationContext(), "添加失敗", 0).show();
		}
	}

	private void delete() {
		// 獲取數據庫對象
		SQLiteDatabase writableDatabase = myOpenHelpernew.getWritableDatabase();
		/**
		 * whereClause:刪除的條件
		 * whereArgs:內容,爲String數組
		 */
		//返回值爲受影響的行數
		int delete = writableDatabase.delete("info", "name=?", new String[]{"王五"});
		writableDatabase.close();	
		Toast.makeText(getApplicationContext(), "刪除了"+delete+"行", 0).show();
	}

	private void update() {
		// 獲取數據庫對象
		SQLiteDatabase writableDatabase = myOpenHelpernew.getWritableDatabase();
	     ContentValues values = new ContentValues();
	     values.put("phone", "120");
		int update = writableDatabase.update("info", values, "name=?", new String[]{"王五"});
		writableDatabase.close();
		Toast.makeText(getApplicationContext(), "更新了"+update+"行", 0).show();
	}

	private void select() {
		// 獲取數據庫對象
		SQLiteDatabase writableDatabase = myOpenHelpernew.getWritableDatabase();
		/**
		 * columns:需要查詢哪些列,爲String數組,可以new String[]{"name","phone"},null代表查詢所有
		 * selection:查詢的條件
		 * selectionArgs:查詢條件的具體內容
		 * groupBy:分組
		 * having:過濾條件
		 * orderBy:排序
		 */
		Cursor cursor = writableDatabase.query("info", null, "name=?", new String[]{"王五"}, null, null, null);
		if (cursor != null && cursor.getCount() > 0) {
			while(cursor.moveToNext()){
			// columnIndex代表列的索引
			int id = cursor.getInt(0);
			String name = cursor.getString(1);
			String phone = cursor.getString(2);
			// 把數據封裝到javabean中
				Info info = new Info();
				info.setId(id);
				info.setName(name);
				info.setPhone(phone);
				// 把javabean對象加入到集合
				lists.add(info);
			}	
            //設置數據適配器
			lv.setAdapter(new myListAdapter());
		}
		writableDatabase.close();
	}

四、數據庫的事務介紹

db.beginTransaction();//開啓事務
   try {//寫具體的邏輯
     ...
     //給當前事務設置一個成功的標記,失敗則回滾
     db.setTransactionSuccessful();
   } catch(Exception e){
			Toast.makeText(getApplicationContext(), "服務器忙,請稍後再試", 0).show();
   } finally {
     db.endTransaction();//關閉事務
   }

五、ListView

1、ListView入門

1.1在佈局定義ListView

    <ListView
        android:id="@+id/lv"
        android:layout_width="match_parent"		//均需填充框體
        android:layout_height="match_parent"	//均需填充框體,如果爲包裹內容,listview會做多次的校驗,降低效率。
        android:fastScrollEnabled="true" >		//滾動條
    </ListView>

1.2定義ListView的數據適配器

// 顯示數據 和其他控件有點區別,數據來源於ListAdapter(接口)
		lv.setAdapter(new myListAdapter());
// 定義listView數據適配器,其中BaseAdapter interface ListAdapter
	public class myListAdapter extends BaseAdapter {
	
	}

1.3實現BaseAdapter的getCount和getView方法

// 一共有多少條數據需要展示
		public int getCount() {
			// TODO Auto-generated method stub
			return 15;
		}
		/**
		 * 獲取一個view 用來顯示listView的數據,會作爲listView的一個條目出現 
		 * convertView 歷史緩存對象
		 */
		public View getView(int position, View convertView, ViewGroup parent) {
			TextView tv;
			if (convertView == null) {
				// 創建新的緩存對象
				tv = new TextView(getApplicationContext());
			} else {
				//複用歷史緩存對象
				tv = (TextView) convertView;
			}
			return tv;
		}
	}

2、ListView顯示數據的原理

mvc

  • javaweb

    m:mode數據

    v:view視圖 jsp

    c:controller servlet

  • Android

    m:mode數據(javabean)

    v:view listview

    c:adapter

3、打氣筒inflate

線性佈局,相對佈局都繼承於ViewGroup,可以有自己的孩子

通過一個打氣筒inflate,可以把一個佈局轉換成一個view對象

public View getView(int position, View convertView, ViewGroup parent) {
			// 想辦法將自己的佈局轉換成一個view對象就可以了
			View view;
			if (convertView == null) {
				// 創建新的佈局對象 可以通過打氣筒把一個佈局資源轉換爲一個view對象
				// resource 就是我們定義的佈局文件
				// root 把view加到ViewGroup裏
				/**
				 * 獲取打氣筒服務常用的三種方法
				 */
				//1、獲取打氣筒服務
				view = View.inflate(getApplicationContext(),
						R.layout.activity_item, null);
                
				//2、獲取打氣筒服務
//				  view = LayoutInflater.from(getApplicationContext()).inflate(R.layout.activity_item, null);
				
				//3、獲取打氣筒服務(此方法爲Google工程師使用)
//				LayoutInflater inflater = (LayoutInflater) getSystemService(LAYOUT_INFLATER_SERVICE);
//				view = inflater.inflate(R.layout.activity_item, null);
			} else {
				// 複用歷史緩存對象
				view = convertView;
			}
			return view;
		}
	}

4、數組適配器ArrayAdapter

//也可以是列表
String objects[] = { "張三", "李四", "王五", "花花", "草草" };

// 創建一個ArrayAdapter
		// 有多種方法
		// ArrayAdapter<String> adapter = new ArrayAdapter<String>(
		// getApplicationContext(), R.layout.activity_item1, objects);
		/**
		 * 第三個參數textViewResourceId :必須是textView的id
		 */
		ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
				R.layout.activity_item2, R.id.item2, objects);

5、SimpleAdapter

// 準備listview要顯示的數據data
		List<Map<String, String>> data = new ArrayList<Map<String, String>>();
		Map<String, String> map1 = new HashMap<String, String>();
		map1.put("name", "張飛");
		map1.put("phone", "110");
// 把map加入集合中
		data.add(map1);
// 創建一個SimpleAdapter
		/**
		 * 第二個參數data:List<Map<String, String>> 
		 * 第四個參數from:map集合的key 
		 * 第五個參數to:需要顯示在哪個控件上的id
		 */
		SimpleAdapter adapter = new SimpleAdapter(this, data,
				R.layout.activity_item, new String[] { "name", "phone" },
				new int[] { R.id.tv_name, R.id.tv_phone });

6、查出數據庫的內容然後顯示到ListView上

//Info:javabean,用來封裝數據
List<Info> lists = new ArrayList<Info>();	
//查出數據庫的內容
private void select() {
		// 獲取數據庫對象
		SQLiteDatabase writableDatabase = myOpenHelpernew.getWritableDatabase();

		Cursor cursor = writableDatabase.query("info", null, null, null, null,
				null, null);//表示查詢所有數據
		if (cursor != null && cursor.getCount() > 0) {
			while (cursor.moveToNext()) {
				// columnIndex代表列的索引
				String id = cursor.getString(0);
				String name = cursor.getString(1);
				String phone = cursor.getString(2);
				// 把數據封裝到javabean中
				Info info = new Info();
				info.setId(id);
				info.setName(name);
				info.setPhone(phone);
				// 把javabean對象加入到集合
				lists.add(info);
			}
			//設置數據適配器
			lv.setAdapter(new myListAdapter());
		}
		writableDatabase.close();
	}
//把數據顯示到ListView上
public View getView(int position, View convertView, ViewGroup parent) {
			// 想辦法將自己的佈局轉換成一個view對象就可以了
			View view;
			if (convertView == null) {
				// 獲取打氣筒服務
				view = View.inflate(getApplicationContext(),
						R.layout.activity_item, null);
			} else {
				// 複用歷史緩存對象
				view = convertView;
			}
//			找到控件用來顯示數據,小技巧:view.
			TextView tv_id = (TextView) view.findViewById(R.id.tv_id);
			TextView tv_name = (TextView) view.findViewById(R.id.tv_name);
			TextView tv_phone = (TextView) view.findViewById(R.id.tv_phone);
			
//			如何顯示數據
			Info info = lists.get(position);
			tv_id.setText(info.getId());
			tv_name.setText(info.getName());
			tv_phone.setText(info.getPhone());

			return view;
		}
	}

7、補充

彈出一個對話框

// 彈出一個對話框的方法
			private void showmyDialog(final int position, final Product info) {
				// 彈出一個對話框
				AlertDialog.Builder builder = new Builder(MainActivity.this);
				builder.setTitle("是否確定刪除該條目");
				builder.setPositiveButton("確定",
						new DialogInterface.OnClickListener() {
							public void onClick(DialogInterface dialog,
									int which) {
								// 把選中的條目從集合中刪除
								lists.remove(position);
								// 把當前這個條目從數據庫中刪除
								productDao.delete(info.getId());
								// 更新一下ui
								notifyDataSetChanged();
							}

						});
				builder.setNegativeButton("取消",
						new DialogInterface.OnClickListener() {

							public void onClick(DialogInterface dialog,
									int which) {
								// TODO Auto-generated method stub
							}
						});
				// 對話框一定要記得show出來
				builder.show();
			}

@CopyRight名偵探柯小啓

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章