Android SQLite案例
重点掌握execSQL()和rawQuery()方法,rawQuery()方法用于执行select语句。
SQLiteOpenHelper,实现了onCreate和onUpgrade方法。
第一次创建之后接着会调用onCreate方法(我们在这里创建了数据表),之后onCreate就不再被调用。
DatabaseHelper类:
package com.example.hellodatabases; import android.content.Context;
import android.database.DatabaseErrorHandler;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log; //参考:http://blog.csdn.net/liuhe688/article/details/6715983 public class DatabaseHelper extends SQLiteOpenHelper// 继承SQLiteOpenHelper类
{ // 数据库版本号
private static final int DATABASE_VERSION = ;
// 数据库名
private static final String DATABASE_NAME = "TestDB.db"; // 数据表名,一个数据库中可以有多个表(虽然本例中只建立了一个表)
public static final String TABLE_NAME = "PersonTable"; // 构造函数,调用父类SQLiteOpenHelper的构造函数
public DatabaseHelper(Context context, String name, CursorFactory factory,
int version, DatabaseErrorHandler errorHandler)
{
super(context, name, factory, version, errorHandler); } public DatabaseHelper(Context context, String name, CursorFactory factory,
int version)
{
super(context, name, factory, version);
// SQLiteOpenHelper的构造函数参数:
// context:上下文环境
// name:数据库名字
// factory:游标工厂(可选)
// version:数据库模型版本号
} public DatabaseHelper(Context context)
{
super(context, DATABASE_NAME, null, DATABASE_VERSION); // 数据库实际被创建是在getWritableDatabase()或getReadableDatabase()方法调用时
Log.d(AppConstants.LOG_TAG, "DatabaseHelper Constructor");
// CursorFactory设置为null,使用系统默认的工厂类
} // 继承SQLiteOpenHelper类,必须要覆写的三个方法:onCreate(),onUpgrade(),onOpen()
@Override
public void onCreate(SQLiteDatabase db)
{
// 调用时间:数据库第一次创建时onCreate()方法会被调用 // onCreate方法有一个 SQLiteDatabase对象作为参数,根据需要对这个对象填充表和初始化数据
// 这个方法中主要完成创建数据库后对数据库的操作 Log.d(AppConstants.LOG_TAG, "DatabaseHelper onCreate"); // 构建创建表的SQL语句(可以从SQLite Expert工具的DDL粘贴过来加进StringBuffer中)
StringBuffer sBuffer = new StringBuffer(); sBuffer.append("CREATE TABLE [" + TABLE_NAME + "] (");
sBuffer.append("[_id] INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, ");
sBuffer.append("[name] TEXT,");
sBuffer.append("[age] INTEGER,");
sBuffer.append("[info] TEXT)"); // 执行创建表的SQL语句
db.execSQL(sBuffer.toString()); // 即便程序修改重新运行,只要数据库已经创建过,就不会再进入这个onCreate方法 } @Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
{
// 调用时间:如果DATABASE_VERSION值被改为别的数,系统发现现有数据库版本不同,即会调用onUpgrade // onUpgrade方法的三个参数,一个 SQLiteDatabase对象,一个旧的版本号和一个新的版本号
// 这样就可以把一个数据库从旧的模型转变到新的模型
// 这个方法中主要完成更改数据库版本的操作 Log.d(AppConstants.LOG_TAG, "DatabaseHelper onUpgrade"); db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME);
onCreate(db);
// 上述做法简单来说就是,通过检查常量值来决定如何,升级时删除旧表,然后调用onCreate来创建新表
// 一般在实际项目中是不能这么做的,正确的做法是在更新数据表结构时,还要考虑用户存放于数据库中的数据不丢失 } @Override
public void onOpen(SQLiteDatabase db)
{
super.onOpen(db);
// 每次打开数据库之后首先被执行 Log.d(AppConstants.LOG_TAG, "DatabaseHelper onOpen");
} }
Person类:
package com.example.hellodatabases; public class Person
{
public int _id;
public String name;
public int age;
public String info; public Person()
{
} public Person(String name, int age, String info)
{
this.name = name;
this.age = age;
this.info = info;
} }
管理类DBManager:
package com.example.hellodatabases; 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 android.util.Log; //参考:http://blog.csdn.net/liuhe688/article/details/6715983
public class DBManager
{
private DatabaseHelper helper;
private SQLiteDatabase db; public DBManager(Context context)
{
Log.d(AppConstants.LOG_TAG, "DBManager --> Constructor");
helper = new DatabaseHelper(context);
// 因为getWritableDatabase内部调用了mContext.openOrCreateDatabase(mName, 0,
// mFactory);
// 所以要确保context已初始化,我们可以把实例化DBManager的步骤放在Activity的onCreate里
db = helper.getWritableDatabase();
} /**
* add persons
*
* @param persons
*/
public void add(List<Person> persons)
{
Log.d(AppConstants.LOG_TAG, "DBManager --> add");
// 采用事务处理,确保数据完整性
db.beginTransaction(); // 开始事务
try
{
for (Person person : persons)
{
db.execSQL("INSERT INTO " + DatabaseHelper.TABLE_NAME
+ " VALUES(null, ?, ?, ?)", new Object[] { person.name,
person.age, person.info });
// 带两个参数的execSQL()方法,采用占位符参数?,把参数值放在后面,顺序对应
// 一个参数的execSQL()方法中,用户输入特殊字符时需要转义
// 使用占位符有效区分了这种情况
}
db.setTransactionSuccessful(); // 设置事务成功完成
}
finally
{
db.endTransaction(); // 结束事务
}
} /**
* update person's age
*
* @param person
*/
public void updateAge(Person person)
{
Log.d(AppConstants.LOG_TAG, "DBManager --> updateAge");
ContentValues cv = new ContentValues();
cv.put("age", person.age);
db.update(DatabaseHelper.TABLE_NAME, cv, "name = ?",
new String[] { person.name });
} /**
* delete old person
*
* @param person
*/
public void deleteOldPerson(Person person)
{
Log.d(AppConstants.LOG_TAG, "DBManager --> deleteOldPerson");
db.delete(DatabaseHelper.TABLE_NAME, "age >= ?",
new String[] { String.valueOf(person.age) });
} /**
* query all persons, return list
*
* @return List<Person>
*/
public List<Person> query()
{
Log.d(AppConstants.LOG_TAG, "DBManager --> query");
ArrayList<Person> persons = new ArrayList<Person>();
Cursor c = queryTheCursor();
while (c.moveToNext())
{
Person person = new Person();
person._id = c.getInt(c.getColumnIndex("_id"));
person.name = c.getString(c.getColumnIndex("name"));
person.age = c.getInt(c.getColumnIndex("age"));
person.info = c.getString(c.getColumnIndex("info"));
persons.add(person);
}
c.close();
return persons;
} /**
* query all persons, return cursor
*
* @return Cursor
*/
public Cursor queryTheCursor()
{
Log.d(AppConstants.LOG_TAG, "DBManager --> queryTheCursor");
Cursor c = db.rawQuery("SELECT * FROM " + DatabaseHelper.TABLE_NAME,
null);
return c;
} /**
* close database
*/
public void closeDB()
{
Log.d(AppConstants.LOG_TAG, "DBManager --> closeDB");
// 释放数据库资源
db.close();
} }
Activity:
HelloDBActivity package com.example.hellodatabases; import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map; import android.app.Activity;
import android.database.Cursor;
import android.database.CursorWrapper;
import android.os.Bundle;
import android.view.Menu;
import android.view.View;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.SimpleCursorAdapter; //参考:http://blog.csdn.net/liuhe688/article/details/6715983 public class HelloDBActivity extends Activity
{
private DBManager dbManager;
private ListView listView; @Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_hello_db); listView = (ListView) findViewById(R.id.listView);
// 初始化DBManager
dbManager = new DBManager(this); } @Override
public boolean onCreateOptionsMenu(Menu menu)
{
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.hello_db, menu);
return true;
} @Override
protected void onDestroy()
{
super.onDestroy();
dbManager.closeDB();// 释放数据库资源
} public void add(View view)
{
ArrayList<Person> persons = new ArrayList<Person>(); Person person1 = new Person("Ella", , "lively girl");
Person person2 = new Person("Jenny", , "beautiful girl");
Person person3 = new Person("Jessica", , "sexy girl");
Person person4 = new Person("Kelly", , "hot baby");
Person person5 = new Person("Jane", , "a pretty woman"); persons.add(person1);
persons.add(person2);
persons.add(person3);
persons.add(person4);
persons.add(person5); dbManager.add(persons);
} public void update(View view)
{
// 把Jane的年龄改为30(注意更改的是数据库中的值,要查询才能刷新ListView中显示的结果)
Person person = new Person();
person.name = "Jane";
person.age = ;
dbManager.updateAge(person);
} public void delete(View view)
{
// 删除所有三十岁以上的人(此操作在update之后进行,Jane会被删除(因为她的年龄被改为30))
// 同样是查询才能查看更改结果
Person person = new Person();
person.age = ;
dbManager.deleteOldPerson(person);
} public void query(View view)
{
List<Person> persons = dbManager.query();
ArrayList<Map<String, String>> list = new ArrayList<Map<String, String>>();
for (Person person : persons)
{
HashMap<String, String> map = new HashMap<String, String>();
map.put("name", person.name);
map.put("info", person.age + " years old, " + person.info);
list.add(map);
}
SimpleAdapter adapter = new SimpleAdapter(this, list,
android.R.layout.simple_list_item_2, new String[] { "name",
"info" }, new int[] { android.R.id.text1,
android.R.id.text2 });
listView.setAdapter(adapter);
} @SuppressWarnings("deprecation")
public void queryTheCursor(View view)
{
Cursor c = dbManager.queryTheCursor();
startManagingCursor(c); // 托付给activity根据自己的生命周期去管理Cursor的生命周期
CursorWrapper cursorWrapper = new CursorWrapper(c)
{
@Override
public String getString(int columnIndex)
{
// 将简介前加上年龄
if (getColumnName(columnIndex).equals("info"))
{
int age = getInt(getColumnIndex("age"));
return age + " years old, " + super.getString(columnIndex);
}
return super.getString(columnIndex);
}
};
// 确保查询结果中有"_id"列
SimpleCursorAdapter adapter = new SimpleCursorAdapter(this,
android.R.layout.simple_list_item_2, cursorWrapper,
new String[] { "name", "info" }, new int[] {
android.R.id.text1, android.R.id.text2 });
ListView listView = (ListView) findViewById(R.id.listView);
listView.setAdapter(adapter);
} }
布局:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" > <Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:onClick="add"
android:text="add" /> <Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:onClick="update"
android:text="update" /> <Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:onClick="delete"
android:text="delete" /> <Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:onClick="query"
android:text="query" /> <Button
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:onClick="queryTheCursor"
android:text="queryTheCursor" /> <ListView
android:id="@+id/listView"
android:layout_width="fill_parent"
android:layout_height="wrap_content" /> </LinearLayout>
常量:
package com.example.hellodatabases; public class AppConstants
{
public static final String LOG_TAG="Hello DB"; }
官网Training: Saving Data in SQL Databases
http://developer.android.com/training/basics/data-storage/databases.html
Android中SQLite应用详解:
http://blog.csdn.net/liuhe688/article/details/6715983
关于Cursor类的介绍:
http://www.cnblogs.com/TerryBlog/archive/2010/07/05/1771459.html
Android 小项目之--SQLite 使用法门 (附源码):
http://www.cnblogs.com/TerryBlog/archive/2010/06/12/1757166.html
Android SQLite案例的更多相关文章
- Android SQLite 通配符查询找不到参数问题
使用Android SQLite中SQLiteDatabase类的query方法查询时,如果where中包含通配符,则参数会无法设置,如类似下面的方法查询时 SQLiteDatabase db = d ...
- Android+Sqlite 实现古诗阅读应用(三)
往期传送门: Android+Sqlite 实现古诗阅读应用(一) Android+Sqlite 实现古诗阅读应用(二) 加入截图分享的功能. 很多应用都有分享的功能,我也想在我的古诗App里加入这个 ...
- Android+Sqlite 实现古诗阅读应用(二)
传送门:Android+Sqlite 实现古诗阅读应用(一) Hi,又回来了,最近接到很多热情洋溢的小伙伴们的来信,吼开心哈,我会继续努力的=-=! 上回的东西我们做到了有个textview能随机选择 ...
- Android Sqlite 数据库版本更新
Android Sqlite 数据库版本更新 http://87426628.blog.163.com/blog/static/6069361820131069485844/ 1.自己写一个类继承 ...
- Android SQLite总结(一) (转)
Android SQLite总结(一) 郑海波 2012-08-21 转载请声明:http://blog.csdn.net/nuptboyzhb/article/details/7891887 前言 ...
- android SQLite使用SQLiteOpenHelper类对数据库进行操作
android SQLite使用SQLiteOpenHelper类对数据库进行操作 原文: http://byandby.iteye.com/blog/835580
- Android sqlite管理数据库基本用法
Android操作系统中内置了sqlite数据库(有关sqlite数据库详细介绍见:http://zh.wikipedia.org/wiki/SQLite),而sqllite本身是一个很小型的数据库, ...
- Android SQLite 数据库详细介绍
Android SQLite 数据库详细介绍 我们在编写数据库应用软件时,需要考虑这样的问题:因为我们开发的软件可能会安装在很多用户的手机上,如果应用使用到了SQLite数据库,我们必须在用户初次使用 ...
- Android Sqlite 导入CSV文件 .
http://blog.csdn.net/johnnycode/article/details/7413111 今天遇到 Oracle 导出的12万条CSV格式数据导入 Android Sqlite ...
随机推荐
- jenkins配置以cygwin环境的子节点
1.为Cygwin配置上sshd服务 ⑴.双击点击如下安装文件,并一直选取下一步 ⑵.到这个步骤停止,并且在search栏里输入openssh,并下载搜出的两个程序 ⑶.下载好以后以管理员权限打开cy ...
- Angular material mat-icon 资源参考_Connection
ul,li>ol { margin-bottom: 0 } dt { font-weight: 700 } dd { margin: 0 1.5em 1.5em } img { height: ...
- 描边shader(法线外拓)
描边的思路是需要两个pass.第一个pass让顶点沿着法线方向延伸出去,使得模型变大一圈.第二个pass正常渲染,让正常渲染的模型挡在第一个pass之上,这样就会露出延伸出去的部分,延伸出去的就是我们 ...
- [JAVA]Apache FTPClient操作“卡死”问题的分析和解决
最近在和一个第三方的合作中不得已需要使用FTP文件接口.由于FTP Server由对方提供,而且双方背后各自的网络环境都很不单纯等等原因,造成测试环境无法模拟实际情况.测试环境中程序一切正常,但是在部 ...
- (转)Python 标准库笔记:string模块
String模块包含大量实用常量和类,以及一些过时的遗留功能,并还可用作字符串操作. 原文:http://www.10tiao.com/html/384/201709/2651305041/1.htm ...
- selenium+Python(alert 、confirm 、prompt 的处理)
alert\confirm\prompt 弹出框操作主要方法有: text 返回 alert/confirm/prompt 中的文字信息 accept 点击确认按钮 dismiss 点击取消按钮, ...
- 【lua】LWT request请求处理
request请求处理 通过mod_lwt模块提供的处理程序来调用Lua脚本处理HTTP请求.具体流程: 判断该请求是否由LWT处理,如果不是,拒绝处理请求; 判断Lua脚本文件是否存在,如果不存在, ...
- 1.7 js基础,字符串、数组小结
一.arguments 实参参数的数组 实参[实际的值],形参[形式上的参数] 当参数个数不固定的时候使用. 示例: script> var g ...
- 常用Oracle的SQL语句20181206更新
--clob转字符串:dbms_lob.substr() --锁表:select object_name,machine,s.sid,s.serial# from v$locked_object l, ...
- Java通过流对MP4视频文件进行加密,H5 video播放流
加密目标文件 代码如下: 不建议进行二次加密,若二次加密必须要二次解密 package com.xgt.util; import java.io.*; public class VideoEncode ...