android从放弃到坚持放弃第六课(下)

来源:互联网 发布:mac系统网络恢复 编辑:程序博客网 时间:2024/06/06 20:48

使用LitePal操作数据库

  • 使用LitePal操作数据库
    • 使用LitePal简介
    • 创建和升级数据库
    • 添加数据
    • 更新数据
    • 删除数据
    • 查询数据
  • 总结
  • 问题

使用LitePal简介

这是我学习的第一个开源库——LitePal。LitePal是一款开源的Android数据库框架,它采用对象关系映射(ORM)的模式,并将我们平时开发的最常用的一些数据库功能进行了封装.GitHub:Click me

他在readme.md文件中写了Quick setup。不妨看看。

首先在闭包中添加

dependencies {    compile fileTree(dir: 'libs', include: ['*.jar'])    androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {        exclude group: 'com.android.support', module: 'support-annotations'    })    compile 'com.android.support:appcompat-v7:25.3.1'    testCompile 'junit:junit:4.12'    compile 'org.litepal.android:core:1.5.1'}

配置litepal.xml文件。右键app/src/main目录→New→Directory,创建一个assets目录,然后在assets目录下新建一个litepal.xml文件

new一个File→litepal.xml的文件

<?xml version="1.0" encoding="utf-8"?><litepal>    <!--        Define the database name of your application.         By default each database name should be end with .db.         If you didn't name your database end with .db,         LitePal would plus the suffix automatically for you.        For example:            <dbname value="demo" />    -->    <dbname value="Bookstore2" />    <!--        Define the version of your database. Each time you want         to upgrade your database, the version tag would helps.        Modify the models you defined in the mapping tag, and just         make the version value plus one, the upgrade of database        will be processed automatically without concern.            For example:            <version value="1" />    -->    <version value="1" />    <!--        Define your models in the list with mapping tag, LitePal will        create tables for each mapping class. The supported fields        defined in models will be mapped into columns.        For example:            <list>            <mapping class="com.test.model.Reader" />            <mapping class="com.test.model.Magazine" />        </list>    -->    <list>    </list>    <!--        Define where the .db file should be. "internal" means the .db file        will be stored in the database folder of internal storage which no        one can access. "external" means the .db file will be stored in the        path to the directory on the primary external storage device where        the application can place persistent files it owns which everyone        can access. "internal" will act as default.        For example:        <storage value="external" />    --></litepal>

This is the only configuration file, and the properties are simple.

  • dbname configure the database name of project.
  • version configure the version of database. Each time you want to upgrade database, plus the value here.
  • list configure the mapping classes.
  • storage configure where the database file should be stored. internal and external are the only valid options.

显而易见:标签用于指定数据库名,标签用于指定数据库版本号,标签用于指定所有的映射模型。

配置LitePalApplication,修改AndroidMainfest.xml:

<manifest>    <application        android:name="org.litepal.LitePalApplication"        ...    >        ...    </application></manifest>

配置好了。


创建和升级数据库

先创建一个类继承SQLiteOpenHelper,然后在onCreate()方法来编写建表语句来实现,而使用LitePal就方便多了。

我们使用的编程语言是面向对象编程语言,而使用的数据库则是关系型数据库,那么将面向对象的语言和面向关系的数据库之间建立一种映射关系,这就是对象关系映射。

我们可以用面向对象的四维来操作数据库。

新建Book2类

package com.example.wrjjrw.litepaltest;import org.litepal.crud.DataSupport;/** * Created by wrjjrw on 2017/4/12. */public class Book extends DataSupport{    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;    }}

Tips:可以alt+insert快速补全

添加litepal.xml:

<?xml version="1.0" encoding="utf-8" ?><litepal>    <dbname value = "Bookstore"> </dbname>    <version value = '1'></version>    <list>        <mapping class = "com.example.wrjjrw.litepaltest.Book"></mapping>    </list></litepal>

标签来声明我们要配置的映射模型类,注意一定要使用完整的类名。

xml不再贴代码了:

        Button createLitepalDatabase = (Button) findViewById(R.id.create_litepal);        createLitepalDatabase.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                Connector.getDatabase();            }        });

调用Connector.getDatabase()方法就是一次最简单的数据库操作,只要点击一下,就可以创建了.

若你想添加一个列(比如press),就可以直接修改Book里的代码,记得要generate他的getter和setter()函数。

如果你还想添加一张表,只需要新建一个类即可。

比如Category:

public class Category extends DataSupport{    private int id;    private String categoryName;    private int categoryCode;    public int getId() {        return id;    }    public void setId(int id) {        this.id = id;    }    public String getCategoryName() {        return categoryName;    }    public void setCategoryName(String categoryName) {        this.categoryName = categoryName;    }    public int getCategoryCode() {        return categoryCode;    }    public void setCategoryCode(int categoryCode) {        this.categoryCode = categoryCode;    }}

然后在litepal.xml中添加一个mapping就可以了(别忘记了版本号。)

<?xml version="1.0" encoding="utf-8" ?><litepal>    <dbname value = "Bookstore"> </dbname>    <version value = '2'></version>    <list>        <mapping class = "com.example.wrjjrw.litepaltest.Book"></mapping>        <mapping class="com.example.wrjjrw.litepaltest.Category" />    </list></litepal>

添加数据

在MainActivity:

java
Button addData = (Button) findViewById(R.id.Lite_add_database);
addData.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Book book = new Book();
book.setName("The Da Vinci Code");
book.setAuthor("Dan Brown");
book.setPages(454);
book.setPrice(16.96);
book.setPress("Unknow");
book.save();
}
});

可以看到这样的存储数据更简单。


更新数据

        Button updateData = (Button) findViewById(R.id.Lite_update_database);        updateData.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                Book book = new Book();                book.setAuthor("The Lost Symbol");                book.setPages(510);                book.setPress("Unknow");                book.save();                book.setPrice(19.95);                book.save();            }        });

对,没错,就这样。。。。

另外一种方式:

        Button updateData = (Button) findViewById(R.id.Lite_update_database);        updateData.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                Book book = new Book();                book.setAuthor("The Lost Symbol");                book.setPages(510);                book.setPress("Unknow");                book.save();                book.setPrice(19.95);                book.save();                Book book2 = new Book();                book2.setPrice(14.95);                book2.setPress("Anchor");                book2.updateAll("name = ? and author = ?", "The Lost Symbol", "Dan Brown");            }        });

我们调用了updateAll()的方法执行更新操作。(where参数更加简洁了,但是如果不指定条件语句的话,就是默认所有数据了)

可以看看他的源码:

    /**     * Updates all records with details given if they match a set of conditions     * supplied. This method constructs a single SQL UPDATE statement and sends     * it to the database.     *      * <pre>     * Person person = new Person();     * person.setName(&quot;Jim&quot;);     * person.updateAll(&quot;name = ?&quot;, &quot;Tom&quot;);     * </pre>     *      * This means that all the records which name is Tom will be updated into     * Jim.<br>     *      * <b>Note: </b> 1. If you set a default value to a field, the corresponding     * column won't be updated. Use {@link #setToDefault(String)} to update     * columns into default value. 2. This method couldn't update foreign key in     * database. So do not use setXxx to set associations between models.     *      * @param conditions     *            A string array representing the WHERE part of an SQL     *            statement. First parameter is the WHERE clause to apply when     *            updating. The way of specifying place holders is to insert one     *            or more question marks in the SQL. The first question mark is     *            replaced by the second element of the array, the next question     *            mark by the third, and so on. Passing empty string will update     *            all rows.     * @return The number of rows affected.     */public synchronized int updateAll(String... conditions) {        try {            UpdateHandler updateHandler = new UpdateHandler(Connector.getDatabase());            int rowsAffected = updateHandler.onUpdateAll(this, conditions);            getFieldsToSetToDefault().clear();            return rowsAffected;        } catch (Exception e) {            throw new DataSupportException(e.getMessage(), e);        }    }
* <b>Note: </b> 1. If you set a default value to a field, the corresponding* column won't be updated. Use {@link #setToDefault(String)} to update* columns into default value. 2. This method couldn't update foreign key in* database. So do not use setXxx to set associations between models.

有没有看到上面这句话,如果我们想把值改成默认值的话,就需要使用

                book.setToDefault("pages");                book.updateAll();

上面这句话,我们更新了所有的书的页数,都是0了。


删除数据

        Button deleteButton = (Button) findViewById(R.id.Lite_delete_database);        deleteButton.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                DataSupport.deleteAll(Book.class, "price < ?", "15");            }        });

删除和跟新差不多是一个道理


查询数据

讲道理,这里应该是最复杂的。在这里,问题就不大了。

这里只要用泛型就可以了findAll了,炒鸡方便

        Button queryBotton = (Button) findViewById(R.id.Lite_query_database);        queryBotton.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                List<Book> books = DataSupport.findAll(Book.class);                for(Book book:books){                    Log.d(Tag, "Book name is " + book.getName());                    Log.d(Tag, "Book author is " + book.getAuthor());                    Log.d(Tag, "Book pages is " + book.getPages());                    Log.d(Tag, "Book price is " + book.getPrice());                    Log.d(Tag, "Book press is " + book.getPress());                    Toast.makeText(MainActivity.this, book.getName()+"costs"+book.getPrice(),                            Toast.LENGTH_LONG).show();                }            }        });

除此之外还有以下语句:

Book firstBook = DataSupport.findFirst(Book.class);Book lastBook = DataSupport.findLast(Book.class);//只查询几列的数据List<Book> books2 = DataSupport.select("name", "author").find(Book.class);//指定查询的约束条件List<Book> books3 = DataSupport.where("pages > ?", "400").find(Book.class);//指定结果的排序 desc降序, asc或者默认即升序List<Book> books4 = DataSupport.order("price desc").find(Book.class);//指定查询结果的数量List<Book> books5 = DataSupport.limit(3).find(Book.class);// 指定结果的偏移量,比如要查询表中的第2,3,4条数据List<Book> books6 = DataSupport.limit(3).offset(1).find(Book.class);//将以上方法组合List<Book> books7 = DataSupport.select("name", "author", "pages").where("pages > ?", "400").order("pages").limit(3).offset(1).find(Book.class);//LitePal也同样支持原生的SQL来查询Cursor c = DataSupport.findBySQL("select * from Book where pages > " +"? and price < ?","400","20");

//但原生的查询也需要原生的读取,因为上面的是Cursor对象。


总结

数据库基础知识不扎实,需要好好巩固一下。

总共有三部分知识,文件储存,IO编程不熟练

SharedPreferences存储以及数据库知识,需要勤加练习呐。。


问题:

  1. Error:Execution failed for task ‘:app:transformClassesWithDexForDebug’.

    com.android.build.api.transform.TransformException: com.android.ide.common.process.ProcessException: java.util.concurrent.ExecutionException: com.android.dex.DexException: Multiple dex files define Lorg/litepal/LitePal;

答:依赖包重复了。

  1. 有没有文档可供查询:

答:Click me

0 0
原创粉丝点击