安卓学习之持久化技术(数据库操作)

1.持久化技术简介

让数据在瞬时状态和持久化状态进行转换的机制。

主要包括文件存储、shareOreference存储以及数据库存储。

2.文件存储

1.将数据存储到文件中

  • Context 类中提供了一个openFileOutput() 方法,可以用于将数据存储到指定的文件中

  • 这个方法接收两个参数,第一个参数是文件名,在文件创建的时候使用的就是这个名称,注意
    这里指定的文件名不可以包含路径,因为所有的文件都是默认存储到/data/data//files/目录下的。第二个参数是文件的操作模式,主要有两种模式可选,MODE_PRIVATE
    和MODE_APPEND。其中MODE_PRIVATE是默认的操作模式,表示当指定同样文件名的时候,
    所写入的内容将会覆盖原文件中的内容,而MODE_APPEND则表示如果该文件已存在,就往文
    件里面追加内容,不存在就创建新文件

    public void save() {
        String data = "Data to save";
        FileOutputStream out = null;
        BufferedWriter writer = null;
        try {
            out = openFileOutput("data", Context.MODE_PRIVATE);
            writer = new BufferedWriter(new OutputStreamWriter(out));
            writer.write(data);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (writer != null) {
                    writer.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    
  • 通过openFileOutput() 方法能够得到一个FileOutputStream 对象,然后再借助它构建出一个OutputStreamWriter 对象,接着再使用OutputStreamWriter 构建出一个BufferedWriter 对象,这样你就可以通过BufferedWriter 来将文本内容写入到文件中了。

  • onCreate() 方法中获取了EditText的实例,然后重写了onDestroy()方法,这样就可以保证在活动销毁之前一定会调用这个方法。在onDestroy() 方法中我们获取了EditText中输入的内容,并调用save() 方法把输入的内容存储到文件中,文件命名为data

  • public class MainActivity extends AppCompatActivity {
        private EditText edit;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            edit = (EditText) findViewById(R.id.edit);
        }
        @Override
        protected void onDestroy() {
            super.onDestroy();
            String inputText = edit.getText().toString();
            save(inputText);
        }
        public void save(String inputText) {
            FileOutputStream out = null;
            BufferedWriter writer = null;
            try {
                out = openFileOutput("data", Context.MODE_PRIVATE);
                writer = new BufferedWriter(new OutputStreamWriter(out));
                writer.write(inputText);
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    if (writer != null) {
                        writer.close();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    

2.从文件中读取数据

  • Context 类中还提供了一个openFileInput() 方法,用于从文件中读取数据。这个方法要比openFileOutput() 简单一些,它只接收一个参数,即要读取的文件名,然后系统会自动到/data/data//files/目录下去加载这个文件,并返回一个FileInputStream 对象

    public String load() {
        FileInputStream in = null;
        BufferedReader reader = null;
        StringBuilder content = new StringBuilder();
        try {
            in = openFileInput("data");
            reader = new BufferedReader(new InputStreamReader(in));
            String line = "";
            while ((line = reader.readLine()) != null) {
                content.append(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (reader != null) {
                try {
                    reader.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return content.toString();
    }
    
  • 首先通过openFileInput() 方法获取到了一个FileInputStream 对象,然后借助它又构建出了一个InputStreamReader 对象,接着再使用InputStreamReader 构建出一个BufferedReader 对象,这样我们就可以通过BufferedReader 进行一行行地读取,把文件中所有的文本内容全部读取出来,并存放在一个StringBuilder 对象中,最后将读取到的内容返回就可以了

    public class MainActivity extends AppCompatActivity {
        private EditText edit;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            edit = (EditText) findViewById(R.id.edit);
            String inputText = load();
            if (!TextUtils.isEmpty(inputText)) {
                edit.setText(inputText);
                edit.setSelection(inputText.length());
                Toast.makeText(this, "Restoring succeeded", Toast.LENGTH_SHORT).show();
            }
        }
        ...
        public String load() {
            FileInputStream in = null;
            BufferedReader reader = null;
            StringBuilder content = new StringBuilder();
            try {
                in = openFileInput("data");
                reader = new BufferedReader(new InputStreamReader(in));
                String line = "";
                while ((line = reader.readLine()) != null) {
                    content.append(line);
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                if (reader != null) {
                    try {
                        reader.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
            return content.toString();
        }
    }
    
  • 在onCreate() 方法中调用load() 方法来读取文件中存储的文本内容,如果读到的内容不为null ,就调用EditText的setText() 方法将内容填充到EditText里,并调用setSelection() 方法将输入光标移动到文本的末尾位置以便于继续输入,然后弹出一句还原成功的提示.

3. SharedPreferences存储

  • 不同于文件的存储方式,SharedPreferences是使用键值对的方式来存储数据的
  • 当保存一条数据的时候,需要给这条数据提供一个对应的键,这样在读取数据的时候就可以通过这
    个键把相应的值取出来

1.将数据存储到SharedPreferences中

三种获取到SharedPreferences 对象方法

  • Context 类中的getSharedPreferences() 方法

    此方法接收两个参数,第一个参数用于指定SharedPreferences文件的名称,如果指定的文件不存在则会创建一个,SharedPreferences文件都是存放在/data/data//shared_prefs/目录下的。第二个参数用于指定操作模式,目前只有MODE_PRIVATE这一种模式可选

  • Activity 类中的getPreferences() 方法

    这个方法和Context中的getSharedPreferences() 方法很相似,不过它只接收一个操作模式参数,因为使用这个方法时会自动将当前活动的类名作为SharedPreferences的文件名

  • PreferenceManager 类中的getDefaultSharedPreferences() 方法

    这是一个静态方法,它接收一个Context 参数,并自动使用当前应用程序的包名作为前缀来命名SharedPreferences文件

得到了对象,分三步存储数据

  1. 调用SharedPreferences 对象的edit() 方法来获取一个SharedPreferences.Editor 对象
  2. 向SharedPreferences.Editor 对象中添加数据,比如添加一个布尔型数据就使用putBoolean() 方法,添加一个字符串则使用putString() 方法
  3. 调用apply() 方法将添加的数据提交,从而完成数据存储操作
public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button saveData = (Button) findViewById(R.id.save_data);
        saveData.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                SharedPreferences.Editor editor = getSharedPreferences("data",
                    MODE_PRIVATE).edit();
                editor.putString("name", "Tom");
                editor.putInt("age", 28);
                editor.putBoolean("married", false);
                editor.apply();
            }
        });
    }
}

2.从SharedPreferences中读取数据

SharedPreferences 对象中提供了一系列的get 方法,用于对存储的数据进行读取,每种get 方法都对应了
SharedPreferences.Editor 中的一种put 方法,比如读取一个布尔型数据就使用getBoolean() 方法,读取一个字符串就使用getString() 方法。这些get 方法都接收两个参数,第一个参数是键,传入存储数据时使用的键就可以得到相应的值了;第二个参数是默认值,即表示当传入的键找不到对应的值时会以什么样的默认值进行返回

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >
    <Button
        android:id="@+id/save_data"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Save data"
        />
    <Button
        android:id="@+id/restore_data"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Restore data"
        />
</LinearLayout>
public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        Button restoreData = (Button) findViewById(R.id.restore_data);
        restoreData.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                SharedPreferences pref = getSharedPreferences("data", MODE_PRIVATE);
                String name = pref.getString("name", "");
                int age = pref.getInt("age", 0);
                boolean married = pref.getBoolean("married", false);
                Log.d("MainActivity", "name is " + name);
                Log.d("MainActivity", "age is " + age);
                Log.d("MainActivity", "married is " + married);
            }
        });
    }
}

4. SQLite数据库存储

1、创建数据库

  • 专门提供了一个SQLiteOpenHelper帮助类,借助这个类就可以非常简单地对数据库进行创建和升级
  • SQLiteOpenHelper中有两个抽象方法,分别是onCreate() 和onUpgrade()
  • SQLiteOpenHelper中还有两个非常重要的实例方法:getReadableDatabase() 和getWritableDatabase() 。这两个方法都可以创建或打开一个现有的数据库(如果数据库已存在则直接打开,否则创建一个新的数据库),并返回一个可对数据库进行读写操作的对象。不同的是,当数据库不可写入的时候(如磁盘空间已满),getReadableDatabase()方法返回的对象将以只读的方式去打开数据库,而getWritableDatabase() 方法则将出现异常
public class MyDatabaseHelper extends SQLiteOpenHelper {
    public static final String CREATE_BOOK = "create table Book ("
            + "id integer primary key autoincrement, "
            + "author text, "
            + "price real, "
            + "pages integer, "
            + "name text)";
    private Context mContext;
    public MyDatabaseHelper(Context context, String name,
                            SQLiteDatabase.CursorFactory factory, int version) {
        super(context, name, factory, version);
        mContext = context;
    }
    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL(CREATE_BOOK);
        Toast.makeText(mContext, "Create succeeded", Toast.LENGTH_SHORT).show();
    }
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    }
}
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    >
    <Button
        android:id="@+id/create_database"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Create database"
        />
</LinearLayout>
public class MainActivity extends AppCompatActivity {
    private MyDatabaseHelper dbHelper;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        dbHelper = new MyDatabaseHelper(this, "BookStore.db", null, 1);
        Button createDatabase = (Button) findViewById(R.id.create_database);
        createDatabase.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                dbHelper.getWritableDatabase();
            }
        });
    }
}
  • 在onCreate() 方法中构建了一个MyDatabaseHelper 对象,并且通过构造函数的参数将数据库名指定为BookStore.db,版本号指定为1,然后在Create database按钮的点击事件里调用了getWritableDatabase() 方法。这样当第一次点击Create database按钮时,就会检测到当前程序中并没有BookStore.db这个数据库,于是会创建该数据库并调用MyDatabaseHelper中的onCreate() 方法,这样Book表也就得到了创建,然后会弹出一个Toast提示创建成功。再次点击Create database按钮时,会发现此时已经存在BookStore.db数据库了,因此不会再创建一次

2、检查数据库是否创建

  • 建好环境变量,将platform-tools目录配置进去
  • 配置好了环境变量之后,就可以使用adb工具了。打开命令行界面,输入adb shell
  • 输入su命令切换成超级管理员,如果进入超级管理员失败,则需要更换模拟器为goole APIs的型号,不能是play,否则会切换失败。
  • 进入到/data/data/com.example.databasetest/databases/目录下,并使用ls 命令查看到该目录里的文件
  • sqlite3 BookStore.db 打开数据库
  • 键入.table 命令 查看有哪些表

3.创建新的表

public class MyDatabaseHelper extends SQLiteOpenHelper {
    public static final String CREATE_BOOK = "create table Book ("
            + "id integer primary key autoincrement, "
            + "author text, "
            + "price real, "
            + "pages integer, "
            + "name text)";
    public static final String CREATE_CATEGORY = "create table Category ("
            + "id integer primary key autoincrement, "
            + "category_name text, "
            + "category_code integer)";
    private Context mContext;
    public MyDatabaseHelper(Context context, String name,
                            SQLiteDatabase.CursorFactory factory, int version) {
        super(context, name, factory, version);
        mContext = context;
    }
    @Override
    public void onCreate(SQLiteDatabase db) {
        db.execSQL(CREATE_BOOK);
        db.execSQL(CREATE_CATEGORY);
        Toast.makeText(mContext, "Create succeeded", Toast.LENGTH_SHORT).show();
    }
    @Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
    }
}

修改MyDatabaseHelper中的代码

@Override
    public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
        db.execSQL("drop table if exists Book");
        db.execSQL("drop table if exists Category");
        onCreate(db);
    }

在onUpgrade() 方法中执行了两条DROP 语句,如果发现数据库中已经存在Book表或Category表了,就将这两张表删除掉,然后再调用onCreate() 方法重新创建。这里先将已经存在的表删除掉,因为如果在创建表时发现这张表已经存在了,就会直接报错

还记得SQLiteOpenHelper的构造方法里接收的第四个参数吗?它表示当前数据库的版本号,之前我们传入的是1,现在只要传入一个比1大的数,就可以让onUpgrade() 方法得到执行了。修改MainActivity中的代码(其实就把1改成了2)

public class MainActivity extends AppCompatActivity {
    private MyDatabaseHelper dbHelper;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        dbHelper = new MyDatabaseHelper(this, "BookStore.db", null, 2);
        Button createDatabase = (Button) findViewById(R.id.create_database);
        createDatabase.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                dbHelper.getWritableDatabase();
            }
        });
    }
}

4、增加数据

  • SQLiteDatabase 中提供了一个insert() 方法,这个方法就是专门用于添加数据的。它接收3个参数,第一个参数是表名,我们希望向哪张表里添加数据,这里就传入该表的名字。第二个参数用于在未指定添加数据的情况下给某些可为空的列自动赋值NULL ,一般我们用不到这个功能,直接传入null 即可。第三个参数是一个ContentValues 对象,它提供了一系列的put() 方法重载,用于向ContentValues 中添加数据

  • 增添一个按钮来增加数据

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        >
        ...
        <Button
            android:id="@+id/add_data"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="Add data"
            />
    </LinearLayout>
    
    public class MainActivity extends AppCompatActivity {
        private MyDatabaseHelper dbHelper;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            dbHelper = new MyDatabaseHelper(this, "BookStore.db", null, 2);
            ...
            Button addData = (Button) findViewById(R.id.add_data);
            addData.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    SQLiteDatabase db = dbHelper.getWritableDatabase();
                    ContentValues values = new ContentValues();
                    // 开始组装第一条数据
                    values.put("name", "The Da Vinci Code");
                    values.put("author", "Dan Brown");
                    values.put("pages", 454);
                    values.put("price", 16.96);
                    db.insert("Book", null, values); // 插入第一条数据
                    values.clear();
                    // 开始组装第二条数据
                    values.put("name", "The Lost Symbol");
                    values.put("author", "Dan Brown");
                    values.put("pages", 510);
                    values.put("price", 19.95);
                    db.insert("Book", null, values); // 插入第二条数据
                }
            });
        }
    }
    
  • 在添加数据按钮的点击事件里面,我们先获取到了SQLiteDatabase 对象,然后使用ContentValues 来对要添加的数据进行组装。如果你比较细心的话应该会发现,这里只对Book表里其中四列的数据进行了组装,id那一列并没给它赋值。这是因为在前面创建表的时候,我们就将id 列设置为自增长了,它的值会在入库的时候自动生成,所以不需要手动给它赋值了。接下来调用了insert() 方法将数据添加到表当中,注意这里我们实际上添加了两条数据,上述代码中使用ContentValues 分别组装了两次不同的内容,并调用了两次insert()方法

  • 查看添加数据是否成功

    • 打开cmd,输入adb shell
    • 输入su,进入管理员模式
    • 定位到文件所在位置: cd /data/data/com.example.databasetest/databases/
    • 进入数据库:sqlite3 BookStore.db
    • 查看有哪些表:.table
    • 查询表中的数据: select * from Book;(注意这个分号不能少!!!)

5.更新数据

  • SQLiteDatabase 中也提供了一个非常好用的update() 方法,用于对数据进行更新,这个方法接收4个参数,第一个参数和insert() 方法一样,也是表名,在这里指定去更新哪张表里的数据。第二个参数ContentValues 对象,要把更新数据在这里组装进去。第三、第四个参数用于约束更新某一行或某几行中的数据,不指定的话默认就是更新所有行

步骤:

  • 1.先添加增加数据按钮

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        >
        ...
        <Button
            android:id="@+id/update_data"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="Update data"
            />
    </LinearLayout>
    
  • 2.添加按钮点击事件:找到id,构建ContentValues对象,前提是调用getWritableDatabase方法

  • 3.添加数据

  • 4.调用update方法,四个参数:这里使用了第三、第四个参数来指定具体更新哪几行。第三个参数对应的是SQL语句的where 部分,表示更新所有name 等于? 的行,而? 是一个占位符,可以通过第四个参数提供的一个字符串数组为第三个参数中的每个占位符指定相应的内容

    public class MainActivity extends AppCompatActivity {
        private MyDatabaseHelper dbHelper;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            dbHelper = new MyDatabaseHelper(this, "BookStore.db", null, 2);
            ...
            Button updateData = (Button) findViewById(R.id.update_data);
            updateData.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    SQLiteDatabase db = dbHelper.getWritableDatabase();
                    ContentValues values = new ContentValues();
                    values.put("price", 10.99);
                    db.update("Book", values, "name = ?", new String[] { "The Da Vinci
                        Code" });
                }
            });
        }
    }
    

6.删除数据

  • 添加按钮

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        >
        ...
        <Button
            android:id="@+id/delete_data"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="Delete data"
            />
    </LinearLayout>
    
  • 调用删除方法

    public class MainActivity extends AppCompatActivity {
        private MyDatabaseHelper dbHelper;
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            dbHelper = new MyDatabaseHelper(this, "BookStore.db", null, 2);
            ...
            Button deleteButton = (Button) findViewById(R.id.delete_data);
            deleteButton.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    SQLiteDatabase db = dbHelper.getWritableDatabase();
                    db.delete("Book", "pages > ?", new String[] { "500" });
                }
            });
        }
    }
    

    7.查询数据

在这里插入图片描述

  • 添加按钮

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:orientation="vertical"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        >
        ...
        <Button
            android:id="@+id/query_data"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="Query data"
            />
    </LinearLayout>
    
  • 查询语句

public class MainActivity extends AppCompatActivity {
    private MyDatabaseHelper dbHelper;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        dbHelper = new MyDatabaseHelper(this, "BookStore.db", null, 2);
        ...
        Button queryButton = (Button) findViewById(R.id.query_data);
        queryButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                SQLiteDatabase db = dbHelper.getWritableDatabase();
                // 查询Book表中所有的数据
                Cursor cursor = db.query("Book", null, null, null, null, null, null);
                if (cursor.moveToFirst()) {
                    do {
                        // 遍历Cursor对象,取出数据并打印
                        String name = cursor.getString(cursor.getColumnIndex
                            ("name"));
                        String author = cursor.getString(cursor.getColumnIndex
                            ("author"));
                        int pages = cursor.getInt(cursor.getColumnIndex("pages"));
                        double price = cursor.getDouble(cursor.getColumnIndex
                            ("price"));
                        Log.d("MainActivity", "book name is " + name);
                        Log.d("MainActivity", "book author is " + author);
                        Log.d("MainActivity", "book pages is " + pages);
                        Log.d("MainActivity", "book price is " + price);
                    } while (cursor.moveToNext());
                }
                cursor.close();
            }
        });
    }
}
  • 首先在查询按钮的点击事件里面调用了SQLiteDatabase的query() 方法去查询
  • 查询完之后就得到了一个Cursor 对象,接着我们调用它的moveToFirst() 方法将数据的指针移动到第一行的位置
  • 调用它的moveToFirst() 方法将数据的指针移动到第一行的位置,然后进入了一个循环当中,去遍历查询到的每一行数据
  • 在这个循环中可以通过Cursor 的getColumnIndex() 方法获取到某一列在表中对应的位置索引,然后将这个索引传入到相应的取值方法中,就可以得到从数据库中读取到的数据了
  • 接着我们使用Log的方式将取出的数据打印出来,借此来检查一下读取工作有没有成功完成
  • 最后别忘了调用close() 方法来关闭Cursor

8.使用SQL操作数据库

上面的语句都太繁琐,直接使用sql语句

1.增加数据
将
    SQLiteDatabase db = dbHelper.getWritableDatabase();
    ContentValues values = new ContentValues();
    // 开始组装第一条数据
    values.put("name", "The Da Vinci Code");
    values.put("author", "Dan Brown");
    values.put("pages", 454);
    values.put("price", 16.96);
    db.insert("Book", null, values); // 插入第一条数据
    values.clear(); 

更换成
    SQLiteDatabase db = dbHelper.getWritableDatabase();
    ContentValues values = new ContentValues();
    db.execSQL("insert into Book(name,author,pages,price) values(?,?,?,?)",
                        new String[]{"love and peace","tanglei","100","5.21"});
2.更新数据
将
   values.put("price", 10.99);
   db.update("Book", values, "name = ?", new String[] { "The Da Vinci Code" });
改成
   db.execSQL("update Book set price = ? where name = ?", new String[] { "10.99", "The Da Vinci Code"});

3.删除数据
将
    db.delete("Book", "pages > ?", new String[] { "500" });
改成
    db.execSQL("delete from Book where pages > ?", new String[] { "500" });

4.查询数据
将
    // 查询Book表中所有的数据
    db.query("Book", null, null, null, null, null, null);

改为
    db.rawQuery("select * from Book", null);

5.使用LitePal操作数据库

1.LitePal简介

  • 是一款开源的Android数据库框架
  • 采用了对象关系映射(ORM)的模式
  • 将开发最常用到的一些数据库功能进行了封装

2.配置

  • 在app/build.gradle里面声明引用

    implementation 'org.litepal.android:core:1.4.1'
    
  • 这样我们就把LitePal成功引入到当前项目中了,接下来需要配置litepal.xml文件.右击app/src/main目录→New→Directory,创建一个assets目录,然后在assets目录下再新建一个litepal.xml文件

    <?xml version="1.0" encoding="utf-8"?>
    <litepal>
        <dbname value="BookStore" ></dbname>
        <version value="1" ></version>
        <list>
        </list>
    </litepal>
    ##其中, <dbname> 标签用于指定数据库名,
        	<version> 标签用于指定数据库版本号,
            <list>标签用于指定所有的映射模型
    
  • 在AndroidManifest.xml中加入

    android:name="org.litepal.LitePalApplication"
    

3.创建和更新数据库

  • 定义一个实体类Book

    public class Book {
        private int id;
        private String author;
        private double price;
        private int pages;
        private String name;
        public int getId() {
            return id;
        }
        public void setId(int id) {
            this.id = id;
        }
        public String getAuthor() {
            return author;
        }
        public void setAuthor(String author) {
            this.author = author;
        }
        public double getPrice() {
            return price;
        }
        public void setPrice(double price) {
            this.price = price;
        }
        public int getPages() {
            return pages;
        }
        public void setPages(int pages) {
            this.pages = pages;
        }
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
    }
    
  • 在litepal.xml中加入映射

    <litepal>
        <dbname value="BookStore" ></dbname>
        <version value="1" ></version>
        <list>
            <mapping class="com.example.litepaltest.Book"></mapping>
        </list>
    </litepal>
    
  • 修改maninactivity中的代码

    public class MainActivity extends AppCompatActivity {
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            Button createDatabase = (Button) findViewById(R.id.create_database);
            createDatabase.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    LitePal.getDatabase();
                }
            });
        }
    }
    

    至此可以创建出一个数据库,如果想要向数据库中加入数据,则需要

    • 在实体类中加入属性和其get\set方法

    • 如果加表的话,需要创建表category的实体类

    • 改完了东西之后,修改litepal.xml文件:版本加1,加入映射

      <?xml version="1.0" encoding="utf-8"?>
      <litepal>
          <dbname value="BookStore" ></dbname>
          <version value="2" ></version>
          <list>
              <mapping class="com.example.litepaltest.Book"></mapping>
              <mapping class="com.example.litepaltest.Category"></mapping>
          </list>
      </litepal>
      
    • 去查看数据库的时候,记得是要进入数据库里面才能看到新建的表,用(.schema)查看字段

4.使用LitePal添加数据

  1. 让实体类继承DataSupport

  2. 修改按钮监听事件

     //添加数据
    Button addData = (Button) findViewById(R.id.add_data);
    addData.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Book book = new Book();
            book.setName("love and peace");
            book.setAuthor("tanglei");
            book.setPages(454);
            book.setPrice(16.96);
            book.setPress("Unknow");
            book.save();
            Toast.makeText(MainActivity.this,"点击了我",Toast.LENGTH_SHORT).show();
        }
    });
    

5.使用LitePal更新数据

方法一

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ...
        Button updateData = (Button) findViewById(R.id.update_data);
        updateData.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Book book = new Book();
                book.setName("The Lost Symbol");
                book.setAuthor("Dan Brown");
                book.setPages(510);
                book.setPrice(19.95);
                book.setPress("Unknow");
                book.save();
                //重点在这
                book.setPrice(10.99);
                book.save();
            }
        });
    }
}

方法二

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ...
        Button updateData = (Button) findViewById(R.id.update_data);
        updateData.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Book book = new Book();
                book.setPrice(14.95);
                book.setPress("Anchor");
                book.updateAll("name = ? and author = ?", "The Lost Symbol", "Dan
                    Brown");
            }
        });
    }
}

6.使用LitePal删除数据

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ...
        Button deleteButton = (Button) findViewById(R.id.delete_data);
        deleteButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                DataSupport.deleteAll(Book.class, "price < ?", "15");
            }
        });
    }
}

调用了DataSupport.deleteAll() 方法来删除数据,其中deleteAll() 方法的第一个参数用于指定删除哪张表中的数据,Book.class就意味着删除Book表中的数据,后面的参数用于指定约束条件

7.使用LitePal查询数据

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        ...
        Button queryButton = (Button) findViewById(R.id.query_data);
        queryButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                List<Book> books = DataSupport.findAll(Book.class);
                for (Book book: books) {
                    Log.d("MainActivity", "book name is " + book.getName());
                    Log.d("MainActivity", "book author is " + book.getAuthor());
                    Log.d("MainActivity", "book pages is " + book.getPages());
                    Log.d("MainActivity", "book price is " + book.getPrice());
                    Log.d("MainActivity", "book press is " + book.getPress());
                }
            }
        });
    }
}
查询Book表中的第一条数据
    Book firstBook = DataSupport.findFirst(Book.class);
查询Book表中的最后一条数据
    Book lastBook = DataSupport.findLast(Book.class);
只查name 和author 这两列的数据
    List<Book> books = DataSupport.select("name", "author").find(Book.class);
只查页数大于400的数据
    List<Book> books = DataSupport.where("pages > ?", "400").find(Book.class);
将查询结果按照书价从高到低排序:desc 表示降序排列,asc 或者不写表示升序排列
    List<Book> books = DataSupport.order("price desc").find(Book.class);
limit() 方法用于指定查询结果的数量,比如只查表中的前3条数据
    List<Book> books = DataSupport.limit(3).find(Book.class);
offset() 方法用于指定查询结果的偏移量,比如查询表中的第2条、第3条、第4条数据
    List<Book> books = DataSupport.limit(3).offset(1).find(Book.class);5个方法进行任意的连缀组合
    List<Book> books = DataSupport.select("name", "author", "pages")
                              .where("pages > ?", "400")
                              .order("pages")
                              .limit(10)
                              .offset(10)
                              .find(Book.class);
                    这段代码就表示,查询Book表中第11~20条满足页数大于400这个条件的name 、author 和
                    pages 这3列数据,并将查询结果按照页数升序排列

);


只查name 和author 这两列的数据
    List<Book> books = DataSupport.select("name", "author").find(Book.class);
只查页数大于400的数据
    List<Book> books = DataSupport.where("pages > ?", "400").find(Book.class);
将查询结果按照书价从高到低排序:desc 表示降序排列,asc 或者不写表示升序排列
    List<Book> books = DataSupport.order("price desc").find(Book.class);
limit() 方法用于指定查询结果的数量,比如只查表中的前3条数据
    List<Book> books = DataSupport.limit(3).find(Book.class);
offset() 方法用于指定查询结果的偏移量,比如查询表中的第2条、第3条、第4条数据
    List<Book> books = DataSupport.limit(3).offset(1).find(Book.class);5个方法进行任意的连缀组合
    List<Book> books = DataSupport.select("name", "author", "pages")
                              .where("pages > ?", "400")
                              .order("pages")
                              .limit(10)
                              .offset(10)
                              .find(Book.class);
                    这段代码就表示,查询Book表中第11~20条满足页数大于400这个条件的name 、author 和
                    pages 这3列数据,并将查询结果按照页数升序排列
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值