目錄
小朋友,你是不是有很多問號???
數據庫編程
一、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();
}