Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱
MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina.com

ORM数据库框架 LitePal SQLite


目录

简介

Demo地址

GitHub

litepal-1.6.1.jar

litepal-1.6.1-src.jar

An Android library that makes developers use SQLite database extremely easy.

LitePal是一个开源的Android库,允许开发人员非常容易地使用SQLite数据库。 您可以完成大部分数据库操作,而无需编写SQL语句[statement],包括创建或升级表,crud操作,聚合函数[aggregate functions]等。LitePal的设置也非常简单,您可以在不到5分钟内将其集成到项目中。

特性

  • 使用对象关系映射[object-relational mapping,ORM]模式。
  • 很“轻”,jar包只有100k不到,使用起来比较简单
  • 几乎为零配置,只有一个属性很少的配置文件。
  • 自动维护[Maintains]所有表。例如,创建、更改或删除表。
  • 支持多数据库。
  • 封装的API,用于避免编写SQL语句。
  • 极好用的流式查询API。
  • 作为替代选择,你仍可使用SQL,但使用起来比原始API更易用。

LitePal不管是创建数据库、创建表还是执行增删改查,都是根据Model的类名和属性名,每次都需要进行反射拼装,然后调用Android原生的数据库操作,实现相应的功能。

使用过程

  • 首先引入lib,可以通过gradle引入也可以将下载的litepal.jar包直接放入libs目录下。
  • 然后在assets目录下新建一个 litepal.xml 文件,文件名称不能更改。
  • 然后在 AndroidManifest 中配置一下 LitePalApplication,如果已使用自定义的Application,只需在你的Application的onCreate方法中调用 LitePal.initialize(this) 即可。
  • 接下来创建继承自DataSupport的Mode类,之后这些实体类就拥有了进行CRUD操作的能力,LitePal框架会自动创建好相应的数据表,以及表数据类型和非空约束等。

配置

添加依赖

  1. implementation 'org.litepal.android:java:3.0.0' //2018-10月最新版本
  2. //implementation 'org.litepal.android:kotlin:3.0.0' //kotlin

配置 litepal.xml

在项目的 assets 目录中创建一个 litepal.xml文件,并按以下方式配置。

几个标签的作用:

  • dbname:配置数据库名称
  • version:配置数据库版本每次要升级数据库时,此处的值加1
  • list:配置映射类
  • storag:配置数据库文件的存储位置,只能选择【internal】或【external】

示例:

  1. <?xml version="1.0" encoding="utf-8"?>
  2. <litepal>
  3. <!--定义应用程序的数据库名称。默认情况下,每个数据库名称应以.db结尾。如果您没有使用.db命名数据库端,LitePal会自动为您添加后缀。-->
  4. <dbname value="demo" />
  5. <!--定义数据库的版本。每次要升级数据库时,version标记都会有所帮助。修改您在映射标记中定义的模型,只需将版本值加1,数据库升级将自动处理,你无需关心。-->
  6. <version value="1" />
  7. <!--定义模型,LitePal将为每个映射类创建表。模型中定义的受支持字段将映射到列中。-->
  8. <list>
  9. <mapping class="com.test.model.Reader" />
  10. <mapping class="com.test.model.Magazine" />
  11. </list>
  12. <!--定义.db文件的位置。【internal】表示.db文件将存储在内部存储的数据库文件夹中,无人可以访问(默认值)。【external】表示.db文件将存储在主外部存储设备所在目录的路径中,应用程序可以放置它拥有的每个人都可以访问的持久文件。-->
  13. <storage value="external" />
  14. </litepal>

配置 LitePalApplication

如果没有自定义Application:android:name="org.litepal.LitePalApplication"

如果已自定义Application:LitePal.initialize(this);

始终记得使用 application 作为参数。不要将任何 activity 或 service 等的实例用作参数,以避免内存泄漏。

API

创建表

首先定义模型,例如:

  1. public class Album extends LitePalSupport {
  2. @Column(unique = true, defaultValue = "unknown")
  3. private String name;
  4. private float price;
  5. private byte[] cover;
  6. private List<Song> songs = new ArrayList<Song>();
  7. // generated getters and setters.
  8. ...
  9. }
  1. public class Song extends LitePalSupport {
  2. @Column(nullable = false)
  3. private String name;
  4. private int duration;
  5. @Column(ignore = true)
  6. private String uselessField;
  7. private Album album;
  8. // generated getters and setters.
  9. ...
  10. }

注意,3.0.0之后是继承自 LitePalSupport,之前是继承自 DataSupport

然后将这些 models 添加到litepal.xml的 list 标签中:

  1. <list>
  2. <mapping class="org.litepal.litepalsample.model.Album" />
  3. <mapping class="org.litepal.litepalsample.model.Song" />
  4. </list>

下次操作数据库时将生成上面添加的数据库表。

LitePal不管是创建数据库、创建表还是执行增删改查,都是根据Model的类名和属性名,每次都需要进行反射拼装,然后调用Android原生的数据库操作,实现相应的功能。

更新表

LitePal中的升级表非常简单,只需修改你想要的模型:

  1. public class Album extends DataSupport {
  2. ...
  3. @Column(ignore = true)
  4. private float price;//忽略掉此字段
  5. private Date releaseDate;//添加此字段
  6. }

添加了 releaseDate 字段,并给 price 字段添加了 ignore 注解用以忽略。

然后增加 litepal.xml 中的版本号:<version value="2" />

这些表将在您下次运行数据库时升级,升级后 releaseDate 列将添加到 album 表中,原始的 price 列将被删除。

升级后,除了那些删除的列之外,album 表中的所有数据都将被保留。

但是有些升级条件下LitePal无法兼容的处理数据,这些情况下,升级后表中的所有数据都将被清除:

  • 添加了一个带有 unique = true 注解的字段(因为旧的数据的这个字段的值不满足 unique 条件)
  • 为一个已存在的字段添加了 unique = true 注解(同样是因为旧的数据的这个字段的值不满足 unique 条件)
  • 为一个已存在的字段添加了 nullable = false 注解(因为旧的数据的这个字段的值不满足非 nullable 条件)

一定要注意,进行上述操作会导致数据丢失!

保存数据

所有继承自LitePalSupport的model都有save()方法用于保存数据到数据库:

  1. Album album = new Album();
  2. album.setName("album");
  3. album.setPrice(10.99f);
  4. album.setCover(getCoverImageBytes());
  5. album.save();

更新数据

最简单的方法是使用 save 方法更新 find 找到的记录:

  1. Album albumToUpdate = LitePal.find(Album.class, 1); //3.0.0之前是通过 DataSupport 查找的
  2. albumToUpdate.setPrice(20.99f); //更改 price
  3. albumToUpdate.save();

从LitePalSupport 继承的每个model也都具有 updateupdateAll 方法。 您可以通过指定 ID 更新单个记录:

  1. Album albumToUpdate = new Album();
  2. albumToUpdate.setPrice(20.99f);
  3. albumToUpdate.update(id);

你也可以通过使用 where 语句一次更新多条数据:

  1. Album albumToUpdate = new Album();
  2. albumToUpdate.setPrice(20.99f);
  3. albumToUpdate.updateAll("name = ?", "album");

删除数据

  1. LitePal.delete(Song.class, id); //删除一条数据
  2. DataSupport.deleteAll(Song.class, "duration > ?" , "350"); //删除多条数据

查找数据

  1. Song song = LitePal.find(Song.class, id); //通过id查找单条数据
  2. List<Song> allSongs = LitePal.findAll(Song.class); //查找全部数据
  3. List<Song> songs = LitePal.where("name like ? and duration < ?", "song%", "200") //条件查询
  4. .order("duration")
  5. .find(Song.class);

异步操作

默认情况下,每个数据库操作都在主线程上,如果您的操作可能花费很长时间,例如保存或查询大量记录,您可能希望使用异步操作。LitePal支持所有crud方法的异步操作。

例如在后台线程中异步查找song表中的所有记录:

  1. LitePal.findAllAsync(Song.class).listen(new FindMultiCallback<Song>() {
  2. @Override
  3. public void onFinish(List<Song> t) {
  4. //异步返回查询结果
  5. }
  6. });

在后台线程中异步保存数据:

  1. album.saveAsync().listen(new SaveCallback() {
  2. @Override
  3. public void onFinish(boolean success) {
  4. //异步返回保存结果
  5. }
  6. });

多库操作(动态创建数据库)

如果您的应用需要多个数据库,LitePal会完全支持它。您可以在运行时创建任意数量的数据库。例如:

  1. LitePalDB litePalDB = new LitePalDB("demo2", 1);
  2. litePalDB.addClassName(Singer.class.getName());
  3. litePalDB.addClassName(Album.class.getName());
  4. litePalDB.addClassName(Song.class.getName());
  5. LitePal.use(litePalDB);

这将创建一个包含 singer, album 和 song 表的名为 demo2 的数据库。

创建一个配置与 litepal.xml 相同的新的数据库:LitePal.use(LitePalDB.fromDefault("newdb"));

切换回默认数据库:LitePal.useDefault();

通过数据库名称删除数据库LitePal.deleteDatabase("newdb");

监听数据库的创建和更新

  1. LitePal.registerDatabaseListener(new DatabaseListener() {
  2. @Override
  3. public void onCreate() {
  4. // fill some initial data
  5. }
  6. @Override
  7. public void onUpgrade(int oldVersion, int newVersion) {
  8. // upgrade data in db
  9. }
  10. });

混淆

如果您要在项目中启用ProGuard,您需要添加以下内容:

  1. -keep class org.litepal.** {
  2. *;
  3. }
  4. -keep class * extends org.litepal.crud.DataSupport {
  5. *;
  6. }
  7. -keep class * extends org.litepal.crud.LitePalSupport {
  8. *;
  9. }

测试demo

实体类

  1. public class Album extends LitePalSupport {
  2. @Column(unique = true, defaultValue = "包青天")
  3. private String name;
  4. private int age;//新增一个字段时需要更改数据库版本,否则操作数据时会失败
  5. private float price;
  6. @Column(ignore = true)//忽略掉的字段,此字段的值不会保存到数据库中
  7. private int size;
  8. //必须有一个默认的、public的无参构造器,否则执行 update 等语句时会崩溃
  9. public Album() {
  10. }
  11. //省略了 set/get 方法,以及我添加的 Build 相关的代码
  12. }

测试类

  1. public class LitePalActivity extends ListActivity {
  2. protected void onCreate(Bundle savedInstanceState) {
  3. super.onCreate(savedInstanceState);
  4. String[] array = {"findAll()",
  5. "save() ",
  6. "find() 和 save()",
  7. "update()",
  8. "updateAll()",
  9. "delete() 和 deleteAll()",
  10. "fluent query",
  11. "Async operations: saveAsync() + listen()",
  12. "Async operations: findAllAsync() + listen()",
  13. };
  14. setListAdapter(new ArrayAdapter<>(this, android.R.layout.simple_list_item_1, Arrays.asList(array)));
  15. }
  16. @Override
  17. protected void onListItemClick(ListView l, View v, int position, long id) {
  18. int random = new Random().nextInt(5);
  19. switch (position) {
  20. case 0: //findAll()
  21. showTips(new Gson().toJson(LitePal.findAll(Album.class))); //[{"age":1,"name":"包青天1","price":1.0,"size":0,"baseObjId":1}]
  22. break;
  23. case 1: //save()
  24. Album saveAlbum = Album.newBuilder().name("包青天" + random).age(random).price(random).size(random).build();
  25. showTips(saveAlbum.save() + " " + new Gson().toJson(saveAlbum));
  26. break;
  27. case 2: //find() 和 save() 和 findAll
  28. Album findAlbum = LitePal.find(Album.class, random);
  29. if (findAlbum != null) {
  30. findAlbum.setPrice(9.99f); //仅更改指定的值
  31. showTips(random + " " + findAlbum.save());
  32. } else {
  33. showTips("没有找到id=" + random + "的数据");
  34. }
  35. break;
  36. case 3: //update()
  37. Album updateAlbum = Album.newBuilder().name("包青天0").age(random + 100).build();
  38. //注意:如果指定为 unique 字段的值已存在,则会报 DataSupportException: UNIQUE constraint failed: album.name
  39. try {
  40. int rowsAffected = updateAlbum.update(random); //未指定的字段的值不会更改,比如这里不会更改 price的值
  41. showTips(random + " 更新" + (rowsAffected == 0 ? "失败(未找到指定 id 的数据)" : rowsAffected + "条"));
  42. } catch (Exception e) {
  43. e.printStackTrace();
  44. showTips(random + " 更新失败(主键冲突 UNIQUE constraint failed )");
  45. }
  46. break;
  47. case 4: //updateAll()
  48. Album whereAlbum = Album.newBuilder().age(random + 200).price(random + 200).size(random + 200).build();
  49. int rowsAffected = whereAlbum.updateAll("name like ? and age > ?", "包青天%", Integer.toString(3));
  50. showTips(random + " 更新" + (rowsAffected == 0 ? "失败(未找到指定 id 的数据)" : rowsAffected + "条"));
  51. break;
  52. case 5://delete() 和 deleteAll()
  53. int rowsAffected1 = LitePal.delete(Album.class, random);
  54. int rowsAffected2 = LitePal.deleteAll(Album.class, "age < ?", Integer.toString(200));
  55. showTips(random + " " + rowsAffected1 + " " + rowsAffected2);
  56. break;
  57. case 6: //fluent query
  58. List<Album> albumList = LitePal.where("name like ? and price <= ?", "包青天%", Float.toString(3.0f))
  59. .order("name")
  60. .find(Album.class);
  61. showTips(new Gson().toJson(albumList));
  62. break;
  63. case 7: //Async operations: saveAsync() + listen()
  64. Album saveAsyncAlbum = Album.newBuilder().name("包青天" + random).age(random).price(random).size(random).build();
  65. saveAsyncAlbum.saveAsync()
  66. .listen(success -> showTips(random + "," + success + "," + (Looper.myLooper() == Looper.getMainLooper())));//主线程
  67. break;
  68. case 8: //Async operations: findAllAsync() + listen()
  69. LitePal.findAllAsync(Album.class)
  70. .listen(list -> showTips(new Gson().toJson(list)));
  71. break;
  72. }
  73. }
  74. private void showTips(String s) {
  75. Toast.makeText(this, s, Toast.LENGTH_SHORT).show();
  76. Log.i("bqt", s);
  77. }
  78. }

2018-5-28

ORM数据库框架 LitePal SQLite MD的更多相关文章

  1. ORM数据库框架 greenDAO SQLite MD

    Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...

  2. ORM数据库框架 SQLite 常用数据库框架比较 MD

    Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...

  3. ORM数据库框架 SQLite ORMLite MD

    Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...

  4. SQlite数据库框架:LitePal

    常用的数据库框架Android的发展的速度是难以置信的,Android出来哪一年我还在小学上学很,还能很清楚的记得,那年一切,但是那个时候的我怎么可能也不会想到自己将来会要去做Android.Andr ...

  5. Android开源库--ActiveAndroid(active record模式的ORM数据库框架)

    Github地址:https://github.com/pardom/ActiveAndroid 前言 我一般在Android开发中,几乎用不到SQLlite,因为一些小数据就直接使用Preferen ...

  6. android高效ORM数据库框架greenDao使用

    因为项目中多处用到了数据库,需要对数据库频繁的读写操作,虽然android 自带的SQLiteOpenHelper的.这种方式比较方便易懂,但是在使用过程中需要写很多的sql语句,而且需要及时的关闭和 ...

  7. 数据库框架 Litepal

    1.导包 dependencies {   compile 'org.litepal.android:core:1.4.1' } 2.在asstes中建立litepal.xml文件 <?xml ...

  8. LitePal——Android数据库框架完整使用手册

    LitePal for Android LitePal是一个开源的Android库,使开发人员使用SQLite数据库非常简单.您无需编写任何SQL语句就可以完成大部分数据库操作,包括创建或升级表,增. ...

  9. Android数据库框架——GreenDao轻量级的对象关系映射框架,永久告别sqlite

    Android数据库框架--GreenDao轻量级的对象关系映射框架,永久告别sqlite 前不久,我在写了ORMLite这个框架的博文 Android数据库框架--ORMLite轻量级的对象关系映射 ...

随机推荐

  1. PHP之PDO_MYSQL扩展安装步骤(转)

    看到CakePHP文档要求安装pdo_mysql扩展,于是就尝试安装了一下. 这里我的系统是CentOS 6.0.如果你的系统是其他版本的Linux/Unix,可以参考.如果你的系统是Windows的 ...

  2. HDU 4745 Two Rabbits (2013杭州网络赛1008,最长回文子串)

    Two Rabbits Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others)Tota ...

  3. POJ 2546 &amp; ZOJ 1597 Circular Area(求两圆相交的面积 模板)

    题目链接: POJ:http://poj.org/problem? id=2546 ZOJ:problemId=597" target="_blank">http: ...

  4. OAuth2.0网页授权 提示未关注该测试号

    用无高级接口权限的公众号使用别人的appid和appsecret在网页中获取用户信息时,提示未关注该测试号. 搜集各种资料才发现是因为 测试帐号只能对关注者网页授权,正式帐号可以对未关注者授权

  5. EZ1105

    http://www.godexintl.com/cn/product/type/model/EZ1105

  6. TVB三个台

    翡翠台http://token.tvb.com/stream/live/hls/mobilehd_jade.smil 高清翡翠,http://token.tvb.com/stream/live/hls ...

  7. Managing DbContext the right way with Entity Framework 6: an in-depth guide by mehdime

    UPDATE: the source code for DbContextScope is now available on GitHub: DbContextScope on GitHub. A b ...

  8. Ubuntu下配置用msmtp发送gmail邮件

    从https://gist.github.com/JosefJezek/6194563上找到的一个配置脚本,下载后添加可执行权限,然后运行即可. 下面是脚本setup-msmtp-for-gmail. ...

  9. C# String.split()用法小结

    第一种方法 string s=abcdeabcdeabcde; string[] sArray=s.Split('c') ; foreach(string i in sArray) Console.W ...

  10. 技术人生:Knowing when or where it’s appropriate to use a technique or tool is just as important as knowing how to use it.

    Knowing when or where it’s appropriate to use a technique or tool is just as important as knowing ho ...