数据库相关(5) SQLite
2015-07-31 16:39
369 查看
在安卓系统,涉及到数据存储的,主要有4种情况
文件读写 openFileOutput()方法 FileOutputStream outStream = this.openFileOutput("cskaoyan.txt", Context.MODE_PRIVATE);
sharedPreference SharedPreferences sharedPreferences = getSharedPreferences("infomation", 0);
网络数据
SQLite
1. 在SQLite中,增删改查的语句有两种写法
一种是对应每类操作的专门方法,insert()等等,略过不提了
第二种是execSQL和rawQuery两种方法,前者执行数据库变动的方法,建表,增删改;后者专门用来进行查询操作,与第一种方法的区别是,这两个方法里面直接填入SQL的通用操作语句即可,很方便。
exec方法, 实际操作中,我们通常是在外接收数据来进行操作,这里涉及到一些特殊符号的转义问题,直接写比较麻烦,所以用一个object对象来接收,有一个重载后的execSQL(String sql, Object[] bindArgs)方法,前面的sql里面可以用占位符 ? 来替代具体参数,把具体参数传给object即可
raw方法,第一个参数为select语句;第二个参数为select语句中占位符参数的值,如果select语句没有使用占位符,该参数可以设置为null。需要注意在执行raw后返回一个cursor,要通过这个cursor来往下读取。因为查询的目的是为了读取数据库里的数据,某些字段什么的,形象来说,是一节一节的读取。
Cursor是结果集游标,用于对结果集进行随机访问,如果大家熟悉jdbc, 其实Cursor与JDBC中的ResultSet作用很相似。使用moveToNext()方法可以将游标从当前行移动到下一行,如果已经移过了结果集的最后一行,返回结果为false,否则为true。另外Cursor 还有常用的moveToPrevious()方法(用于将游标从当前行移动到上一行,如果已经移过了结果集的第一行,返回值为false,否则为true )、moveToFirst()方法(用于将游标移动到结果集的第一行,如果结果集为空,返回值为false,否则为true
)和moveToLast()方法(用于将游标移动到结果集的最后一行,如果结果集为空,返回值为false,否则为true ) 。
下面的Demo是在布局文件里写了button,这里就不贴上来了
2. SQLiteOpenHelper & 第一类方法
在Android系统,提供了一个SQLiteOpenHelper抽象类,该类用于对数据库版本进行管理.
需要继承这个抽象来,实现一个有参构造函数和两个方法
他的构造方法用来接收参数再来创建一个数据库
这个抽象类一般是用来版本控制,表结构有变动,或者说升级什么的,这就是upgrade方法的用处,在调用这个抽象类创建数据库的时候,还可以在他的oncreate方法里去创建表(第一次才有用)
为了防止溢出,用readable
另外再helper里可以创建表,而且是数据库被创建时才会调用一次,无需在activity里去建表了,以后再调用这个openhelper只是进行查询操作
在版本升级时,要增加一些功能加别的表什么的,就要调用upgrade,添加新表什么的,同时版本号必须变动
在activity里有了新版本后,必须说要先在openhelper里添加新的功能,然后才能在activity里去查询什么的
比如数据库里添加了一个gender的字段,数据库版本就变动了,数据库变动就会调用这个upgrade方法,在这里应该实现添加字段的功能,然后才可以在activity里去查询这个字段。
再来看第一类方法
3. 事务处理
ContentValues:数据库插入、更新数据的时候用到,应该是一个map,一个key,一个value。一个数据表的Column,一个存入的值。返回的是数组。它和HashTable类似都是一种存储的机制,contenvalues只能存储基本类型的数据,而HashTable却可以存储对象
在向数据库中插入数据的时候,首先应该有一个ContentValues的对象
和之前在MySQL里差不多
有一点要注意,SQLite里下标从0开始计算的,mysql什么的是从1计数
4.SQLite有一个命令行的查询工具,不过现在又现成的图形界面的数据库管理软件,例如SQLite Expert
5.测试
为了方便测试数据库,无需去启动UI画面来看结果,可以写一个AndroidTestCase类,这个类也要在虚拟机上安装,但是会自动销毁,不显示画面
这个还要去manifest里声明
在某个项目里加上测试类就好
文件读写 openFileOutput()方法 FileOutputStream outStream = this.openFileOutput("cskaoyan.txt", Context.MODE_PRIVATE);
sharedPreference SharedPreferences sharedPreferences = getSharedPreferences("infomation", 0);
网络数据
SQLite
1. 在SQLite中,增删改查的语句有两种写法
一种是对应每类操作的专门方法,insert()等等,略过不提了
第二种是execSQL和rawQuery两种方法,前者执行数据库变动的方法,建表,增删改;后者专门用来进行查询操作,与第一种方法的区别是,这两个方法里面直接填入SQL的通用操作语句即可,很方便。
exec方法, 实际操作中,我们通常是在外接收数据来进行操作,这里涉及到一些特殊符号的转义问题,直接写比较麻烦,所以用一个object对象来接收,有一个重载后的execSQL(String sql, Object[] bindArgs)方法,前面的sql里面可以用占位符 ? 来替代具体参数,把具体参数传给object即可
raw方法,第一个参数为select语句;第二个参数为select语句中占位符参数的值,如果select语句没有使用占位符,该参数可以设置为null。需要注意在执行raw后返回一个cursor,要通过这个cursor来往下读取。因为查询的目的是为了读取数据库里的数据,某些字段什么的,形象来说,是一节一节的读取。
Cursor是结果集游标,用于对结果集进行随机访问,如果大家熟悉jdbc, 其实Cursor与JDBC中的ResultSet作用很相似。使用moveToNext()方法可以将游标从当前行移动到下一行,如果已经移过了结果集的最后一行,返回结果为false,否则为true。另外Cursor 还有常用的moveToPrevious()方法(用于将游标从当前行移动到上一行,如果已经移过了结果集的第一行,返回值为false,否则为true )、moveToFirst()方法(用于将游标移动到结果集的第一行,如果结果集为空,返回值为false,否则为true
)和moveToLast()方法(用于将游标移动到结果集的最后一行,如果结果集为空,返回值为false,否则为true ) 。
下面的Demo是在布局文件里写了button,这里就不贴上来了
public class MainActivity extends Activity { public static String TAG ="sqlitedemo"; SQLiteDatabase db=null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //创建数据库 db = SQLiteDatabase.openOrCreateDatabase(getFilesDir()+"userinfo.db", null); } public void insert(View v){ insert(db); } public void delete(View v){ delete(db); } public void update(View v){ Update(db); } public void query(View v){ query(db); } private void Update(SQLiteDatabase db) { /*String update = "update user set password ='88888888' where id =2;"; db.execSQL(update);*/ String update = "update user set password =? where id =?;"; Object[] args = {"99999999",5}; db.execSQL(update,args); } private void delete(SQLiteDatabase db) { /* String delete = "delete from user where id =1;"; db.execSQL(delete);*/ String delete = "delete from user where id =?;"; Object[] args = {5}; db.execSQL(delete,args); } private void query(SQLiteDatabase db) { //查询,并弄到名为resultset的Cursor类的集合里 String sql = "select * from user where id = ? and name =?;"; String[] arg = {"1","user1"}; Cursor resultset = db.rawQuery(sql, arg); //先在resultset里找到行数 int row = resultset.getCount(); //sqlite列标从0开始,mysql从1开始 Log.i(TAG, row+""); //Cursor的游标指向了数据的前一行,所以需要next while(resultset.moveToNext()){ int id = resultset.getInt(0); String username= resultset.getString(1); String password= resultset.getString(2); Log.i(TAG, id+","+username+","+password); } } private void insert(SQLiteDatabase db) { /*String insert = "insert into user values(5,'user5','12345');"; db.execSQL(insert);*/ String insert = "insert into user values(?,?,?);"; Object[] args = {4,"user4","55555555"}; db.execSQL(insert, args); } private void createTable(SQLiteDatabase db) { String createtable = "create table user(id int,name varchar(20),password char(8));"; db.execSQL(createtable); } }
2. SQLiteOpenHelper & 第一类方法
在Android系统,提供了一个SQLiteOpenHelper抽象类,该类用于对数据库版本进行管理.
需要继承这个抽象来,实现一个有参构造函数和两个方法
他的构造方法用来接收参数再来创建一个数据库
这个抽象类一般是用来版本控制,表结构有变动,或者说升级什么的,这就是upgrade方法的用处,在调用这个抽象类创建数据库的时候,还可以在他的oncreate方法里去创建表(第一次才有用)
//一般用来查询,创建数据库的时候,可以插入一些数据,或者建表什么的 public class MydbOpenHelper extends SQLiteOpenHelper { //在调用的时候,把要创建的数据库名保存起来 //然后在调用Helper获取数据库的时候,用这个名字创建数据库 public MydbOpenHelper(Context context, String name, CursorFactory factory, int version) { super(context, name, factory, version); } //oncreate函数当数据库第一次被创建的时候才会被调用 //上面提到的建表、插入数据什么的就在oncreate里实现 @Override public void onCreate(SQLiteDatabase db) { String createtable = "create table user(id int,name varchar(20),password char(8));"; db.execSQL(createtable); System.out.println("MydbOpenHelper.onCreate()"); } //数据库版本升级的时候调用,不会把原有User数据删掉 //之前版本没有的、或者需要变动的,使用Upgrade @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { //在这里对传送过来的db进行改动,比如加一个gender属性,然后下面执行 //db.execSQL(sql); //看看有没有调用到 Log.i("MydbOpenHelper", "oldervserion"+oldVersion+"newversion"+newVersion); System.out.println("MydbOpenHelper.onUpgrade()"); } }
public class MainActivity extends Activity { SQLiteDatabase db=null; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); //此时数据还没有被创建出来 MydbOpenHelper dbhelper = new MydbOpenHelper(this,"userinfo.db",null,1); //调用下条语句之后,数据库才会被创建出来 //SQLiteDatabase db = dbhelper.getWritableDatabase(); //磁盘满了的话创建的数据库是只读的,不能写,比write强一点 SQLiteDatabase db = dbhelper.getReadableDatabase(); /*//可以使用这个原始方法,但是在openhelper里有google封装好的 String createtable = "create table user(id int,name varchar(20),password char(8));"; db.execSQL(createtable);*/
为了防止溢出,用readable
另外再helper里可以创建表,而且是数据库被创建时才会调用一次,无需在activity里去建表了,以后再调用这个openhelper只是进行查询操作
在版本升级时,要增加一些功能加别的表什么的,就要调用upgrade,添加新表什么的,同时版本号必须变动
在activity里有了新版本后,必须说要先在openhelper里添加新的功能,然后才能在activity里去查询什么的
比如数据库里添加了一个gender的字段,数据库版本就变动了,数据库变动就会调用这个upgrade方法,在这里应该实现添加字段的功能,然后才可以在activity里去查询这个字段。
//数据库版本升级的时候调用,不会把原有User数据删掉 //之前版本没有的、或者需要变动的,使用Upgrade @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { //在这里对传送过来的db进行改动,比如加一个gender属性,然后下面执行 //db.execSQL(sql); //看看有没有调用到 Log.i("MydbOpenHelper", "oldervserion"+oldVersion+"newversion"+newVersion); System.out.println("MydbOpenHelper.onUpgrade()"); }
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); /*//此时数据还没有被创建出来 MydbOpenHelper dbhelper = new MydbOpenHelper(this,"userinfo.db",null,1); //调用下条语句之后,数据库才会被创建出来 //SQLiteDatabase db = dbhelper.getWritableDatabase(); //磁盘满了的话创建的数据库是只读的,不能写,比write强一点 SQLiteDatabase db = dbhelper.getReadableDatabase(); //可以使用这个原始方法,但是在openhelper里有google封装好的 String createtable = "create table user(id int,name varchar(20),password char(8));"; db.execSQL(createtable);*/ //新的db,版本6 MydbOpenHelper dbhelper = new MydbOpenHelper(this,"userinfo.db",null,6); db = dbhelper.getReadableDatabase(); /*String sql = "select gender from user;"; db.execSQL(sql);*/ }
再来看第一类方法
public void insert(View v){ //需要new一个,而不是Null ContentValues c = new ContentValues(); c.put("id", 1); c.put("name", "user1"); c.put("password", "123454"); //table往哪个表插,values是个map,键值对,定义键名和值(默认8) //columnHack db.insert("user", null, c); } public void delete(View v){ db.delete("user", " id =? and name =? ", new String[]{"1", "user1"}); } public void update(View v){ //Update(db); ContentValues c = new ContentValues(); c.put("name", "user22222"); c.put("password", "88888888"); db.update("user", c, "id=?", new String[]{"2"}); } public void query(View v){ String[] colums ={"id","name"}; String[] args = {"1","12345"}; Cursor c = db.query("user",colums,"id=? and password=?",args , null,null,null); while(c.moveToNext()){ int id = c.getInt(c.getColumnIndex("id")); String username= c.getString(c.getColumnIndex("name")); Log.i("sqliteopenhelper", id+","+id+","+username); } }
3. 事务处理
ContentValues:数据库插入、更新数据的时候用到,应该是一个map,一个key,一个value。一个数据表的Column,一个存入的值。返回的是数组。它和HashTable类似都是一种存储的机制,contenvalues只能存储基本类型的数据,而HashTable却可以存储对象
在向数据库中插入数据的时候,首先应该有一个ContentValues的对象
public class MainActivity extends Activity { SQLiteDatabase db; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); MydbOpenHelper helper = new MydbOpenHelper(this,"count.db",null,1); db = helper.getReadableDatabase(); try{ insert(); update(); }finally{ db.close(); } } private void update() { db.beginTransaction(); try{ ContentValues contentValues = new ContentValues(); contentValues.put("money", 7000); db.update("user", contentValues, "id=1", null); int b = 1/0; contentValues.clear(); contentValues.put("money", 11000); db.update("user", contentValues, "id=2", null); db.setTransactionSuccessful(); }finally{ //commit 提交 //不成功则回滚 db.endTransaction(); } } private void insert() { ContentValues contentValues = new ContentValues(); contentValues.put("id",1); contentValues.put("name","user1"); contentValues.put("money",8000); db.insert("user", null, contentValues); contentValues.put("id",2); contentValues.put("name","user2"); contentValues.put("money",1000); db.insert("user", null, contentValues); } }
和之前在MySQL里差不多
有一点要注意,SQLite里下标从0开始计算的,mysql什么的是从1计数
4.SQLite有一个命令行的查询工具,不过现在又现成的图形界面的数据库管理软件,例如SQLite Expert
5.测试
为了方便测试数据库,无需去启动UI画面来看结果,可以写一个AndroidTestCase类,这个类也要在虚拟机上安装,但是会自动销毁,不显示画面
这个还要去manifest里声明
<pre name="code" class="java">
<uses-sdk android:minSdkVersion="14" android:targetSdkVersion="19" /> <!-- test指令集 --> <instrumentation android:name="android.test.InstrumentationTestRunner" android:targetPackage="com.example.sqliteopenhelper" > </instrumentation> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <!-- 测试类库 --> <uses-library android:name="android.test.runner"/> <activity
在某个项目里加上测试类就好
public class MyAndroidTestCase extends AndroidTestCase { SQLiteDatabase db; @Override protected void setUp() throws Exception { // TODO Auto-generated method stub super.setUp(); MydbOpenHelper dbhelper = new MydbOpenHelper(getContext(), "userinfo.db", null, 6); db = dbhelper.getReadableDatabase(); Log.i("test", "setUp()"); } //自动销毁测试 @Override protected void tearDown() throws Exception { // TODO Auto-generated method stub super.tearDown(); db.close(); Log.i("test", "tearDown()"); } //选中这个方法,右键测试跑起就好 public void testcase1(){ testinsert(); testquery(); } public void testinsert(){ ContentValues c = new ContentValues(); c.put("id", 9); c.put("name", "user2"); c.put("password", "123454"); db.insert("user", null, c); } public void testquery(){ Cursor c= db.rawQuery("select * from user", null); while (c.moveToNext()) { //表示由mydbopenhelper里的onCreate创建,可以去看下结构 int id= c.getInt(0); String name= c.getString(1); String password= c.getString(2); Log.i("test", id+","+name+","+password ); } } }
相关文章推荐
- mysql查询语句in和exists二者的区别和性能影响
- Redis——简介
- PHP-redis中文文档
- redis安装部署
- MySQL规范
- 批量删除Redis数据库中的Key
- memcache的启动
- sqlserver中的序列
- mongodb 命令相关
- SQL Server中的“最大并行度”的配置建议
- 原生sql 查clob字段,查出的结果是string类型
- Oracle EBS APIs(转)
- SQL Server存储过程中执行动态SQL语句
- 常用的mysql语句
- Oracle&&Enterprisedb中的大小写
- NoSQL
- SQL server 那些数据类型不能作为索引
- Redis中的简单事物以及消息订阅发布
- sql语句的性能优化问题
- JDBC链接Access数据库