码迷,mamicode.com
首页 > 移动开发 > 详细

Android中的SQLite的高级使用

时间:2015-08-25 19:41:55      阅读:241      评论:0      收藏:0      [点我收藏+]

标签:sqlite   查询排序   limit   orderby   

SQLite在android实际开发中是基本上避免不了的,很多时候我们都会使用到他作为数据存储的一种手段。

比如,我们现在,一般打开app,不用有网络的一些操作,我们就可以给用户显示上次退出之前的最新的前二十条或者多少条数据,一些评论等等。我们就是可以使用SQLite来实现。思想是:每一次用户有刷新成功的操作,我们就保存本次刷新得到的前二十条(根据实际情况)数据,然后把相关数据保存本地,通过数据库去维护并且获取,这样子的用户体验就很好,因为不用打开APP需要有网络请求的数据成功之后才有东西显示出来。

我们本次聊聊的就是如何使用SQLite去保存数据。

首先需要了解一些关于SQLite的相关的东西,比如语法,它允许的字段类型等等(虽然SQlite是基本上可以说没有类型之分,但是还是需要了解的)

请看连接:http://blog.csdn.net/liweijie_chengxuyuan/article/details/47031163

 

其中最基本的增删吃、改差我这里就不提及了,跟大家分享一些比较高级一点的东西,比如拿出来的数据如何排序,怎么从一个地方拿从一个位置到另外一个位置的数据等等。这些我们都是可以使用得上的,比如,我们把某一类型的数据本地化了,使用SQLite保存,然后我们显示的时候,不可能一次性从本地获取完毕的是吧,所以呢,我们就是当用户下拉加载的时候,我们就去根据当前显示的list的数据的大小作为我们从数据库再拿数据的开始,然后一次再拿十五条数据(自己定),然后拿出来的数据需要按照一定的格式排好顺序这样。

下面是实例:

首先是建表,我这里建两个表,一个是Book,一个是Person,其中,Book的主键只有一个,使用自动生成的id作为主键,Person表的的主键是age+id(主要是为了测试)。

他的的创建表语句的使用时这样的:

数据库帮助类:,一般的数据库需要使用单利模式,因为很多时候数据库会有并发问题出现

package com.example.sqlite_demo.helper;

import android.content.Context;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;

public class MySqliteHelper extends SQLiteOpenHelper
{
	private static final String DB_NAME = "mydb";
	private static final int VERSION = 1;
	private static final String DROP = "DROP TABLE IF EXISTS ";
	public static final String BOOK_TABLE = "book";
	public static final String BOOK_PERSON = "person";

	private MySqliteHelper(Context context)
	{
		super(context, DB_NAME, null, VERSION);
		// TODO Auto-generated constructor stub
	}

	@Override
	public void onCreate(SQLiteDatabase db)
	{
		// TODO Auto-generated method stub
		db.execSQL(DROP + BOOK_TABLE);
		String CREATE_BOOK = "CREATE TABLE " + BOOK_TABLE + "( "
		    + "_id INTEGER PRIMARY KEY AUTOINCREMENT ,name TEXT, price INTEGER" + ")";
		db.execSQL(CREATE_BOOK);

		db.execSQL(DROP + BOOK_PERSON);
		String CREATE_PERSON = "CREATE TABLE " + BOOK_PERSON + " ("
		    + "name TEXT,age INTEGER,birthDay DATE,salary INTEGER,id INTEGER,PRIMARY KEY(age,id)" + ")";
		db.execSQL(CREATE_PERSON);
		Log.i("MySqliteHelper","创建表完成");
	}

	@Override
	public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion)
	{
		// TODO Auto-generated method stub
		db.execSQL(DROP + BOOK_TABLE);
		db.execSQL(DROP + BOOK_PERSON);
		onCreate(db);
	}

	private static MySqliteHelper helper;

	/**
	 * 使用单例模式
	 * 
	 * @param context
	 * @return
	 */
	public static MySqliteHelper getInstance(Context context)
	{
		if (null == helper)
		{
			synchronized (MySqliteHelper.class)
			{
				if (null == helper)
				{
					helper = new MySqliteHelper(context);
				}
			}
		}

		return helper;
	}

}
添加数据:

	// 增加
	public void addperson(Person per)
	{
		// 写入的时候需要确保是可以写进去的
		SQLiteDatabase db = mHelper.getWritableDatabase();
		db.execSQL("INSERT INTO " + MySqliteHelper.BOOK_PERSON + " values(?,?,?,?,?)", new Object[]
		{ per.getName(), per.getAge(), per.getBirthDay(), per.getSalary(), per.getId() });
	}

	// 增加
	public void addBook(Book b)
	{
		// 写入的时候需要确保是可以写进去的
		SQLiteDatabase db = mHelper.getWritableDatabase();
		db.execSQL("INSERT INTO " + MySqliteHelper.BOOK_TABLE +  "(name,price) values(?,?)", new Object[]
		{ b.getName(), b.getPrice() });
	}

这是TestSqlite,继承了AndroidTestCase的测试类中添加数据,注意,日期格式的那一栏的必须是像我那样,不能是“2015-1-1”之类的,然后,大家注意一下主键的问题,在Person表中,age+id在插入数据的时候是没有一个相同的,但是在Book表中,就可以有相同的数据,这就是主键的不同作用。

public void testAddDb() throws Exception
	{
		MySQLiteService service = new MySQLiteService(getContext());
		Person per = new Person("A", 22, "1993-04-20", 10, 1);
		Person per1 = new Person("B", 22, "1990-04-20", 109, 2);
		Person per2 = new Person("C", 22, "1996-04-20", 108, 3);
		Person per3 = new Person("D", 22, "1998-04-10", 107, 4);
		Person per4 = new Person("E", 22, "2000-04-20", 107, 5);
		Person per5 = new Person("F", 23, "2015-04-20", 104, 1);
		Person per6 = new Person("G", 24, "2014-04-20", 101, 1);
		Person per7 = new Person("H", 25, "2005-04-20", 100, 1);
		service.addperson(per);
		service.addperson(per1);
		service.addperson(per2);
		service.addperson(per3);
		service.addperson(per4);
		service.addperson(per5);
		service.addperson(per6);
		service.addperson(per7);

		Book b = new Book("1", 1);
		Book b1 = new Book("1", 1);
		Book b2 = new Book("2", 3);
		Book b3 = new Book("4", 1);
		Book b4 = new Book("5", 1);
		service.addBook(b);
		service.addBook(b);
		service.addBook(b1);
		service.addBook(b2);
		service.addBook(b3);
		service.addBook(b4);

	}

截图结果,对应两个表

技术分享技术分享


关于删除更新那些操作大家可以看看我之前的blog,这里要介绍是高级一点的SQLite技能


按照我们需要的一些东西排序之后得到查找结果:比如,我需要按照生日的顺序,由小到大排序,就可以这样


	// 获取person,然后按出生日期排序
	public List<Person> getListPerson()
	{
		List<Person> mList = new ArrayList<Person>();
		SQLiteDatabase db = mHelper.getWritableDatabase();
		Cursor cursor = db.rawQuery("select * from " + MySqliteHelper.BOOK_PERSON + " ORDER BY "
		    + "birthDay" + " DESC", null);
		if (cursor.moveToFirst())
		{
			do
			{
				Person per = new Person();
				per.setAge(cursor.getInt(cursor.getColumnIndex("age")));
				per.setBirthDay(cursor.getString(cursor.getColumnIndex("birthDay")));
				per.setId(cursor.getInt(cursor.getColumnIndex("id")));
				per.setName(cursor.getString(cursor.getColumnIndex("name")));
				per.setSalary(cursor.getInt(cursor.getColumnIndex("salary")));
				mList.add(per);
			} while (cursor.moveToNext());
		}
		cursor.close();
		return mList;
	}

测试代码:

public void testOrderBy() throws Exception
	{
		MySQLiteService service = new MySQLiteService(getContext());
		List<Person> listPerson = service.getListPerson();
		for (Person per : listPerson)
		{
			Log.i(TAG, per.toString());
		}
	}

结果截图:

技术分享

其中DESC是从大到小(日期的话是从进到远,向这里)ASC则是与DESC相反,这里不写实例


第二种需求:我们需要从我们的数据库查询数据,而不是全部查询,比如我一次需要查询二十条,假如数据库没有辣么多数据的时候,则是查找全部

首先,我们需要知道数据的、库有多少条数据

	//query count
	public int getPersonCount()
	{
		int count = 0;
		SQLiteDatabase db = mHelper.getWritableDatabase();
		Cursor cursor = db.rawQuery("select * from " + MySqliteHelper.BOOK_PERSON, null);
		count = cursor.getCount();
		cursor.close();
		return count;
	}

这样就可以获得了

现在,我们往数据库插入100条新数据

测试代码,需要保证的是age+id唯一:

	public void testAddDb() throws Exception
	{
		MySQLiteService service = new MySQLiteService(getContext());
		for (int i = 0; i < 100; i++)
		{
			Person per = new Person(i + "名字", i, "2015-08-30", i * 100, i);
			service.addperson(per);
		}
	}
然后,这时候我们去获取数据,获取的数据的原则是,从哪一个位置开始,到哪一个位置结束

代码:

public List<Person> getListPersonByLimit(int start, int length)
	{
		List<Person> list = new ArrayList<Person>();
		SQLiteDatabase db = mHelper.getWritableDatabase();
		Cursor cursor = db.rawQuery(
		    "select * from " + MySqliteHelper.BOOK_PERSON + " limit " + String.valueOf(start) + ","
		        + String.valueOf(length), null);
		if (cursor.moveToFirst())
		{
			do
			{
				Person per = new Person();
				per.setAge(cursor.getInt(cursor.getColumnIndex("age")));
				per.setBirthDay(cursor.getString(cursor.getColumnIndex("birthDay")));
				per.setId(cursor.getInt(cursor.getColumnIndex("id")));
				per.setName(cursor.getString(cursor.getColumnIndex("name")));
				per.setSalary(cursor.getInt(cursor.getColumnIndex("salary")));
				list.add(per);
			} while (cursor.moveToNext());
		}
		cursor.close();
		return list;
	}

测试代码:

public void testLimit() throws Exception
	{
		MySQLiteService service = new MySQLiteService(getContext());
		Log.i(TAG, "数据库目前的长度大小" + service.getPersonCount());
		List<Person> listPerson = service.getListPersonByLimit(10, 19);
		Log.i(TAG, "获取的list的的长度大小" + listPerson.size());
		for (Person per : listPerson)
		{
			Log.i(TAG, per.toString());
		}
	}

截图结果:结果的意思就是从数据库的第十个开始去,去19条数据出来,假如没有19条数据,则取完

技术分享

好了,终极的问题来了,就是假如,我需要查询从某一个位置开始的数据,差取20条,然后需要按照什么鬼排序,而且我查询的是条件是什么等等。

我们首先为了测试方便,就添加一些新的数据

public void testAddDb() throws Exception
	{
		MySQLiteService service = new MySQLiteService(getContext());
		for (int i = 0; i < 31; i++)
		{
			Person per;
			//保证日期格式正确
			if (i < 10)
			{
				per = new Person("liweijie", i, "2015-08-0" + i, i * 100, i + 300);
			} else
			{
				per = new Person("liweijie", i, "2015-08-" + i, i * 100, i + 300);
			}
			service.addperson(per);
		}
	}

现在,我们要获取二十条 名字叫liweijie的 ,id>300的,按照日期从近到远排列的一个list

代码实现:

	/**
	 * @param start
	 *          开始位置
	 * @param length
	 *          获取长度
	 * @param name
	 *          查询条件
	 * @param id
	 *          查询条件
	 * @param birthday
	 *          排序方式
	 * @return
	 */
	public List<Person> getPerson(int start, int length, String name, int id)
	{
		List<Person> list = new ArrayList<Person>();
		SQLiteDatabase db = mHelper.getWritableDatabase();
		Cursor cursor = db.rawQuery("select * from " + MySqliteHelper.BOOK_PERSON
		    + " where name = ? and id >=? ORDER BY birthDay DESC limit " + String.valueOf(start) + ","
		    + String.valueOf(length), new String[]
		{ name, String.valueOf(id) });
		if (cursor.moveToFirst())
		{
			do
			{
				Person per = new Person();
				per.setAge(cursor.getInt(cursor.getColumnIndex("age")));
				per.setBirthDay(cursor.getString(cursor.getColumnIndex("birthDay")));
				per.setId(cursor.getInt(cursor.getColumnIndex("id")));
				per.setName(cursor.getString(cursor.getColumnIndex("name")));
				per.setSalary(cursor.getInt(cursor.getColumnIndex("salary")));
				list.add(per);
			} while (cursor.moveToNext());
		}
		cursor.close();
		return list;
	}

测试daim:

public void testGetPerson() throws Exception
	{
		MySQLiteService service = new MySQLiteService(getContext());
		Log.i(TAG, "数据库目前的长度大小" + service.getPersonCount());
		List<Person> listPerson = service.getPerson(0, 20, "liweijie", 300);
		Log.i(TAG, "获取的list的的长度大小" + listPerson.size());
		for (Person per : listPerson)
		{
			Log.i(TAG, per.toString());
		}
	}

技术分享

好了,写了一个下午,之后会在、继续跟大家分享



版权声明:本文为博主原创文章,未经博主允许不得转载。

Android中的SQLite的高级使用

标签:sqlite   查询排序   limit   orderby   

原文地址:http://blog.csdn.net/liweijie_chengxuyuan/article/details/47067647

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!