zoukankan      html  css  js  c++  java
  • Android(java)学习笔记136:利用谷歌API对数据库增删改查(推荐使用)

    接下来我们通过项目案例来介绍:这个利用谷歌API对数据库增删改查

    1. 首先项目图:

    2. 这里的布局文件activity_main.xml:

     1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     2     xmlns:tools="http://schemas.android.com/tools"
     3     android:layout_width="match_parent"
     4     android:layout_height="match_parent"
     5     android:orientation="vertical"
     6     tools:context=".MainActivity" >
     7 
     8     <Button
     9         android:onClick="add"
    10         android:layout_width="match_parent"
    11         android:layout_height="wrap_content"
    12         android:text="增" />
    13 
    14     <Button
    15         android:onClick="delete"
    16         android:layout_width="match_parent"
    17         android:layout_height="wrap_content"
    18         android:text="删" />
    19 
    20     <Button
    21         android:onClick="update"
    22         android:layout_width="match_parent"
    23         android:layout_height="wrap_content"
    24         android:text="改" />
    25 
    26     <Button
    27         android:onClick="query"
    28         android:layout_width="match_parent"
    29         android:layout_height="wrap_content"
    30         android:text="查" />
    31 
    32 </LinearLayout>

    3. 其次是MyDBOpenHelper.java  和  MainActivity.java

    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)");
    
        }
    }

    MainActivity.java:

    package com.itheima.dbcreate;
    
    import java.util.Random;
    
    import android.app.Activity;
    import android.content.ContentValues;
    import android.database.Cursor;
    import android.database.sqlite.SQLiteDatabase;
    import android.os.Bundle;
    import android.view.View;
    import android.widget.Toast;
    
    public class MainActivity extends Activity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
        }
    
        /**
         * 添加一条数据
         */
        public void add(View view) {
            // 执行下面的一行代码,数据库是不会别创建的了。
            MyDBOpenHelper helper = new MyDBOpenHelper(this);
            // 如果想创建数据库必须执行,下一行代码
            SQLiteDatabase db = helper.getWritableDatabase();
            Random random = new Random();
            // db.execSQL("insert into info (name,phone) values (?,?)", new Object[]
            // {
            // "王五" + random.nextInt(100), "110-" + random.nextInt(100) });
            ContentValues values = new ContentValues();
            values.put("name", "王五" + random.nextInt(100));
            values.put("phone", "110-" + random.nextInt(100));
            long id = db.insert("info", null, values);// google封装API,内部本质还是通过组拼SQL语句
            db.close();
            if (id != -1) {
                Toast.makeText(this, "添加成功,在第" + id + "行", 0).show();
            } else {
                Toast.makeText(this, "添加失败", 0).show();
            }
        }
    
        /**
         * 删除一条数据
         */
        public void delete(View view) {
            // 执行下面的一行代码,数据库是不会别创建的了。
            MyDBOpenHelper helper = new MyDBOpenHelper(this);
            // 如果想创建数据库必须执行,下一行代码
            SQLiteDatabase db = helper.getWritableDatabase();
            // db.execSQL("delete from info ");
            int result = db.delete("info", null, null);
            db.close();
            if (result == 0) {
                Toast.makeText(this, "删除失败", 0).show();
            } else {
                Toast.makeText(this, "删除了"+result+"条记录", 0).show();
                // 再去查询一次。
            }
        }
    
        /**
         * 修改一条数据
         */
        public void update(View view) {
            // 执行下面的一行代码,数据库是不会别创建的了。
            MyDBOpenHelper helper = new MyDBOpenHelper(this);
            // 如果想创建数据库必须执行,下一行代码
            SQLiteDatabase db = helper.getWritableDatabase();
            //db.execSQL("update info set phone=?", new Object[] { "8888" });
            ContentValues values = new ContentValues();
            values.put("phone", "99999");
            int result = db.update("info", values, null, null);
            db.close();
            if (result == 0) {
                Toast.makeText(this, "修改了0条记录", 0).show();
            } else {
                Toast.makeText(this, "修改了"+result+"条记录", 0).show();
            }
        }
    
        /**
         * 查询全部数据
         */
        public void query(View view) {
            // 执行下面的一行代码,数据库是不会别创建的了。
            MyDBOpenHelper helper = new MyDBOpenHelper(this);
            // 如果想创建数据库必须执行,下一行代码
            SQLiteDatabase db = helper.getReadableDatabase();
            //Cursor cursor = db.rawQuery("select * from info", null);
            Cursor cursor = db.query("info", new String[]{"name","phone","_id"}, null, null, null, null, null);
            while (cursor.moveToNext()) {
                String name = cursor.getString(0);
                String phone = cursor.getString(1);
                String id = cursor.getString(2);
                System.out.println("id:" + id + "--name:" + name + "--phone"
                        + phone);
                System.out.println("----");
            }
            // 记得用完数据库 关闭cursor
            cursor.close();
            db.close();
        }
    
    }

    4. 注意事项:

    (1)首先是getWritableDatabase()和getReadableDatabase()使用:

    getWritableDatabase()

    public SQLiteDatabase getWritableDatabase() {
            synchronized (this) {
                return getDatabaseLocked(true);
            }
        }

    getReadableDatabase()

     public SQLiteDatabase getReadableDatabase() {
            synchronized (this) {
                return getDatabaseLocked(false);
            }
        }

    这里getWritableDatabase()从源码可以看出,它是给数据库数据加锁,这是因为当我们写入数据到数据库的时候,我们考虑的线程安全,在多线程中,在写入数据到数据库中,不同线程写入数据顺序不一样。

    这里getReadableDatabase()从源码可以看出,它是给数据库数据没有加锁,这是因为当我们读取数据库数据的时候,可以多个线程同时读取

    (2)google封装API

     public long insert(String table, String nullColumnHack, ContentValues values)

    参数table:要插入数据的数据库表名

    参数nullColumnHack:比如如果我们定义nullColumnHack为"phone",表示如果数据库中"phone"这一列出现某一行为空,就会系统自动补一个null

    通常我们这个nullColumnHack我们设置为"null",就是不希望自动补null。

    当values参数为空或者里面没有内容的时候,我们insert是会失败的(底层数据库不允许插入一个空行),为了防止这种情况,我们要在这里指定一个 列名,到时候如果发现将要插入的行为空行时,就会将你指定的这个列名的值设为null,然后再向数据库中插入。

    参数values:一个ContentValues对象,类似一个map.通过键值对的形式存储值。可以使用ContentValues的put()方法,put()原型如下:

    public void put(String key, String value) {
            mValues.put(key, value);
        }

    返回值long类型:返回插入的数据在表中第几行(long),插入失败返回 -1

    比如:values.put( "name",  "王五" + random.nextInt(100) );

    public int delete(String table, String whereClause, String[] whereArgs)

    参数table要删除数据的数据库表名

    参数whereClause:更新的条件,为一个字符串。如果为null,则所有行都将更新

    参数whereArgs:字符串数组,和whereClause配合使用。有两种用法,如果whereClause的条件已经直接给出,如"class = " + num,num是传入的参数,则whereArgs可设为null。如果是”class = ?“,则?会被whereArgs这个数组中对应的值替换,whereArgs给出?代表的值,有多个?的,字符串数组里的值依次填入。

    返回值int类型:返回删除了多少条(int)记录数据删除失败返回0

    这里whereClause和whereArgs通常我们设置都是null,表示没有过滤条件,表示全部删除

    例:db.delete("info", null, null);

         db.delete("info","phone=?",new String[] {"999"});----删除所有phone=999的数据,等价于SQL的:delete from info where phone=999

         db.delete("info","phone=999",null);----------------------删除所有phone=999的数据,等价于SQL的:delete from info where phone=999

    public int update(String table, ContentValues values, String whereClause, String[] whereArgs)

    参数table要更新数据的数据库表名

    参数values:你需要更新个数据组成的一个map,由列的名字和列的新值构成,null是合法的值,会被转化为NULL;
    参数whereClause:更新的条件,为一个字符串。如果为null,则所有行都将更新;
    参数whereArgs:字符串数组,和whereClause配合使用。有两种用法,如果whereClause的条件已经直接给出,如“class = “ + num,num是传入的参数,则whereArgs可设为null。如果是”class = ?“,则?会被whereArgs这个数组中对应的值替换,whereArgs给出?代表的值,有多个?的,字符串数组里的值依次填入。
    返回值int类型:返回更新多少行数据(int)
    比如:db.update("info", values, null, null);
     

    public Cursor query(String table, String[] columns,  String selection, String[] selectionArgs, String groupBy, String having, String orderBy)

    参数table要查询数据的数据库表名
    参数culumns:需要返回的列的列表,如果为null,则返回全部的列;
    参数selection:查询的条件,符合什么条件的行将返回。如果为null,则这个表里的所有行都将返回。其两种用法和update里的一样;
    参数selectionArgs:用法和update里的一样。

    返回值Cursor类型:返回了一个游标指针的Cursor,接下来可以使用Cursor中方法可以查询数据

    比如:

    db.query("info", new String[]{"name","phone","_id"}, null, null, null, null, null);

    while (cursor.moveToNext()) {
            String name = cursor.getString(0);
            String phone = cursor.getString(1);
            String id = cursor.getString(2);
            System.out.println("id:" + id + "--name:" + name + "--phone"+ phone);
            System.out.println("----");
    }
    // 记得用完数据库 关闭cursor
    cursor.close();

    由于往往我们不知道数据库表中字段的排列顺序,但是我们可以在查询的时候:

    db.query("info", new String[]{"name","phone","_id"}, null, null, null, null, null);

    这样的话下面使用游标Cursor时候:index=0就是 nameindex=1就是phoneindex=2就是 _id

    也就是: String name = cursor.getString(0);
                 String phone = cursor.getString(1);
                 String id = cursor.getString(2);

    这里特别注意使用Cursor查询完了之后,一定要关闭使用cursor.close()

    5. 使用完了数据库一定要关闭

    db.close();

  • 相关阅读:
    jsp——java服务页面
    会话管理——cookie和session技术
    [Java]如何为一个自定义类型的List排序。
    silverlight——获取控件相对位置
    C#操作xml文件
    [转载]Unicode中对中文字符的编码
    silverlight——多次异步调用的顺序执行
    内心需要跟我一起长大
    生活总是问题叠着问题,而任务就是一件问题一件问题的解决~
    真的该学点新的东西了。
  • 原文地址:https://www.cnblogs.com/hebao0514/p/4754987.html
Copyright © 2011-2022 走看看