关于android开发,android数据库开发持久化是在app中还是在服务器中

Android greenDAO数据库配置教程
核心提示:一、环境配置1、在Android Studio中,在.src/main目录下新建一个java-gen文件夹,和java文件夹同级。用于存放greenDAO生成的DaoMaster、DaoSession、Table、TableDaoSession实体类。2、配置项目的app.gradle文件,指定java-gen文件,引入greenDAO第三方jar包s
一、环境配置
1、在Android Studio中,在.src/main目录下新建一个java-gen文件夹,和java文件夹同级。用于存放greenDAO生成的DaoMaster、DaoSession、Table、TableDaoSession实体类。
2、配置项目的app.gradle文件,指定java-gen文件,引入greenDAO第三方jar包
sourceSets {
java.srcDirs = ['src/main/java', 'src/main/java-gen']
compile 'de.greenrobot:greendao:1.3.7'
3、新建一个greengenerator模块,用于代码自动生成DaoMaster、DaoSession、Table、TableDao实体类
配置新建moudle的build.gradle文件
compile 'de.greenrobot:greendao-generator:1.3.1'
至此,greenDAO的环境配置就完成了。
二、利用greedgenerater模块生成DaoMaster、DaoSession、Table、TableDao实体类的代码,编写moudle下的MyClass类
import de.greenrobot.daogenerator.DaoG
import de.greenrobot.daogenerator.E
import de.greenrobot.daogenerator.S
public class MyClass {
public static void main(String[] args) throws Exception {
// 正如你所见的,你创建了一个用于添加实体(Entity)的模式(Schema)对象。
// 两个参数分别代表:数据库版本号与自动生成代码的包路径。
Schema schema = new Schema(1, &test.greendao&);
当然,如果你愿意,你也可以分别指定生成的 Bean 与 DAO 类所在的目录,只要如下所示:
Schema schema = new Schema(1, &test.greendao.bean&);
schema.setDefaultJavaPackageDao(&test.greendao.dao&);
// 模式(Schema)同时也拥有两个默认的 flags,分别用来标示 entity 是否是 activie 以及是否使用 keep sections。
// schema2.enableActiveEntitiesByDefault();
// schema2.enableKeepSectionsByDefault();
// 一旦你拥有了一个 Schema 对象后,你便可以使用它添加实体(Entities)了。
addNote(schema);
// 最后我们将使用 DAOGenerator 类的 generateAll() 方法自动生成代码,此处你需要根据自己的情况更改输出目录(既之前创建的 java-gen)。
// 其实,输出目录的路径可以在 build.gradle 中设置,有兴趣的朋友可以自行搜索,这里就不再详解。
new DaoGenerator().generateAll(schema, &/Users/licheng/Documents/Healthdoctor/app/src/main/java-gen&);
* @param schema
private static void addNote(Schema schema) {
// 一个实体(类)就关联到数据库中的一张表,此处表名为「Note」(既类名)
Entity note = schema.addEntity(&TestTable&);
// 你也可以重新给表命名
// note.setTableName(&NODE&);
// greenDAO 会自动根据实体类的属性值来创建表字段,并赋予默认值
// 接下来你便可以设置表中的字段:
note.addIdProperty();
note.addStringProperty(&aa&);
// 与在 Java 中使用驼峰命名法不同,默认数据库中的命名是使用大写和下划线来分割单词的。
// For example, a property called “creationDate” will become a database column “CREATION_DATE”.
note.addIntProperty(&bb&);
note.addIntProperty(&cc&);
note.addIntProperty(&dd&);
note.addIntProperty(&ee&);
如果运行结果打印如下,说明配置成功并且实体类生成成功
三、greenDAO代码全局配置
1、DaoMaster、DaoSession配置
一个APP项目,一般不只一个数据库,一个数据库里也不只一个表,如果有多个表的情况,按照上面的配置,会发现每生成一个实体类表,除了Table和TableDao类外,都会有一个DaoMaster和DaoSession生成,这时候我们就可以配置DaoMaster和DaoSession类了,一个类管理多张表。
我们可以再生成一个实体类表,表名为TestAnOtherTable,这样,一个数据库下就有了2个表。
配置DaoMaster类
package test.
import android.content.C
import android.database.sqlite.SQLiteD
import android.database.sqlite.SQLiteDatabase.CursorF
import android.database.sqlite.SQLiteOpenH
import android.util.L
import de.greenrobot.dao.AbstractDaoM
import de.greenrobot.dao.identityscope.IdentityScopeT
import test.greendao.TestAnOtherTableD
// THIS CODE IS GENERATED BY greenDAO, DO NOT EDIT.
* Master of DAO (schema version 1): knows all DAOs.
public class DaoMaster extends AbstractDaoMaster {
public static final int SCHEMA_VERSION = 1;
/** Creates underlying database table using DAOs. */
public static void createAllTables(SQLiteDatabase db, boolean ifNotExists) {
TestAnOtherTableDao.createTable(db, ifNotExists);
TestTableDao.createTable(db, ifNotExists);
/** Drops underlying database table using DAOs. */
public static void dropAllTables(SQLiteDatabase db, boolean ifExists) {
TestAnOtherTableDao.dropTable(db, ifExists);
TestTableDao.dropTable(db, ifExists);
public static abstract class OpenHelper extends SQLiteOpenHelper {
public OpenHelper(Context context, String name, CursorFactory factory) {
super(context, name, factory, SCHEMA_VERSION);
public void onCreate(SQLiteDatabase db) {
Log.i(&greenDAO&, &Creating tables for schema version & + SCHEMA_VERSION);
createAllTables(db, false);
/** WARNING: Drops all table on Upgrade! Use only during development. */
public static class DevOpenHelper extends OpenHelper {
public DevOpenHelper(Context context, String name, CursorFactory factory) {
super(context, name, factory);
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
Log.i(&greenDAO&, &Upgrading schema from version & + oldVersion + & to & + newVersion + & by dropping all tables&);
dropAllTables(db, true);
onCreate(db);
public DaoMaster(SQLiteDatabase db) {
super(db, SCHEMA_VERSION);
registerDaoClass(TestAnOtherTableDao.class);
registerDaoClass(TestTableDao.class);
public DaoSession newSession() {
return new DaoSession(db, IdentityScopeType.Session, daoConfigMap);
public DaoSession newSession(IdentityScopeType type) {
return new DaoSession(db, type, daoConfigMap);
配置DaoSession类
package test.
import android.database.sqlite.SQLiteD
import java.util.M
import de.greenrobot.dao.AbstractD
import de.greenrobot.dao.AbstractDaoS
import de.greenrobot.dao.identityscope.IdentityScopeT
import de.greenrobot.dao.internal.DaoC
import test.greendao.TestAnOtherT
import test.greendao.TestAnOtherTableD
// THIS CODE IS GENERATED BY greenDAO, DO NOT EDIT.
* {@inheritDoc}
* @see de.greenrobot.dao.AbstractDaoSession
public class DaoSession extends AbstractDaoSession {
private final DaoConfig testAnOtherTableDaoC
private final DaoConfig testTableDaoC
private final TestAnOtherTableDao testAnOtherTableD
private final TestTableDao testTableD
public DaoSession(SQLiteDatabase db, IdentityScopeType type, Map&Class&? extends AbstractDao&?, ?&&, DaoConfig&
daoConfigMap) {
super(db);
testAnOtherTableDaoConfig = daoConfigMap.get(TestAnOtherTableDao.class).clone();
testAnOtherTableDaoConfig.initIdentityScope(type);
testTableDaoConfig = daoConfigMap.get(TestTable.class).clone();
testTableDaoConfig.initIdentityScope(type);
testAnOtherTableDao = new TestAnOtherTableDao(testAnOtherTableDaoConfig, this);
testTableDao = new TestTableDao(testTableDaoConfig, this);
registerDao(TestAnOtherTable.class, testAnOtherTableDao);
registerDao(TestTable.class, testTableDao);
public void clear() {
testAnOtherTableDaoConfig.getIdentityScope().clear();
testTableDaoConfig.getIdentityScope().clear();
public TestAnOtherTableDao getTestAnOtherTableDao() {
return testAnOtherTableD
public TestTableDao getTestTableDao() {
return testTableD
这样,2个表就可以通过一个DaoMaster和DaoSession管理了。
2、greenDAO Application配置
greedDAO官方建议,DaoSession最好配置在Application里。
我们新建一个GreenDaoUtils类,用来新建数据库以及管理所有数据库表。
public class GreenDaoUtils {
* 创建数据库连接
* @param context
public static DaoSession createDB(Context context) {
DaoMaster.DevOpenHelper helper = new DaoMaster.DevOpenHelper(context,
TableNameEntity.DB_NAME, null);
return new DaoMaster(helper.getWritableDatabase()).newSession();
* 给TestTable表插入数据
* @param testTable
* @param daoSession
public static void addTestTableInfo(TestTable testTable, DaoSession daoSession){
daoSession.getTestTableDao().insert(testTable);
* 获取TestTable表所有数据
* @param daoSession
public static List&?& getTestTableInfoList(DaoSession daoSession){
QueryBuilder&TestTable& queryBuilder = daoSession.getTestTableDao()
.queryBuilder().orderAsc(TestTableDao.Properties.Id);
if(!ListUtils.isEmpty(queryBuilder.list())){
return queryBuilder.list();
public class HealthApplication extends Application {
private GreenDaoUtils mGreenDaoU
private DaoSession mDaoS
private static HealthA
public static HealthApplication getInstance(){
public void onCreate() {
super.onCreate();
instance =
//greenDao数据库
initGreenDao();
/** greenDao数据库框架初始化 **/
private void initGreenDao() {
mGreenDaoUtils = new GreenDaoUtils();
mDaoSession = mGreenDaoUtils.createDB(this);
public DaoSession getmDaoSession() {
return mDaoS
在代码中调用
DaoSession mDaoSession = HealthApplication.getInstance().getmDaoSession();
TestTable testTable = new TestTable();
testTable.setAa(&aa&);
testTable.setBb(11);
testTable.setCc(22);
testTable.setFf(44);
GreenDaoUtils.addTestTableInfo(testTable, mDaoSession);
这样,我们就通过上面代码向TestTable数据库表中插入了一条数据。关于greenDAO的sql语句语法,可以自行查找资料,这里就不再多述。
三、greedDAO数据库的升级
新建一个MigrationHelper类
import android.database.C
import android.database.sqlite.SQLiteD
import android.text.TextU
import android.util.L
import java.util.ArrayL
import java.util.A
import java.util.L
import de.greenrobot.dao.AbstractD
import de.greenrobot.dao.internal.DaoC
public class MigrationHelper {
private static final String CONVERSION_CLASS_NOT_FOUND_EXCEPTION =
&MIGRATION HELPER - CLASS DOESN'T MATCH WITH THE CURRENT PARAMETERS&;
private static MigrationH
public static MigrationHelper getInstance() {
if (instance == null) {
instance = new MigrationHelper();
public void migrate(SQLiteDatabase db, Class&? extends AbstractDao&?, ?&&... daoClasses) {
generateTempTables(db, daoClasses);
DaoMaster.dropAllTables(db, true);
DaoMaster.createAllTables(db, false);
restoreData(db, daoClasses);
private void generateTempTables(SQLiteDatabase db, Class&? extends AbstractDao&?, ?&&... daoClasses) {
for (int i = 0; i & daoClasses. i++) {
DaoConfig daoConfig = new DaoConfig(db, daoClasses[i]);
String divider = &&;
String tableName = daoConfig.
String tempTableName = daoConfig.tablename.concat(&_TEMP&);
ArrayList&String& properties = new ArrayList&&();
StringBuilder createTableStringBuilder = new StringBuilder();
createTableStringBuilder.append(&CREATE TABLE &).append(tempTableName).append(& (&);
for (int j = 0; j & daoConfig.properties. j++) {
String columnName = daoConfig.properties[j].columnN
if (getColumns(db, tableName).contains(columnName)) {
properties.add(columnName);
String type =
type = getTypeByClass(daoConfig.properties[j].type);
} catch (Exception exception) {
createTableStringBuilder.append(divider).append(columnName).append(& &).append(type);
if (daoConfig.properties[j].primaryKey) {
createTableStringBuilder.append(& PRIMARY KEY&);
divider = &,&;
createTableStringBuilder.append(&);&);
db.execSQL(createTableStringBuilder.toString());
StringBuilder insertTableStringBuilder = new StringBuilder();
insertTableStringBuilder.append(&INSERT INTO &).append(tempTableName).append(& (&);
insertTableStringBuilder.append(TextUtils.join(&,&, properties));
insertTableStringBuilder.append(&) SELECT &);
insertTableStringBuilder.append(TextUtils.join(&,&, properties));
insertTableStringBuilder.append(& FROM &).append(tableName).append(&;&);
db.execSQL(insertTableStringBuilder.toString());
private void restoreData(SQLiteDatabase db, Class&? extends AbstractDao&?, ?&&... daoClasses) {
for (int i = 0; i & daoClasses. i++) {
DaoConfig daoConfig = new DaoConfig(db, daoClasses[i]);
String tableName = daoConfig.
String tempTableName = daoConfig.tablename.concat(&_TEMP&);
ArrayList&String& properties = new ArrayList();
for (int j = 0; j & daoConfig.properties. j++) {
String columnName = daoConfig.properties[j].columnN
if (getColumns(db, tempTableName).contains(columnName)) {
properties.add(columnName);
StringBuilder insertTableStringBuilder = new StringBuilder();
insertTableStringBuilder.append(&INSERT INTO &).append(tableName).append(& (&);
insertTableStringBuilder.append(TextUtils.join(&,&, properties));
insertTableStringBuilder.append(&) SELECT &);
insertTableStringBuilder.append(TextUtils.join(&,&, properties));
insertTableStringBuilder.append(& FROM &).append(tempTableName).append(&;&);
StringBuilder dropTableStringBuilder = new StringBuilder();
dropTableStringBuilder.append(&DROP TABLE &).append(tempTableName);
db.execSQL(insertTableStringBuilder.toString());
db.execSQL(dropTableStringBuilder.toString());
private String getTypeByClass(Class&?& type) throws Exception {
if (type.equals(String.class)) {
return &TEXT&;
if (type.equals(Long.class) || type.equals(Integer.class) || type.equals(long.class)) {
return &INTEGER&;
if (type.equals(Boolean.class)) {
return &BOOLEAN&;
Exception exception =
new Exception(CONVERSION_CLASS_NOT_FOUND_EXCEPTION.concat(& - Class: &).concat(type.toString()));
private static List&String& getColumns(SQLiteDatabase db, String tableName) {
List&String& columns = new ArrayList&&();
Cursor cursor =
cursor = db.rawQuery(&SELECT * FROM & + tableName + & limit 1&, null);
if (cursor != null) {
columns = new ArrayList&&(Arrays.asList(cursor.getColumnNames()));
} catch (Exception e) {
Log.v(tableName, e.getMessage(), e);
e.printStackTrace();
} finally {
if (cursor != null) cursor.close();
配置DaoMaster中的DevOpenHelper
/** WARNING: Drops all table on Upgrade! Use only during development. */
public static class DevOpenHelper extends OpenHelper {
public DevOpenHelper(Context context, String name, CursorFactory factory) {
super(context, name, factory);
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
Log.i(&greenDAO&, &Upgrading schema from version & + oldVersion + & to & + newVersion + & by dropping all tables&);
dropAllTables(db, true);
onCreate(db);
MigrationHelper.getInstance().migrate(db, TestTable.class);
MigrationHelper.getInstance().migrate(db, TestAnOtherTable.class);
注意,onUpgrade方法,只有在数据库版本号更改后才会执行,数据库版本号在正式包环境中只能向上兼容,也就是版本号的值不能小于上个数据库的版本号。
public static final int SCHEMA_VERSION = 1;
每次改动数据库,该值需要更改。
如果数据库表字段有更新、或添加删除字段,或数据库有增删表,利用generater模块类重新生成实体类表,然后更改数据库版本号,就可以实现数据库的更新。403 Forbidden
Request forbidden by administrative rules.当前位置: >
> Anddroid App和Java Web服务器间数据交互 之MySQL搭建
Anddroid App和Java Web服务器间数据交互 之MySQL搭建
时间:作者:华清远见
当前各种App软件如滴滴打车、百度外卖、淘宝、京东满足了人们日常生活的衣食住行,那么这些App是怎么实现相关功能的?App从哪里获取的数据,又将用户输入的数据提交到哪里?我们先看看实现该功能由几部分组成。
第一部分 数据库,将与用户相关的据存储到数据库中。例如,在注册时用户名、密码以及自己的交易信息等都需要保存到数据库中,在下次登录或查找相关信息时能够找到并显示。本文举例采用开源MySQL数据库;
第二部分 应用服务器,负责接收App端发来的数据和请求。主要功能是当接收数据后存储到数据库中进行持久化;当接收到请求时,将用户所需数据返回给App进行显示。本文采用Java Web应用服务器,开发工具MyEclipse,采用Tomcat服务器。
第三部分 App程序,就是我们手机端安装的各种App软件,如百度外卖、淘宝、京东等程序。本文采用的Android系统App,开发工具eclipse。
我们可以实现一个Android App程序,完成用户名和密码的注册功能。将Android App输入的用户名和密码发送给Java Web应用服务器,Java Web应用服务器收到数据后,将数据存储到MySQL数据库中,并将存储的结果返回给Android App程序进行显示。下面我们详细演示各个步骤:
(一) 数据库。安装MySQL数据库,执行建表语句,添加数据。
本文安装mysql 5.5版本(安装软件mysql-5.5.28-winx64.msi,本文不再细述安装过程),安装后启动MySQL5.5 Command Line Client,输入安装时密码,进入到mysql控制台,如下图所示:
1) 创建数据库。在mysql后面输入下列命令:
2) 使用刚刚创建的数据库,输入下列命令:
3) 创建user表,由于第二步使用了apptest数据库,那么user表将在apptest数据库中创建。输入建表命令如下:
create table user(id integer primary key auto_increment,
name varchar(20),
pwd varchar(10));
4) 向表中添加数据。输入如下命令:
insert into user(name,pwd) values('violet','123');
5) 查询表中数据。输入如下命令:
所有操作如下图所示:
至此,我们MySQL数据库表已经创建完毕。
学院最新动态Android数据持久化存储
数据持久化存储共有四种方式,分别是文件存储、SharedPreferences、Sqlite和ContentProvider。在本篇幅中只介绍前面三种存储方式,因为ContentProvider属于android四大之一,所以它的数据存储方式在介绍四大组件的时候说明。
1、文件存储
文件存储不对存储的内容进行任何的格式化处理,所有数据都是原封不动地保存到文件当中的,因而它比较适合用于存储一些简单的文本数据或二进制数据。
文件存储有两种方式,一是存储到手机内存中(memory),一是存储到sd卡中。
1.1、存储到手机内存中
1)将数据存储到文件中
Context类中提供了一个openFileOutput()方法,可以用于将数据存储到指定的文件中。
方法介绍:
openFileOutput(name,mode):
name:是文件名,注意这里指定的文件名不可以包含路径,因为所有的文件都是默认存储到/data/data//files/(等价于getFilesDir())目录下的
mode:是文件的操作模式,
MODE_PRIVATE:默认的操作模式,同名文件内容会被覆盖。
MODE_APPEND则表示如果该文件已存在就往文件里面追加内容,不存在就创建新文件。
还有另外两种(android4.2被废弃),MODE_WORLD_READABLE和MODE_WORLD_WRITEABLE,这两种模式表示允许其他的应用程序对我们程序中的文件进行读写操作。
openFileOutput()方法返回的是一个FileOutputStream对象,得到了这个对象之后就可以使用流的方式将数据写入到文件中了。
publicvoidsave(){
Stringdata=&Datatosave&;
FileOutputStreamout=
BufferedWriterwriter=
out=openFileOutput(&data&,Context.MODE_PRIVATE);
writer=newBufferedWriter(newOutputStreamWriter(out));
writer.write(data);
}catch(IOExceptione){
e.printStackTrace();
if(writer!=null){
writer.close();
}catch(IOExceptione){}
以上代码就是将将一段文本内容保存到文件中。
完成将数据存储到文件中,接下来如何从文件中读取数据呢?
2)从文件中读取数据
Context类中还提供了一个openFileInput()方法,用于从文件中读取数据。
这个方法只接收一个参数,即要读取的文件名,使用openFileInput(&filename&)读取存放在/data/data//files目录应用私有的文件。该方法返回一个FileInputStream对象,得到了这个对象之后再通过Java流的方式就可以将数据读取出来了。
publicStringload(){
FileInputStreamin=
BufferedReaderreader=
StringBuildercontent=newStringBuilder();
in=openFileInput(&data&);
reader=newBufferedReader(newInputStreamReader(in));
Stringline=&&;
while((line=reader.readLine())!=null){
content.append(line);
}catch(IOExceptione){
e.printStackTrace();
if(reader!=null){
reader.close();
}catch(IOExceptione){
e.printStackTrace();
returncontent.toString();
1.2、存储到sd卡中
前面说了file储存,数据是存储在应用程序内的,文件大小受到限制;当要存储大的文件时,就要使用sd卡方式存储了。使用sd卡存储主要是使用Environment这个类的功能。
1)将数据存储到sd卡中
Environment类介绍:
①常用常量:
StringMEDIA_MOUNTED:外部存储器可读可写
MEDIA_MOUNTED_READ_ONLY:外部存储器只读
②常用方法:
getExternalStorageDirectory():获取SDCard的目录,/mnt/sdcard
getExternalStorageState():获取外部存储器的当前状态
通过简单价绍Environment类的使用,接下来就是sd卡读写数据了。以下是往sd卡读写数据的步骤:
1)判断sd卡的状态
2)获取存储器的目录,即sd卡的目录
3)使用IO流对sd卡进行文件的读写操作
4)在清单文件中添加权限
写入数据到sd卡中代码如下:
publicvoidwrite2Sd(){
if(Environment.getExternalStorageState().equals(
Environment.MEDIA_MOUNTED)){
Stringcontent=edtContent.getText().toString();
//获取SDcard路径
FilesdCardDir=Environment
.getExternalStorageDirectory();
//SDCard目录:/mnt/sdcard
StringsdcardPath=sdCardDir.getAbsolutePath();
Filefile=newFile(sdCardDir,FILE_NAME);
//Filefile=newFile(sdcardPath
//+File.separator+FILE_NAME);
//以指定文件创建RandomAccessFile对象
RandomAccessFileraf=newRandomAccessFile(file,&rw&);
//将文件记录指针移动最后
raf.seek(file.length());
//输出文件内容
raf.write(content.getBytes());
raf.close();
}catch(Exceptione){
//TODO:handleexception
以上代码可知,往sd卡中写数据先调用getExternalStorageState()判断sd卡状态,接着获取sd卡的存储路径,以路径很文件名创建文件,最后使用RandomAccessFile类存储数据,使用该类的好处是可以定位的指定位置进行读写数据。
2)从sd卡中读取数据
publicvoidreadFromSd(){
if(Environment.getExternalStorageState().equals(
Environment.MEDIA_MOUNTED)){
//获取SDcard路径
StringBuildersb=newStringBuilder();
FilesdCardDir=Environment
.getExternalStorageDirectory();
Filefile=newFile(sdCardDir,FILE_NAME);
InputStreaminputStream=newFileInputStream(file);
byte[]buffer=newbyte[1024];
while((len=inputStream.read(buffer))!=-1){
sb.append(newString(buffer,0,len));
tvResult.setText(sb.toString());
inputStream.close();
}catch(Exceptione){
//TODOAuto-generatedcatchblock
e.printStackTrace();
2、SharedPreferences存储
2.1、将数据存储到sp中
SharedPreferences类,它是一个轻量级的存储类,适合用于保存软件配置参数。SharedPreferences是使用键值对的方式来存储数据的,存储数据是以xml文件形式存储,文件存放在/data/data//shared_prefs目录下。
1)获取SharedPreferences对象。
要想使用sp来存储数据,首先需要获取到sp对象。Android中主要提供了三种方法用于得到sp对象。
1、Context类中的getSharedPreferences(name,mode)方法
Name:用于指定SharedPreferences文件的名称
mode指定操作模式,和文件存储模式一样。
2、Activity类中的getPreferences(mode)方法
使用这个方法时会自动将当前活动的类名作为SharedPreferences的文件名。
3.PreferenceManager类中的getDefaultSharedPreferences(context)方法 这是一个静态方法,使用当前应用程序的包名作为前缀名来命名文件。
2)调用sp对象的edit()方法来获取一个SharedPreferences.Editor对象。
3)向SharedPreferences.Editor对象中添加数据。比如添加一个布尔型数据就使用putBoolean方法,添加一个字符串则使用putString()方法,以此类推。
4)调用commit()方法将添加的数据提交,从而完成数据存储操作
2.2、从sp中读取数据
1)获取SharedPreferences对象。
2)然后分别调用它的geXxx()方法获取存储的值。如getString()、getInt()和getBoolean(),没有找到相应的值就会使用方法中传入的默认值来代替
3、Sqlite数据库存储
SQLite是一款轻量级的关系型数据库,它的运算速度非常快,占用资源很少,通常只需要几百K的内存就足够了。SQLite不仅支持标准的SQL语法,还遵循了数据库的ACID事务。
Android提供了一个SQLiteOpenHelper帮助类,借助这个类就可以非常简单地对数据库进行创建和升级。
SQLiteOpenHelper是一个抽象类,有两个抽象方法,分别是onCreate()和onUpgrade(),分别在这两个方法中去实现创建、升级数据库的逻辑。SQLiteOpenHelper中还有两个实例方法,getReadableDatabase()和getWritableDatabase()。这两个方法都可以创建或打开一个现有的数据库(如果数据库已存在则直接打开,否则创建一个新的数据库),并返回一个可对数据库进行读写操作的对象。
3.1、创建数据库
因为SQLiteOpenHelper是一个抽象类,创建数据库的时候可以创建一个类继承SQLiteOpenHelper,并重写其两个抽象方法。新建MyDatabaseHelper类继承自SQLiteOpenHelper,代码如下所示:
publicclassMyDatabaseHelperextendsSQLiteOpenHelper{
publicstaticfinalStringCREATE_BOOK=&createtablebook(&
+&idintegerprimarykeyautoincrement,&
+&authortext,&
+&pricereal,&
+&pagesinteger,nametext)&;
privateContextmC
publicMyDatabaseHelper(Contextcontext,Stringname,
CursorFactoryfactory,intversion){
super(context,name,factory,version);
publicvoidonCreate(SQLiteDatabasedb){
db.execSQL(CREATE_BOOK);
Toast.makeText(mContext,&Createsucceeded&,Toast.LENGTH_SHORT).show();
publicvoidonUpgrade(SQLiteDatabasedb,intoldVersion,intnewVersion){
如上所示,先把建表语句写成字符串常量,在onCreate()方法中调用SQLiteDatabase的execSQL()方法去执行这条建表语句,以保证数据库创建的同时也成功的创建Book表。
然后再布局文件加入了一个id是.create_database的Button按钮,用于创建数据库。最后修改MainActivity中的代码,如下所示:
publicclassMainActivityextendsActivity{
privateMyDatabaseHelperdbH
protectedvoidonCreate(BundlesavedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
dbHelper=newMyDatabaseHelper(this,&BookStore.db&,null,1);
ButtoncreateDatabase=(Button)findViewById(R.id.create_database);
createDatabase.setOnClickListener(newOnClickListener(){
publicvoidonClick(Viewv){
dbHelper.getWritableDatabase();
如上所示,在onCreate()方法中构建了一个MyDatabaseHelper对象,并且通过构造函数的参数将数据库名指定为BookStore.db,版本号指定为1,然后在Createdatabase按钮的点击事件里调用了getWritableDatabase()方法。这样当第一次点击按钮时,就会检测到当前程序中并没有BookStore.db这个数据库,于是会创建该数据库并调用MyDatabaseHelper中的onCreate()方法同时也创建Book表。
3.2、升级数据库
MyDatabaseHelper中的onUpgrade()方法是用于对数据库进行升级的。
接着我们再添加一张Category表用于记录书籍的分类,修改MyDatabaseHelper代码如下:
publicclassMyDatabaseHelperextendsSQLiteOpenHelper{
publicstaticfinalStringCREATE_CATEGORY=&createtableCategory(&
+&idintegerprimarykeyautoincrement,&
+&category_nametext,&
+&category_codeinteger)&;
publicvoidonCreate(SQLiteDatabasedb){
db.execSQL(CREATE_BOOK);
db.execSQL(CREATE_CATEGORY);
publicvoidonUpgrade(SQLiteDatabasedb,intoldVersion,intnewVersion){
switch(oldVersion){
db.execSQL(CREATE_CATEGORY);
db.execSQL(&altertableBookaddcolumncategory_idinteger&);
可以看到,这里在onUpgrade()方法中加入了一个switch判断,如果oldVersion等于1,就再创建一个CATEGORY表。接着只需要在创建MyDatabaseHelper时构造函数第四个参数改成大于1的整数即可。
紧接着,发现CATEGORY表少添加了category_id列,为了保留原有数据库的数据,只需在添加一个case语句,使用alter..add添加该列就行,注意case之间没有break。使用这种方式升级数据库就不会导致表中的数据丢失问题。
3.3、数据库的CRUD操作
数据库的crud其中C代表添加(Create),R代表查询(Retrieve),U代表更新(Update),D代表删除(Delete)。每一种操作又各自对应了一种SQL命令。
调用SQLiteOpenHelper的getReadableDatabase()或getWritableDatabase()
方法是可以用于创建和升级数据库的,这两个方法还都会返回一个SQLiteDatabase对象,借助这个对象就可以对数据进行CRUD操作。
1)C数据库的add操作
SQLiteDatabase中的insert(table,nullColumnHack,values)方法
Table:表名
nullColumnHack:通常用不到,直接传null。
Value:ContentValue,是map集合,表示待添加的数据。
publicvoidadd(){
SQLiteDatabasedb=dbHelper.getWritableDatabase();
ContentValuesvalues=newContentValues();//开始组装第一条数据
values.put(&name&,&TheDaVinciCode&);
values.put(&author&,&DanBrown&);
values.put(&pages&,454);
values.put(&price&,16.96);
db.insert(&Book&,null,values);
2)R数据库的query操作
SQLiteDatabase中的query(table,columns,selection,selectionArgs,groupBy,having,orderBy)方法:
table,表名
columns,指定去查询哪几列
selection,selectionArgs,指定约束条件和占位符,表示查询哪几行
groupBy,对查询结果进行groupby操作
having,对groupBy后的数据进行进一步过滤
orderBy,对查询的结果进行排序
publicvoidquery(){
SQLiteDatabasedb=dbHelper.getWritableDatabase();
//查询Book表中所有的数据
Cursorcursor=db.query(&Book&,null,null,null,null,null,null);
if(cursor.moveToFirst()){
//遍历Cursor对象
Stringname=cursor.getString(cursor.getColumnIndex(&name&));
Stringauthor=cursor.getString(cursor
.getColumnIndex(&author&));
intpages=cursor.getInt(cursor.getColumnIndex(&pages&));
doubleprice=cursor.getDouble(cursor.getColumnIndex(&price&));
}while(cursor.moveToNext());
cursor.close();
3)U数据库的update操作
SQLiteDatabase中的update(table,values,whereClause,whereArgs)方法
Table:表名
Value:ContentValue,是map集合。
whereClause、whereArgs:指定第三和第四个参数用于指定修改哪些行
publicvoidupdate(){
SQLiteDatabasedb=dbHelper.getWritableDatabase();
ContentValuesvalues=newContentValues();
values.put(&price&,10.99);
db.update(&Book&,values,&name=?&,
newString[]{&xiaoming&});
4)D数据库的delete操作
SQLiteDatabase中的delete(table,whereClause,whereArgs)
table,表名
whereClause,whereArgs:指定要删除哪些行,对应sql语句的where部分。
publicvoiddelete(){
SQLiteDatabasedb=dbHelper.getWritableDatabase();
db.delete(&Book&,&pages&?&,newString[]{&500&});
3.4、使用SQL操作数据库
Android中支持使用原生的sql语句执行数据库的增删改查操作。具体如下:
添加数据的方法如下:
db.execSQL(&insertintoBook(name,author,pages,price)values(?,?,?,?)&,newString[]{&TheDaVinciCode&,&DanBrown&,&454&,&16.96&});
更新数据的方法如下:
db.execSQL(&updateBooksetprice=?wherename=?&,newString[]{&10.99&,&TheDaVinciCode&});
删除数据的方法如下:
db.execSQL(&deletefromBookwherepages&?&,newString[]{&500&});
查询数据的方法如下:
db.rawQuery(&select*fromBook&,null);
3.5、使用LitePal框架完成Android数据库的存储
使用SQLiteOpenHelper有一个弊端,就是如果数据库中某一列已经没有用了,我想把这一列删除,使用SQLite是无法实现删除某一列的(开发中多是忽视它,反正以后也用不到,留着也占用不了多少空间),另外就是如果表之间存在关联关系,建表语句就会变得很复杂,因此使用LitePal来自动建立表关联又是一个非常不错的选择,我们不需要关心什么外键、中间表等实现的细节,只需要在对象中声明好它们相互之间的引用关系,LitePal就会自动在数据库表之间建立好相应的关联关系了。
注:虽然使用Litepal框架可以轻松实习表的关联,但表的关联知识了解下还是有必要的。多表设计数据库口诀:
一对一关联的实现方式是用外键,多对一关联的实现方式也是用外键(外键必须加载多方),多对多关联的实现方式是用中间表。
LitePal开源项目地址:

我要回帖

更多关于 app开发用什么数据库 的文章

 

随机推荐