开源数据库 LitePal 学习,强大好使的 CRUD

denckom 8年前
   <h3>LitePal 简介</h3>    <p>LitePal 是一款开源的 Android 数据库框架,它采用了对象关系映射(ORM)的模式,将我们平时使用的一些数据库(比如 Sqlite)功能进行了封装。</p>    <h3>配置</h3>    <p>第一步</p>    <p>和我们平时使用开源库一样,在项目的 build.gradle 文件下的 dependencies 闭包中添加依赖:</p>    <pre>  <code class="language-java">compile 'org.litepal.android:core:1.4.1'</code></pre>    <p>第二步</p>    <p>需要配置 litepal.xml 文件,在 app/src/main 目录右键 -> New -> Directory , 创建一个 assets 目录,在该目录下新建一个 litepal.xml 文件,编辑内容如下:</p>    <pre>  <code class="language-java"><?xml version="1.0" encoding="utf-8" ?>  <litepal>        <dbname value="AndroidDevelop"></dbname>        <version value="1"></version>        <list>      </list>  </litepal></code></pre>    <p><em>说明:</em> 这里的 <dbname> 标签用于指定数据库名, <version> 标签用于指定数据库版本号,<list> 标签用于指定所有的映射模型。</p>    <p>第三步</p>    <p>配置 LitePalApplication</p>    <pre>  <code class="language-java"><application      android:name="org.litepal.LitePalApplication"      android:allowBackup="true"      android:icon="@mipmap/ic_launcher"      android:label="@string/app_name"      android:roundIcon="@mipmap/ic_launcher_round"      android:supportsRtl="true"      android:theme="@style/AppTheme">      <activity android:name=".MainActivity">          <intent-filter>          <action android:name="android.intent.action.MAIN" />          <category android:name="android.intent.category.LAUNCHER" />          </intent-filter>      </activity>  </application></code></pre>    <h3>验证、创建以及升级数据库</h3>    <p>经过上面的步骤已经将 LitePal 配置完成,那么现在就通过创建表来验证一下。</p>    <p>验证和创建</p>    <p>新建一个 AndDev 类:</p>    <pre>  <code class="language-java">package com.example.mu_16jj.litepaldemo.bean;    /**  * Description:AndDev其实就是一张表  * <p>  * WeChat:mu-16jj  * <p>  * Created by mu-16jj on 2017/3/29.  */    public class AndDev {        private String name;      private int age;      private String sex;      private int workedTime;        public String getName() {          return name;      }        public void setName(String name) {          this.name = name;      }        public int getAge() {          return age;      }        public void setAge(int age) {          this.age = age;      }        public String getSex() {          return sex;      }        public void setSex(String sex) {          this.sex = sex;      }        public int getWorkedTime() {          return workedTime;      }        public void setWorkedTime(int workedTime) {          this.workedTime = workedTime;      }  }</code></pre>    <p><em>说明:</em> 大家肯定都很熟悉,这就是一个 JavaBean ,定义了几个属性,也就是我们的表 AndDev 中有这些字段。</p>    <p>建好了表之后,接下来还需要将它添加到我们的模型列表中:</p>    <pre>  <code class="language-java"><?xml version="1.0" encoding="utf-8" ?>  <litepal>    <dbname value="AndroidDevelop"></dbname>    <version value="1"></version>    <list>  <mapping class="com.example.mu_16jj.litepaldemo.bean.AndDev"></mapping>  </list>  </litepal></code></pre>    <p>现在我们就可以测试了,启动一个 Activity ,我这里只添加了一个按钮,在其点击事件下写下面一句代码:</p>    <pre>  <code class="language-java">LitePal.getDatabase();</code></pre>    <p>运行程序,点击按钮,然后打开 Android Device Monitor 查看结果如下:</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/12c9006a176ccdad7f44ecc2f1afdd34.png"></p>    <p>Android Device Monitor</p>    <p>可见我们的数据库确实创建成功了,接下来我们查看表是否创建成功,点击上图中的导出图标</p>    <p><img src="https://simg.open-open.com/show/66a52a3b31eff2f3a39e2d9d87497272.png"></p>    <p>从手机导出文件</p>    <p>,然后利用 SQLite 打开数据库(也可以通过命令行方式查看),如下图:</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/096e80ad60c11925e1c8f8cd557f45f2.png"></p>    <p>AndDev表</p>    <p>这就证明我们的数据库和表都创建成功了。</p>    <p>升级</p>    <p>就在我们刚刚创建的 AndDev 表里面再增加一个 city(城市)列,只需在 AndDev 中添加 city 字段,设置 getter 和 setter 方法即可(代码自己添加);索性我们再添加一张表,名为 Category ,代码如下:</p>    <pre>  <code class="language-java">package com.example.mu_16jj.litepaldemo.bean;    /**   * Description:技术等级表   * <p>   * WeChat:mu-16jj   * <p>   * Created by mu-16jj on 2017/3/29.   */    public class Level {        private String primaryLevel;      private String middleLevel;      private String soniorLevel;        public String getPrimaryLevel() {          return primaryLevel;      }        public void setPrimaryLevel(String primaryLevel) {          this.primaryLevel = primaryLevel;      }        public String getMiddleLevel() {          return middleLevel;      }        public void setMiddleLevel(String middleLevel) {          this.middleLevel = middleLevel;      }        public String getSoniorLevel() {          return soniorLevel;      }        public void setSoniorLevel(String soniorLevel) {          this.soniorLevel = soniorLevel;      }    }</code></pre>    <p>我们还需要做最后一步操作,需要将我们的对象和关系型数据库建立关系:</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/59dc42ed4ac5a35c77f519fee9828d22.png"></p>    <p>添加表到映射模型</p>    <p><em>说明:</em> 可以看到这段代码相比之前修改了两个地方,数据库版本号修改为 2 ,增加了一个 <mapping> 标签;好了,现在运行程序,点击按钮,查看结果:</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/c7ebbf99160fc1247685484a6b4c0599.png"></p>    <p>新增加列</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/09a52772c2a27ffcbf029d885b7754b8.png"></p>    <p>升级结果</p>    <p>可以看到,AndDev 表中增加了一个 city 列,level 表也创建成功了。</p>    <h3>添加数据</h3>    <p>前面已经配置好环境,冰成功创建了两张表,下面我们就针对这两张表进行CRUD操作,先来给 AndDev 表添加一组数据,在我们的 Activity 上再添加一个按钮,其点击事件代码如下:</p>    <pre>  <code class="language-java">AndDev andDev = new AndDev();  andDev.setAge(25);  andDev.setCity("北京");  andDev.setName("code小生");  andDev.setSex("man");  andDev.setWorkedTime(2);  andDev.save();</code></pre>    <p>仔细看看上面的代码,对于最后一行是不是有些疑惑了,这里需要说明的是,litepal 对表的 CRUD 操作依赖一个类 DataSupport ,所以如果我们需要对表进行操作,那么这个实体类就需要继承 DataSupport 类才可以。</p>    <p>运行程序,点击添加按钮,查看结果:</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/4a5358c1f463b4ba2dca29d163b49fda.png"></p>    <p>添加数据</p>    <p>可以看到,一组数据成功添加进了我们的 AndDev 表。</p>    <h3>更新数据</h3>    <p>我们一般的更新就是针对已存储的对象进行重新设值,那么,LitePal 是怎么判断某个对象是已存储的呢?当然提供了方法,通过 model.isSaved() 方法返回结果来判断,true 表示已存储,false 表示未存储,那就需要知道一个概念 [ 什么是已存储 ]?两种情况,一种是已经调用过 model.save() 方法去添加数据了;另一种是 model 对象是通过 LitePal 查询 API 查出来的,那么这两种情况都会被认为是已存储的对象。</p>    <p>第一种更新方式</p>    <pre>  <code class="language-java">AndDev andDev1 = new AndDev();  andDev1.setWorkedTime(3);  andDev1.setSex("woman");  andDev1.setName("codexiaosheng");  andDev1.setAge(26);  andDev1.setCity("杭州");  andDev1.save();  andDev1.setWorkedTime(5);  andDev1.save();</code></pre>    <p>运行查看结果:</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/35fbf7b1cccf34bcb3e9c14b1f8e23da.png"></p>    <p>对已保存对象更新</p>    <p>可以看到,新的一条数据被成功插入,而且新插入的对象的 workedtime 值并不是 3 ,而是 5,那么就证明更新确实生效了。但是这种方式太死板,再来看一个比较灵活的方式:</p>    <p>修改更新按钮事件代码如下:</p>    <pre>  <code class="language-java">AndDev andDev1 = new AndDev();  andDev1.setCity("甘肃");  andDev1.setWorkedTime(3);  andDev1.updateAll("age = ? and sex = ?", "26", "woman");</code></pre>    <p>运行结果:</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/35fbf7b1cccf34bcb3e9c14b1f8e23da.png"></p>    <p>updateAll</p>    <p>可以看到,将 age = 26 sex = woman 的这条数据的 workedtime 更新为 3 , city 为甘肃。</p>    <p>注意:</p>    <p>如果想把某个字段的值置为默认,那么通过对象的 setXXX() 方法是不起作用的(因为根据就不会调用),LitePal 提供了更新默认的方法,比如下面的示例:</p>    <pre>  <code class="language-java">AndDev andDev2 = new AndDev();  andDev2.setToDefault("age");  andDev2.updateAll();</code></pre>    <p>执行这段代码,就会将所有年龄置为 0 ,updateAll()方法接收一个可变参数变量,不写默认就对所有列生效。</p>    <h3>删除</h3>    <p>我们还是先来看一段代码执行后的结果,删除按钮监听代码:</p>    <pre>  <code class="language-java">DataSupport.deleteAll(AndDev.class, "city = ?", "北京");</code></pre>    <p>结果:</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/1c77d5075436c202a53ce89c99c5a66b.png"></p>    <p>deleteAll</p>    <p>可以看到,删除了 city 字段值为 “北京”的一条数据。deleteAll() 方法和 updateAll() 方法类似,如果不传参数,默认删除表中所有数据。</p>    <h3>查询</h3>    <p>LitePal 的查询 API 就更人性化,使用起来挺方便,下面就看例子。在界面添加删除按钮,点击事件执行下面代码:</p>    <pre>  <code class="language-java">List<AndDev> andDevs = DataSupport.findAll(AndDev.class);                  for (AndDev andDev1 : andDevs) {                      Log.e("MainActivity", "age: " + andDev1.getAge());                      Log.e("MainActivity", "name: " + andDev1.getName());                      Log.e("MainActivity", "sex: " + andDev1.getSex());                      Log.e("MainActivity", "workedtime: " + andDev1.getWorkedTime());                      Log.e("MainActivity", "city: " + andDev1.getCity());                  }</code></pre>    <p>运行查看结果如下:</p>    <p style="text-align:center"><img src="https://simg.open-open.com/show/8649f7981b0cd24b9ee93f042e1c9f71.png"></p>    <p>finaAll</p>    <p>可以看到,表中的所有数据都已查到,这个方法使用起来方便多了。当然了,LitePal 还给我们提供了其他的查询方法,这里列举如下:</p>    <p>findFirst(xxx.class); 查询表中第一条数据;返回一个实体类对象。</p>    <p>findLast(xxx.class); 查询表中最后一条数据;返回一个实体类对象。</p>    <p>select() 方法用于指定查询那几列;返回一个 List 集合;</p>    <pre>  <code class="language-java">DataSupport.select("列名1","列名2").find(实体类.class);</code></pre>    <p>where() 方法用于指定查询约束条件;返回一个 List 集合;</p>    <pre>  <code class="language-java">DataSupport.where("age > >", "20").find(实体类.class);</code></pre>    <p>order() 方法用于指定结果的排序方式;返回一个 List 集合;</p>    <pre>  <code class="language-java">DataSupport.order("age desc").find(实体类.class);</code></pre>    <p>limit() 方法用于指定查询结果的数量;返回一个 List 集合;比如只查表中前 2 条数据,写法如下:</p>    <pre>  <code class="language-java">DataSupport.limit(3).find(实体类.class);</code></pre>    <p>offset() 方法用于指定查询数据的偏移量;返回一个 List 集合;比如查表中第 2 条、第 3 条数据,写法如下:</p>    <pre>  <code class="language-java">DataSupport.limit(2).offset(1).find(实体类.class);</code></pre>    <p>当然了我们可以将上面的方法组合起来进行复杂查询:</p>    <pre>  <code class="language-java">// 复杂查询  List<AndDev> andDevs = DataSupport.select("name", "sex", "age")                  .where("city = ?", "甘肃")                  .order("workedTime")                  .limit(5)                  .offset(2)                  .find(AndDev.class);</code></pre>    <p>这段代码表示,查询 AndDev 表中第 3- 7 条满足 city 为甘肃这个条件的 name、sex、age 这三列数据,并将查询结果按照 workedTime 升序排列。</p>    <p>当然了, LitePal 任然支持原生的 SQL 查询:</p>    <pre>  <code class="language-java">Cursor cursor = DataSupport.findBySQL("select * from AndDev where age > ? and workedTime < 2", "22", "2");</code></pre>    <p> </p>    <p> </p>    <p>来自:http://www.jianshu.com/p/95f2338abe0a</p>    <p> </p>