Android—LitePal操作数据库

简介

LitePal 是一款 Android 数据库框架,它采用了对象关系映射(ORM)的模式。

Demo下载

LitePal 的GitHub地址:https://github.com/LitePalFramework/LitePal

LitePal Demo 的个人GitHub地址:https://github.com/linweimao/LitePal

LitePal Demo 百度网盘链接:https://pan.baidu.com/s/1qgLFDMDPjBl6uSxCP0ovPQ
提取码:rvkv

LitePal采用的是对象关系映射(ORM)模式,那么什么是对象关系映射呢?

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

框架步骤

配置 LitePal

编辑app/build.gradle文件,在 dependencies 闭包中添加如下内容:

implementation 'org.litepal.android:java:3.0.0'

新建 assets 文件夹与创建 litepal.xml 文件

assets 文件夹的创建方式:右击app/src/main 目录—New—Directory,创建一个 assets 目录,然后在 assets 目录下新建一个 litepal.xml 文件,litepal.xml 的文件内容如下:

<?xml version="1.0" encoding="utf-8"?>
<litepal>
    <dbname value="BookStore"></dbname>
    <version value="2"></version>

    <list>
        <mapping class="com.lwm.litepaltest.Book"></mapping>
        <mapping class="com.lwm.litepaltest.Category"></mapping>
    </list>
</litepal>

dbname标签用于指定数据库名

version 标签用于指定数据库版本号

dbname标签用于指定所有的映射模型

配置 AndroidManifest.xml

 将下面的代码添加到 <application 下
 android:name="org.litepal.LitePalApplication"

此时 LitePal 的配置工作全部完成。

创建和升级数据库

定义一个 Book 类和 Category 类

public class Book {
    private int id;
    private String author;
    private double price;
    private int pages;
    private String name;
    private String press;

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

    public String getPress() {
        return press;
    }

    public void setPress(String press) {
        this.press = press;
    }
}
public class Category {
    private int id;
    private String categoryName;

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

以上是典型的Java bean,Book 类对应数据库中的 Book 表,而类中的每一个字段分别对应了表中的每一个列,这就是对象关系映射最直观的体验
 

将 Book 类和 Category 类添加到映射模型列表

在 litepal.xml 进行修改,由于上面我们已经将Book 类和 Category 类添加到映射模型列表所以不用再进行添加了。

   <mapping class="com.lwm.litepaltest.Book"></mapping>
   <mapping class="com.lwm.litepaltest.Category"></mapping>

这里使用 mapping 标签来声明我们要配置的映射模型类,注意一定要使用完整的类名,不管有多少模型类需要映射,都使用同样的方式配置在 lite 标签下
 

创建数据库

createDatabase.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                LitePal.getDatabase();
            }
});

调用 LitePal.getDatabase(); 方法就是一次最简单的数据库操作,只要点击一下按钮,数据库就会自动创建完成
 

查看数据库是否被创建(查看的时候记得运行模拟器)

win+R输入cmd

在窗口输入 adb shell

输入 su 切换模式为超级管理员,这时你可以访问模拟器中的一切数据,如果你的命令行上显示的是 $ 符号,那么就表示你现在是普通管理员。

如果输入 su 报 /system/bin/sh: su: not found 错误,那么你可以参考https://blog.csdn.net/weixin_42814000/article/details/104994222

在输入 ==cd /data/data/com.lwm.litepaltest/databases/==进到数据库下

注意:com.lwm.litepaltest对应项目文件目录,如下
在这里插入图片描述
输入 ls 查看数据库是否被创建
在这里插入图片描述
接下来输入 sqlite3 BookStore.db 进入到数据库
在这里插入图片描述
输入 .schema查看建表语句
在这里插入图片描述
当我们升级数据库时,我们需要把之前的表 drop 掉,然后在重新创建,这其实是一个非常严重的问题,因为这样会造成数据丢失,每当升级一次数据库,之前表中的数据就全没了,在使用 LitePal 时如果要升级数据库,只用将版本号加 1 就可以了(修改 assets 的 litepal.xml 文件的 version 标签),此时 LitePal 会自动保留之前表中的所有数据
 

LitePal 添加数据

LitePal 添加数据的方式:创建模型类的实例,在将所有要存储的数据设置好,最后调用一下 save() 方法就可以了

LitePal 进行表管理操作时不需要模型类有任何的继承结构,但是进行CRUD 操作时就不行了,需要继承自 LitePalSupport 类才行。

public class Book extends LitePalSupport {
    private int id;
    private String author;
    private double price;
    private int pages;
    private String name;
    private String press;

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

    public String getPress() {
        return press;
    }

    public void setPress(String press) {
        this.press = press;
    }
}

开始向 Book 表中添加数据。

 // 添加数据
        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();
            }
        });

首先创建出一个 Book 实例,然后调用 Book 类中的各种 set 方法对数据进行设置,最后在调用 book.save(); 方法就能完成数据添加操作了。

重新运行程序,点击一下 Add data 按钮,此时数据应该已经添加成功了,输入SQL查询语句 select * from Book
在这里插入图片描述
 

LitePal 更新数据

首先最简单的更新方式就是对已存储的对象重新设值,然后重新调用 book.save(); 方法即可
 

什么是已存储对象呢?

对于 LitePal 来说,对象是否已存储就是根据调用 model.isSaved( ) 方法的结果来判断的,返回 true 就表示已存储,返回 false 就表示未存储。那么接下来的问题就是,什么情况下会返回 true ,什么情况会返回 false 呢?

实际上只有在两种情况下 model.isSaved( ) 方法才会返回 true ,一种情况是已经调用过 model.save() 方法去添加数据,此时 model 会被认为是已存储的对象。另一种情况是 model 对象是通过 LitePal 提供的查询 API 查出来的,由于是从数据库中查到的对象,因此也会被认为是已存储的对象。
 
这种更新方式只能对已存储的对象进行操作,限制性比较大

        // 这种更新方式只能对已存储的对象进行操作,限制性比较大
        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();
            }
        });

比较灵巧的更新方式

        // 比较灵巧的更新方式
        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");
                book.save();
            }
        });

在使用 updateAll( ) 方法时,还有一个非常重要的知识点是你需要知晓的
 
当你想把一个字段的值更新成默认值时,是不可以使用上面的方式来 set 数据的。在 Java 中任何一种数据类型的字段都会有默认值,例如 int 类型的默认值是 0 ,boolean 类型的默认值是 false, String 类型的默认值是 null 。那么当 new 出一个 Book 对象时,其实所有的字段都已经被初始化成默认值了,比如说 pages 字段的值就是 0 。因此,如果我们想把数据库表中的 pages 列更新为 0 ,直接调用 book.setPages(0); 是不可以的,因此即使不调用这行代码,pages 字段本身也是 0 ,LitePal 此时是不会对这个列进行更新的。对于所有想要将为数据更新成默认值的操作,LitePal 统一提供了一个 setToDefault( ) 方法,然后传入相应的列名就可以实现了。

        // 将某个字段的数据更新为默认值(例如:int的默认值为0 , boolean的默认值为false , String的默认值为null)
        updateData.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Book book = new Book();
                book.setToDefault("pages");
                book.updateAll();
            }
        });

这个代码的意思是,将所有书的页数都更新为 0 ,因为 updateAll( ) 方法中没有指定约束条件,因此更新操作对所有数据都生效。
 

LitePal 删除数据

        // 删除数据
        deleteButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                LitePal.deleteAll(Book.class, "price < ?", "15");
            }
        });

这里调用了 LitePal.deleteAll( ); 方法来删除数据,其中的 deleteAll( ) 方法的第一个参数用于指定删除哪张表中的数据,Book.class 就意味着删除 Book 表中的数据,后面的参数用于指定约束条件。这行代码的意思是:删除 Book 表中价格低于 15 的书。
 
如果 deleteAll( ) 方法如果不指定约束条件,那么就是要删除表中所有的数据,这一点和 updateAll( ) 方式是相似的。

LitePal 查询数据

查询 Book 表中的所有数据。

List<Book> books = LitePal.findAll(Book.class);

只需要调用一下 findAll( ) 方法,然后通过 Book.class 参数指定查询 Book 表就可以。另外,findAll( ) 方法的返回值是一个 Book 类型的 List 集合,LitePal 已经自动帮我们完成了赋值操作了。

public void query() {
        // 打印查询到的数据
        queryData.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                // 查询 Book 表的所有数据,
                // 与 Cursor cursor = db.query("Book",null,null,null,null,null,null);功能一样
                // findAll() 方法通过 Book.class 参数指定查询 Book 表,
                // 另外, findAll() 方法的返回值实体个 Book 类型的List 集合,也就是说 LitePal 自动帮我们完成了赋值操作
                List<Book> books = LitePal.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());
                }
            }
        });

        // 打印第一条数据
        queryData1.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Book firstBook = LitePal.findFirst(Book.class);
                Log.d(TAG, "book name is: " + firstBook.getName());
                Log.d(TAG, "book author is: " + firstBook.getAuthor());
                Log.d(TAG, "book pages is: " + firstBook.getPages());
                Log.d(TAG, "book price is: " + firstBook.getPrice());
                Log.d(TAG, "book press is: " + firstBook.getPress());
            }
        });

        // 打印最后一条数据
        queryData2.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Book lastBook = LitePal.findLast(Book.class);
                Log.d(TAG, "book name is: " + lastBook.getName());
                Log.d(TAG, "book author is: " + lastBook.getAuthor());
                Log.d(TAG, "book pages is: " + lastBook.getPages());
                Log.d(TAG, "book price is: " + lastBook.getPrice());
                Log.d(TAG, "book press is: " + lastBook.getPress());
            }
        });

        // select() 方法用于指定查询哪几列,对应了 SQL中的 select 关键字。查询name和author两列的数据
        queryData3.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                List<Book> books = LitePal.select("name", "author").find(Book.class);
                Log.d(TAG, "book name is: " + books.get(0).getName());
                Log.d(TAG, "book author is: " + books.get(0).getAuthor());
            }
        });

        // where() 方法用于指定查询的约束条件,对应了SQL当中的where关键字。比如查询页数大于400的数据
        queryData4.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                List<Book> books = LitePal.where("pages > ?", "400").find(Book.class);
                Log.d(TAG, "book name is: " + books.get(0).getName());
                Log.d(TAG, "book author is: " + books.get(0).getAuthor());
                Log.d(TAG, "book pages is: " + books.get(0).getPages());
                Log.d(TAG, "book price is: " + books.get(0).getPrice());
                Log.d(TAG, "book press is: " + books.get(0).getPress());
            }
        });

        // order() 方法用于指定结果的排序方式,对应了SQL中的 order by关键字。比如将查询结果按照书价格从高到底进行排序
        queryData5.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                List<Book> books = LitePal.order("price desc").find(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());
                }
            }
        });

        // limit() 方法用于指定查询结果的数量
        queryData6.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                List<Book> books = LitePal.limit(3).find(Book.class);
                Log.d(TAG, "book name is: " + books.get(0).getName());
                Log.d(TAG, "book author is: " + books.get(0).getAuthor());
                Log.d(TAG, "book pages is: " + books.get(0).getPages());
                Log.d(TAG, "book price is: " + books.get(0).getPrice());
                Log.d(TAG, "book press is: " + books.get(0).getPress());
            }
        });

        // offset() 方法用于指定查询结果的偏移量
        queryData7.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                List<Book> books = LitePal.limit(3).offset(1).find(Book.class);
                Log.d(TAG, "book name is: " + books.get(0).getName());
                Log.d(TAG, "book author is: " + books.get(0).getAuthor());
                Log.d(TAG, "book pages is: " + books.get(0).getPages());
                Log.d(TAG, "book price is: " + books.get(0).getPrice());
                Log.d(TAG, "book press is: " + books.get(0).getPress());
            }
        });

        // 连缀组合查询
        queryData8.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                List<Book> books = LitePal.select("name", "author", "pages")
                        .where("pages > ?", "400")
                        .order("pages")
                        .limit(10)
                        .offset(10)
                        .find(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());
                }
            }
        });

        // 使用原生SQL查询
        queryData9.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Cursor cursor = LitePal.findBySQL("select * from Book where pages > ? and price < ?", "400", "20");
                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("name"));
                        String press = cursor.getString(cursor.getColumnIndex("name"));
                        Log.d(TAG, "book name is: " + name);
                        Log.d(TAG, "book author is: " + author);
                        Log.d(TAG, "book pages is: " + pages);
                        Log.d(TAG, "book price is: " + price);
                        Log.d(TAG, "book press is: " + press);
                    } while (cursor.moveToNext());
                }
                cursor.close();
            }
        });

    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值