一、数据库的创建

1.文件的创建

     //引用,如果文件不存在是不会创建的

  File  file = new File("haha.txt");

    //输出流写数据,文件才会被创建

  FileOutputStream  fos = new FileOutputStream(file);

  fos.write("".getBytes());

  fos.close();

2.数据库的创建

//执行下面这一点代码,数据库是不会被创建出来的。相当于File file = new File("one.txt");(文件one.txt也没有创建出来)

        MyDBOpenHelper helper = new MyDBOpenHelper(this);

//如果要想创建数据库就必须执行下面的代码

       helper.getWritableDatabase();

创建文件我们需要一个File类,创建数据库我们也需要一个特殊的类SQLiteOpenHelper(抽象类)

(1)我创建一个新的Android工程如下:

(2)我们找到SQLiteOpenHelper,发现这是一个抽象类,所以我们必须自定义一个SQLiteOpenHelper的子类实现类:MyDBOpenHelper

代码如下:

 package com.himi.sqlite;

 import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteOpenHelper; public class MyDBOpenHelper extends SQLiteOpenHelper { public MyDBOpenHelper(Context context, String name, CursorFactory factory,
int version) {
super(context, name, factory, version);
// TODO 自动生成的构造函数存根
} @Override
public void onCreate(SQLiteDatabase db) {
// TODO 自动生成的方法存根 } @Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// TODO 自动生成的方法存根 } }

这里我们发现这个构造方法参数很多,很晕,这个我们慢慢仔细看看这个构造函数,如下:

public MyDBOpenHelper(Context context, String name, CursorFactory factory,int version)

 context:上下文,用来打开或者创建数据库

  name:数据库文件的名称

  factory:用来创建游标对象,null就是使用默认的游标工厂

这个游标是什么概念?不懂啊?没事我们这里就说明一下这个概念,要知道这个概念必然是解决问题思路抽取出来的,为解决问题而服务,只是我们不知道这个内在解决问题的思路,才会这样迷糊,没事,很快就好了。

下面这个逻辑图就会让你明白:

version:从数字1开始的一个版本号,用来数据库更新使用

(3)上面已经知道构造函数的4个参数,一次性传入4个参数(context, name, factory, version)太过繁琐,这里修改只传入context。

package com.himi.sqlite;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper; /**
* 相当于File类
* @author Administrator
*
*/
public class MyDBOpenHelper extends SQLiteOpenHelper { public MyDBOpenHelper(Context context) {
super(context, "Juck.db", null, 1);
// TODO 自动生成的构造函数存根
} @Override
public void onCreate(SQLiteDatabase db) {
// TODO 自动生成的方法存根 } @Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// TODO 自动生成的方法存根 } }

这时候我们已经创建出来了数据库工具类MyDBOpenHelper,接下来我们就可以在MainActivity中创建数据库,代码如下:

package com.himi.sqlite;

import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem; public class MainActivity extends Activity { @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main); //执行下面这一点代码,数据库是不会被创建出来的。相当于File file = new File("one.txt");(文件one.txt也没有创建出来)
MyDBOpenHelper helper = new MyDBOpenHelper(this);
//如果要想创建数据库就必须执行下面的代码
helper.getWritableDatabase();
} }

程序运行到手机上,我们在/data/data/com.himi.sqlite/databases目录下查找已经创建的数据库Juck.db,如下:

二、数据库的表创建

    1.之前的MyDBOpenHelper继承SQLiteOpenHelper实现的抽象方法onCreate(), 数据库第一次创建的时候调用,如果数据库已经创建,就不会执行这个onCreate()方法,在onCreate()方法中我们往往执行创建表的操作:create table

    public void onCreate(SQLiteDatabase db)

  2.当数据库的版本需要更新的时候调用的方法:

    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)  

  这里我们知道我们在刚刚利用构造函数创建数据库的时候:

public MyDBOpenHelper(Context context) {
super(context, "itheima.db", null, 1);
}

这里的默认数据库的版本号为version = 1,当我们修改版本号为version = 2,也就是说构造方法修改为如下:

public MyDBOpenHelper(Context context) {
super(context, "itheima.db", null, 2);
}

这就是说明数据库的版本由1升级到2,这样的话就会调用onUpgrade方法,顺便说一句数据库版本号只能升级,不能降级

比如:起初我们创建的数据库版本为version = 1,如下代码:

package com.himi.sqlite;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper; /**
* 相当于File类
* @author Administrator
*
*/
public class MyDBOpenHelper extends SQLiteOpenHelper { public MyDBOpenHelper(Context context) {
super(context, "Juck.db", null, 1);
// TODO 自动生成的构造函数存根
} /**
* 数据库第一次创建的时候调用,如果数据库已经创建,就不会执行这段代码
* @param db 代表的就是我们创建出来的数据库
*/
@Override
public void onCreate(SQLiteDatabase db) {
//创建表
db.execSQL("create table info (_id integer primary key autoincrement, name varchar(20), phone varchar(20))"); } @Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
// TODO 自动生成的方法存根 } }

当我们想添加数据库info一个字段为money varchar(10),代码如下:

package com.himi.sqlite;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper; /**
* 相当于File类
* @author Administrator
*
*/
public class MyDBOpenHelper extends SQLiteOpenHelper { public MyDBOpenHelper(Context context) {
super(context, "Juck.db", null, 2); // 为了满足升级的需求,这里已经修改了版本号,由1修改为2
// TODO 自动生成的构造函数存根
} /**
* 数据库第一次创建的时候调用,如果数据库已经创建,就不会执行这段代码
* @param db 代表的就是我们创建出来的数据库
*/
@Override
public void onCreate(SQLiteDatabase db) {
//创建表
db.execSQL("create table info (_id integer primary key autoincrement, name varchar(20), phone varchar(20))"); } @Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("alter table info add money varchar(10)"); //上面修改了版本号,这里就会调用onUpgrade()方法,从而实现添加money字段 } }

三、这样的话,完整的数据库创建和使用的代码我们也将完成了,如下:

MainActivity.java:

 package com.itheima.dbcreate;

 import android.os.Bundle;
import android.app.Activity;
import android.view.Menu; public class MainActivity extends Activity { @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//执行下面的一行代码,数据库是不会别创建的了。
MyDBOpenHelper helper = new MyDBOpenHelper(this);
//如果想创建数据库必须执行,下一行代码
helper.getWritableDatabase();
} }

而且MyDBOpenHelper.java:

 package com.itheima.dbcreate;

 import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteDatabase.CursorFactory;
import android.database.sqlite.SQLiteOpenHelper; /**
* 相当于File类
* @author Administrator
*
*/
public class MyDBOpenHelper extends SQLiteOpenHelper { /**
* @param context 上下文
* @param name 数据库文件的名称
* @param factory 用来创建游标对象, null就用默认的游标工厂
* @param version 数据库的版本号 从1开始
*/
public MyDBOpenHelper(Context context) {
super(context, "itheima.db", null, 1);
} /**
* 数据库第一次被创建的时候调用,如果数据库已经创建,就不会执行这一句代码
* @param db 代表的就是我们创建出来的数据库
*/
@Override
public void onCreate(SQLiteDatabase db) {
System.out.println("哈哈哈,数据库被创建了。适合初始化数据库的表结构");
//创建表
db.execSQL("create table info (_id integer primary key autoincrement, name varchar(20), phone varchar(20)) ");
}
/**
* 当数据库的版本需要更新的时候调用的方法
*/
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
System.out.println("onupgrade 数据库被升级啦 。哈哈哈,适合修改数据库的表结构");
//db.execSQL("alter table info add money varchar(10)"); }
}

四、特别说明:

首先我们通过一张图引出一个问题,如下:

有时候我们会经常处理数据库,这样的话就会出现很多版本的数据库。不同版本的数据库之间如果要升级,必须要做onUpgrade()方法中执行,比如

上面图中:数据库版本1------>数据库版本2,这里只需要在构造方法中修改版本号为2,同时在 onUpgrade()方法中添加字段money即可;同样的道理,数据库版本2------>数据库版本3,这里只需要在构造方法中修改版本号为3,同时在 onUpgrade()方法中添加字段age即可

相信你已经感觉到了,就是我们数据库升级的时候要考虑自己现在的版本(oldVersion)  以及我们要升级的版本(newVersion

所以这里我们要说一下这里:public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)

将来我们去上班的时候,你会发现有的项目做了很久,DBSQLiteHelper中的 onUpgrade()方法代码很复杂,可能都有好几百行,甚至要上千行,如下:

@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
System.out.println("onupgrade 数据库被升级啦 。哈哈哈,适合修改数据库的表结构");
for (int j = oldVersion; j <= newVersion; j++){
switch(j) {
case 1:
........
break;
case 2:
........
break;
case 3:
........
break;
case 4:
........
break;
case 5:
........
break; .
.
. }
}
}

为什么要在方法里写for循环,主要是考虑到夸数据库版本升级,比如有的用户一直不升级版本,数据库版本号一直是1,而客户端最新版本其实对应的数据库版本已经是4了,那么我中途可能对数据库做了很多修改,通过这个for循环,可以迭代升级,不会发生错误。

你会发现onUpgrade()方法中,有很多类似switch……case……  或者 if……else;这些都是因为我们升级项目的时候,更新数据库,这样就会出现很多版本的数据库,用户在升级数据库的时候,这里会根据用户现在的数据库版本oldVersion,执行相应的操作升级到现在数据库版本newVersion。

这样的话,用户升级软件的时候就不会清除你之前的数据,比如升级游戏的时候,之前的游戏登录账号和密码就还会记住,就不会要求用户重新输入,这样的用户体验是很好的

但是往往有些垄断行业,升级软件就不会有这一大堆switch这样的判断,就会出现升级软件账号和密码要重新输入,就是因为它清空我们之前的数据库内容,但是这样的用户体验是很不好的,这只有垄断行业才会采用的,比如QQ升级。

最新文章

  1. Red Gate(SQLToolbelt)SQL Server的安装与注册(破解)
  2. Sublime Text 2 配置
  3. MySQL数据库 安装图解
  4. mean函数
  5. 第二篇 顾问实施ERP与医生看病过程类比
  6. [AngularJS] Test an Angular Component with $componentController
  7. SAX - Hello World
  8. AngularJs--过滤器(filter)
  9. ios快捷键
  10. Object-C类目(Category)
  11. bootstrap datatable项目封装支持单选多选
  12. codeM美团编程大赛初赛B轮D题
  13. Apache Kafka系列(二) 命令行工具(CLI)
  14. python 函数 装饰器 内置函数
  15. 开源库BaseRecyclerViewAdapterHelper
  16. css之图片下方定位遮掩层
  17. 运用SqlSugar框架+Axios写的增删查案例
  18. PRD是什么
  19. 什么是 java.awt.headless
  20. 6-3 二叉树的重建 uva536

热门文章

  1. VLAN间单臂路由访问
  2. 【UVA 11383】 Golden Tiger Claw (KM算法副产物)
  3. 在TMemo上画一条线
  4. 使用Java正则表达式的分组解析身份证的年月日
  5. message 匹配不上grok正则 也会写入到elasticsearch
  6. 【HDOJ】3061 Battle
  7. 【HDOJ】2209 翻纸牌游戏
  8. bzoj2004
  9. 通过Microsoft Azure服务设计网络架构的经验分享
  10. 20个可以帮你简化iOS app开发流程的工具