SQLite详解与数据库分页问题,指定获取多少条数据

Android 为了让我们能够更加方便地管理数据库,专门提供了一个 SQLiteOpenHelper 帮
助类,借助这个类就可以非常简单地对数据库进行创建和升级。既然有好东西可以直接使用,那我们自然要尝试一下了

数据库文件会存放在/data/data/<package name>/databases/目录下

SQLiteOpenHelper类提供了两个重要的方法,分别是onCreate(SQLiteDatabase db)onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion),前者用于初次使用软件时生成数据库表,后者用于升级软件时更新数据库表结构。当调用SQLiteOpenHelper的getWritableDatabase()或者getReadableDatabase()方法获取用于操作数据库的SQLiteDatabase实例的时候,如果数据库不存在,Android系统会自动生成一个数据库,接着调用onCreate()方法,onCreate()方法在初次生成数据库时才会被调用

getWritableDatabase()和getReadableDatabase()方法都可以获取一个用于操作数据库的SQLiteDatabase实例。但getWritableDatabase() 方法以读写方式打开数据库,一旦数据库的磁盘空间满了,数据库就只能读而不能写,倘若使用getWritableDatabase()打开数据库就会出错。getReadableDatabase()方法先以读写方式打开数据库,如果数据库的磁盘空间满了,就会打开失败,当打开失败后会继续尝试以只读方式打开数据库。

注意:getWritableDatabase(),getReadableDatabase的区别是当数据库写满时,调用前者会报错,调用后者不会,所以如果不是更新数据库的话,最好调用后者来获得数据库连接。  

 1 package com.example.my_sqlite;
 2 
 3 import android.content.ContentValues;
 4 import android.content.Context;
 5 import android.database.sqlite.SQLiteDatabase;
 6 import android.database.sqlite.SQLiteDatabase.CursorFactory;
 7 import android.database.sqlite.SQLiteOpenHelper;
 8 
 9 public class MyDatabaseHelper extends SQLiteOpenHelper{
10     //定义创建表的字符串    表:book(id,书名,价格,作者)                                    
11     public static final String CREATE_BOOK="create table book(id integer primary key autoincrement,name text,price real,author text);";
12     /*integer 表示整型, real 表示浮点型,text 表示文本类型,blob 表示二进制类型。另外,上述建表语句中我们还
13         使用了 primary key 将 id 列设为主键,并用 autoincrement关键字表示 id 列是自增长的。
14      */
15     public MyDatabaseHelper(Context context, String name,
16             CursorFactory factory, int version) {
17         super(context, name, factory, version);//必须调用父类构造方法才能去创建数据库,但是执行此方法不会创建数据库
18         System.out.println("构造方法调用--我的数据库帮助类");
19     }
20 
21     //执行getReadableDatabase(),getWritableDatabase()时会调用此方法
22     //也就是创建了数据库对象才会调用此方法  但是:
23     //注意:onCreate()方法在初次生成数据库时才会被调用,在其他地方再次创建MyDatavaseHelper对象也不会执行该方法
24     @Override
25     public void onCreate(SQLiteDatabase db) {
26         System.out.println("调用oncreate");
27         db.execSQL(CREATE_BOOK);//执行创建该表的语句
28         System.out.println("创建了book表");
29     }
30     
31     //onUpgrade()方法在数据库的版本发生变化时会被调用,一般在软件升级时才需改变版本号
32     @Override
33     public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
34         System.out.println("数据库更新时调用此方法");
35         ContentValues values=new ContentValues();
36         values.put("name", "book3");//与表的数据类型一一对应
37         values.put("price", 52.3);
38         values.put("author", "book3_name");
39         db.insert("book", null, values);//插入数据
40     }
41 
42 }

对数据库进行操作的类:

  1 package com.example.my_sqlite;
  2 
  3 import android.app.Activity;
  4 import android.content.ContentValues;
  5 import android.database.Cursor;
  6 import android.database.sqlite.SQLiteDatabase;
  7 import android.os.Bundle;
  8 import android.view.Menu;
  9 import android.view.MenuItem;
 10 import android.view.View;
 11 import android.view.View.OnClickListener;
 12 import android.widget.Button;
 13 
 14 public class MainActivity extends Activity {
 15     public static int version=1;//数据库的版本号
 16     private MyDatabaseHelper myDatabase;
 17     @Override
 18     protected void onCreate(Bundle savedInstanceState) {
 19         super.onCreate(savedInstanceState);
 20         setContentView(R.layout.activity_main);
 21         Button creat=(Button) findViewById(R.id.button1);//创建数据库和表
 22         Button add_Data=(Button) findViewById(R.id.button2);//添加数据
 23         Button query_Data=(Button) findViewById(R.id.button3);//查询数据
 24         Button update=(Button) findViewById(R.id.button4);//更新数据
 25         Button delete_Data=(Button) findViewById(R.id.button5);//删除数据
 26         Button updata_SQL=(Button) findViewById(R.id.button6);//更新数据库
 27         myDatabase = new MyDatabaseHelper(this, "MySQL", null, version);//执行该语句是不会创建数据库的
 28         /*说明:
 29          * 当调用SQLiteOpenHelper的getWritableDatabase()或者getReadableDatabase()方法
 30          * 获取用于操作数据库的SQLiteDatabase实例的时候,如果数据库不存在,Android系统会自动生成一个数据库,紧接着就会去调用onCreate方法
 31          * 也就是说当调用了读或写的方法时就会先去判断有没有该数据库,有就不创建没有就创建,然后就会去调用onCreate方法
 32          */
 33         creat.setOnClickListener(new OnClickListener() {//创建数据库
 34             @Override
 35             public void onClick(View v) {
 36                 System.out.println("creat");
 37                 SQLiteDatabase db = myDatabase.getReadableDatabase();//创建数据库和调用onCreate方法
 38             }
 39         });
 40         add_Data.setOnClickListener(new OnClickListener() {//为表添加数据
 41             @Override
 42             public void onClick(View v) {
 43                 System.out.println("添加数据(id自增,书名,价格,作者)");
 44                 SQLiteDatabase db = myDatabase.getWritableDatabase();
 45                 ContentValues values=new ContentValues();
 46                 values.put("name", "哈利波特");//与表的数据类型一一对应
 47                 values.put("price", 52.3);
 48                 values.put("author", "作者名");
 49                 db.insert("book", null, values);//插入数据
 50                 values.clear();//清除数据
 51                 values.put("name", "book2");//与表的数据类型一一对应
 52                 values.put("price", 10.5);
 53                 values.put("author", "book2_name");
 54                 db.insert("book", null, values);//插入数据
 55             }
 56         });
 57         query_Data.setOnClickListener(new OnClickListener() {//查询数据
 58             @Override
 59             public void onClick(View v) {
 60                 System.out.println("查询数据单击事件");
 61                 SQLiteDatabase db = myDatabase.getReadableDatabase();
 62                 Cursor cursor = db.query("book",null, null, null, null, null, null);//查询所有数据,返回一个游标
 63                 while(cursor.moveToNext()){
 64                     int id=cursor.getColumnIndex("id");
 65                     int name = cursor.getColumnIndex("name");//获得下标
 66                     int price = cursor.getColumnIndex("price");
 67                     int author=cursor.getColumnIndex("author");
 68                     System.out.print("id:"+cursor.getString(id));
 69                     System.out.print(" 书名:"+cursor.getString(name));//通过下标获取值
 70                     System.out.print(" 价格:"+cursor.getString(price));
 71                     System.out.println(" 作者:"+cursor.getString(author));
 72                 }
 73             }
 74         });
 75         update.setOnClickListener(new OnClickListener() {//更新数据
 76             @Override
 77             public void onClick(View v) {
 78                 System.out.println("更新数据单击事件");
 79                 SQLiteDatabase db = myDatabase.getWritableDatabase();
 80                 ContentValues values=new ContentValues();
 81                 values.put("price",52.2);
 82                 //db.update("book", values, "author=?", new String[]{"book2_name"});//将作者=book2_name的price改为20.2
 83                 db.update("book", values, "id=? or id=? ", new String[]{String.valueOf(5),"3"});//将id=5或id=3的price改为20.2
 84             }//第二个参数是 ContentValues 对象,要把更新数据在这里组装进去。第三、第四个参数
 85         });//用于去约束更新某一行或某几行中的数据,不指定的话默认就是更新所有行。  or and  = 也可写> <
 86         
 87 
 88         delete_Data.setOnClickListener(new OnClickListener() {//删除数据
 89             @Override
 90             public void onClick(View v) {
 91                 System.out.println("删除数据单击事件");
 92                 SQLiteDatabase db = myDatabase.getWritableDatabase();
 93                 db.delete("book", "name=?", new String[]{"哈利波特"});//删除name为哈利波特的数据
 94             }
 95         });
 96         updata_SQL.setOnClickListener(new OnClickListener() {//更新数据库
 97             @Override
 98             public void onClick(View v) {
 99                 System.out.println("更新数据库单击事件");
100                 version=2;//将版本号变大
101                 myDatabase=new MyDatabaseHelper(MainActivity.this, "MySQL", null, version);//执行此方法不会调用更新方法onUpgrade
102                 myDatabase.getWritableDatabase();//调用此方法就会更新数据
103             }
104         });
105     }
106 
107 }

根据指定路径打开数据库,手机内存的也能打开

String path = Environment.getExternalStorageDirectory().getAbsolutePath() + "/person_db.db";
   //根据数据库路径打开数据库,得到操作数据库的对象
SQLiteDatabase db = SQLiteDatabase.openDatabase(path, null,SQLiteDatabase.OPEN_READWRITE);

增删改查的参数可参考: 内容提供者基础(含有自己的例子) 以及sql语句 sqlite3的语句记录

使用事务

SQLite 数据库是支持事务的,事务的特性可以保证让某一系列的操
作要么全部完成,要么一个都不会完成。那么在什么情况下才需要使用事务呢?想象以下场
景,比如你正在进行一次转账操作,银行会将转账的金额先从你的账户中扣除,然后再向收
款方的账户中添加等量的金额。看上去好像没什么问题吧?可是,如果当你账户中的金额刚
刚被扣除,这时由于一些异常原因导致对方收款失败,这一部分钱就凭空消失了!当然银行
肯定已经充分考虑到了这种情况,它会保证扣钱和收款的操作要么一起成功,要么都不会成
功,而使用的技术当然就是事务了。

例如:

 1 Button replaceData = (Button) findViewById(R.id.replace_data);
 2 replaceData.setOnClickListener(new OnClickListener() {
 3     @Override //按钮单击事件
 4     public void onClick(View v) {
 5         SQLiteDatabase db = dbHelper.getWritableDatabase();//获取对数据库的操作对象
 6         db.beginTransaction(); // 开启事务
 7         try {
 8             db.delete("Book", null, null);//删除Book表的所有数据
 9             if (true) {// 在这里手动抛出一个异常,让事务失败
10                 throw new NullPointerException();
11             }
12             ContentValues values = new ContentValues();
13             values.put("name", "Game of Thrones");
14             values.put("author", "George Martin");
15             values.put("pages", 720);
16             values.put("price", 20.85);
17             db.insert("Book", null, values);
18             db.setTransactionSuccessful(); // 事务已经执行成功
19         } catch (Exception e) {
20             e.printStackTrace();
21         } finally {
22             db.endTransaction(); // 结束事务
23         }
24     });
25 }

由于在删除数据之前开启了事务,所以抛出异常的时候执行不到  db.setTransactionSuccessful(); 也就是事务没有执行成功

在结束事务的时候,如果事务没有执行成功,那么开启事务之后的操作也就不会成功了,所以删除数据的操作也就没有成功

数据库的分页问题,获取数据库且指定数据的条数:

public class MainActivity extends Activity {

    private ListView lvPersons;
    private Context context;
    private List<Map<String, Object>> dataList;
    private int index = 1;
    private boolean isBottom = false;
    private SimpleAdapter simpleAdapter;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        this.context = MainActivity.this;
        dataList = new ArrayList<Map<String, Object>>();
        // 获取第一页数据
        List<Map<String, Object>> indexPageDataList = getIndexPageDataList(index);
        dataList.addAll(indexPageDataList);

        lvPersons = (ListView) findViewById(R.id.lv_persons);
         simpleAdapter = new SimpleAdapter(context, dataList, R.layout.listview_item_person,
         new String[]{"name","age"}, new int[]{R.id.tv_name,R.id.tv_age});
         lvPersons.setAdapter(simpleAdapter);
         
         //分页
         lvPersons.setOnScrollListener(new OnScrollListener() {
            
            @Override
            public void onScrollStateChanged(AbsListView view, int scrollState) {
                if(isBottom && scrollState == SCROLL_STATE_IDLE){
                    //第二页
                    index +=1;
                    List<Map<String, Object>> indexPageDataList2 = getIndexPageDataList(index);
                    dataList.addAll(indexPageDataList2);
                    //刷新
                    simpleAdapter.notifyDataSetChanged();
                    
                }
                
            }
            
            @Override
            public void onScroll(AbsListView view, int firstVisibleItem,
                    int visibleItemCount, int totalItemCount) {
                isBottom = (firstVisibleItem + visibleItemCount == totalItemCount);
            }
        });
         
    }
    
    
    
    private List<Map<String, Object>> getIndexPageDataList(int index) {
        ArrayList<Map<String, Object>> resultDatalist = new ArrayList<Map<String, Object>>();
        // 打开数据库
        // 查询index页数据,获得cursor
        // 在while循环中获得每一条数据,封装到map中,并添加到list中

        String path = Environment.getExternalStorageDirectory().getAbsolutePath() + "/person_db.db";//打开指定数据库
        //根据数据库路径打开数据库,得到操作数据库的对象
        SQLiteDatabase db = SQLiteDatabase.openDatabase(path, null,SQLiteDatabase.OPEN_READWRITE);

        // 设置分页查询的起始位置
        int startIndex = (index - 1) * 15;

        String sql = "select * from person limit ?,15";//代表查询person表 15条数据
        Cursor cursor = db.rawQuery(sql, new String[] {startIndex + ""} );
        HashMap<String, Object> map;
        while (cursor.moveToNext()) {
            map = new HashMap<String, Object>();
            String key = "";
            Object value = null;
            String[] columnNames = cursor.getColumnNames();
            for (int i = 0; i < columnNames.length; i++) {
                key = columnNames[i];
                // 确定value
                int type = cursor
                        .getType(cursor.getColumnIndex(columnNames[i]));
                //获得列的索引
                int columnIndex = cursor.getColumnIndex(columnNames[i]);
                
                switch (type) {
                case Cursor.FIELD_TYPE_BLOB://大的二进制数据
                  value = cursor.getBlob(columnIndex);
                    break;
                case Cursor.FIELD_TYPE_FLOAT://浮点类型
                    value = cursor.getFloat(columnIndex);
                    break;
                case Cursor.FIELD_TYPE_INTEGER://整数
                    value = cursor.getInt(columnIndex);
                    break;
                case Cursor.FIELD_TYPE_NULL://

                    break;
                case Cursor.FIELD_TYPE_STRING://字符串
                    value = cursor.getString(columnIndex);
                    break;

                default:
                    break;
                }
                
                map.put(key, value);
            }
            
            resultDatalist.add(map);
        }
        return resultDatalist;
    }
}

 

query 参数详解: http://blog.csdn.net/wssiqi/article/details/8132603

posted @ 2016-04-20 17:01  ts-android  阅读(1428)  评论(0编辑  收藏  举报