Android LitePal 3.0数据库基本用法
简介
引自郭霖用法介绍
LitePal是一款开源的Android数据库框架,它采用了对象关系映射(ORM)的模式,并将我们平时开发时最常用到的一些数据库功能进行了封装,使得不用编写一行SQL语句就可以完成各种建表、増删改查的操作。并且LitePal很“轻”,jar包只有100k不到,而且近乎零配置,这一点和Hibernate这类的框架有很大区别。目前LitePal的源码已经托管到了GitHub上,地址是 https://github.com/LitePalFramework/LitePal 。
官网
LitePal
一.配置集成:
1.app/build.gradle添加依赖
implementation 'org.litepal.android:java:3.0.0'
二.初始化配置:
2.1 配置清单文件- AndroidManifest清单文件中添加
<manifest> <application android:name="xx.xx.Application" ... > ... </application></manifest>
2.2 配置Application
2.2.1 方式一、项目中Application继承LitePalApplication即可
2.2.2 方式二、项目中Application添加如下代码即可
如果有属于自己的Application则继承LitePalApplication或者添加如下代码(2选一即可)
@Override public void onCreate() { super.onCreate(); LitePal.initialize(this); }
三.创建litepal.xml:
在app/src/main新建assets/litepal.xml(与java目录平级),如下图
image.png
并添加如下代码:
<?xml version="1.0" encoding="utf-8"?><litepal> <!-- 定义应用程序的数据库名称。默认情况下,每个数据库名称应以.db结尾。 如果您没有使用.db命名数据库端,LitePal会自动为您添加后缀。--> <dbname value="LitePalDemo" /> <!-- 定义数据库的版本。每次要升级数据库时,版本标记都会有所帮助。 修改您在映射标记中定义的模型,只需将版本值加1,即可自动处理数据库升级而无需担心。--> <version value="1" /> <!-- 定义.db文件的位置。“internal”表示.db文件将存储在内部存储的数据库文件夹中,无人可以访问。 “external”表示.db文件将存储在主外部存储设备上目录的路径中,其中应用程序可以放置其拥有的每个人都 可以访问的永久文件。“内部”将作为默认值。 例如: <storage value =“external”/>--> <list> <!--注册新闻表--> <mapping class="com.litepal.sample.NewsBean" /> </list></litepal>
四.创建实体类
4.1 注解说明
@Column(unique = true) //是否唯一@Column(defaultValue = "default") //指定字段默认值@Column(nullable = false) //是否可以为空@Column(ignore = true) //是否可以忽略
4.2 创建NewsBean实体类并继承LitePalSupport
/** * id字段的值始终为当前记录的行号(下标从1开始),即使我们在实体类中定义了int或者long类型的id字段, * 在添加数据时人为的设置id的值为100等其他值,查询数据库发现该id字段的值设置是无效的,她始终等于该条记录所在的行id,即第几条记录 */public class NewsBean extends LitePalSupport { private String createTime; private String title; private String content; private int number; public int getNumber() { return number; } public void setNumber(int number) { this.number = number; } public String getCreateTime() { return createTime; } public void setCreateTime(String createTime) { this.createTime = createTime; } public String getTitle() { return title; } public void setTitle(String title) { this.title = title; } public String getContent() { return content; } public void setContent(String content) { this.content = content; }}
4.3 然后将这些实体添加到litepal.xml中的映射列表中:
Snipaste_2021-04-12_14-21-06.png
注意
每创建一个实体就要在litepal.xml文件中进行声明
五.使用示例
????5.1 增(代码部分)
增加记录
private void release() { //①:添加单条数据 NewsBean bean = new NewsBean(); bean.setCreateTime(timeInMillsTrasToDate()); bean.setTitle("张三"); bean.setContent("李四"); bean.save(); //返回true代表添加成功,返回flase代表添加失败 if (bean.save()) { Toast.makeText(this, "保存成功", Toast.LENGTH_SHORT).show(); this.finish(); } else { Toast.makeText(this, "保存失败", Toast.LENGTH_SHORT).show(); } //批量添加 List<NewsBean> list = new ArrayList<>(); //②:一次性添加5条 for (int i = 0; i < 5; i++) { NewsBean newsBean = new NewsBean(); newsBean.setCreateTime(timeInMillsTrasToDate()); newsBean.setTitle("张三"); newsBean.setContent("李四"); list.add(newsBean); } LitePal.saveAll(list); } /** * 时间转换 */ public static String timeInMillsTrasToDate() { Date now = new Date(); Long time = now.getTime(); DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); Calendar calendar = null; if (time != null) { calendar = Calendar.getInstance(); calendar.setTimeInMillis(time); } return formatter.format(calendar.getTime()); }
????5.2 删(代码部分)
删除记录
private void deleteNews(int position) { //删除单个记录,id=1 LitePal.delete(NewsBean.class, position); //删除数据库中NewsBean表的所有记录 LitePal.deleteAll(NewsBean.class); //删除数量大于100的 LitePal.deleteAll(NewsBean.class, "number > ?", "100"); //删除标题为张三的 LitePal.deleteAll(NewsBean.class, "title = ?", "张三"); //删除标题为张三,内容为李四的记录 LitePal.deleteAll(NewsBean.class, "title = ? and content = ?", "张三", "李四"); }
????5.3 改(代码部分)
修改记录
private void updateNews() { //①:修改ID为1的记录,并将标题和内容分别设置为张三、李四 NewsBean newsBean = LitePal.find(NewsBean.class, 1); newsBean.setTitle("张三"); newsBean.setContent("李四"); if (newsBean.save()) { Toast.makeText(this, "修改成功", Toast.LENGTH_SHORT).show(); this.finish(); } else { Toast.makeText(this, "修改失败", Toast.LENGTH_SHORT).show(); } //如下方式同上 NewsBean newsBean1 = new NewsBean(); newsBean1.setTitle("张三"); newsBean1.setContent("李四"); //直接更新id为1的记录 newsBean1.update(1); //③:修改ID为1的记录 NewsBean newsBean2 = new NewsBean(); //更新所有title为张三的记录,更新为李四 newsBean2.setTitle("李四"); newsBean2.updateAll("title = ?", "张三"); //④:将title为张三,content为李四的数据修改为王五、赵六 NewsBean newsBean3 = new NewsBean(); newsBean3.setTitle("王五"); newsBean3.setContent("赵六"); newsBean3.setContent(releaseContent.getText().toString()); newsBean3.updateAll("title = ? and content = ?", "张三", "李四"); }
????5.3 查(代码部分)
5.3.1.普通查询记录
private void queryNews() { //①:查询表中所有的记录,返回的是泛型为NewsBean的List集合 List<NewsBean> newsBeanList = LitePal.findAll(NewsBean.class); //②:查找表id为1的记录 NewsBean newsBean = LitePal.find(NewsBean.class, 1); //③:获取表中的第一条数据与最后一条数据 NewsBean firstNews = LitePal.findFirst(NewsBean.class); NewsBean latNews = LitePal.findLast(NewsBean.class); //④:查询表中的第5、10、15条数据 List<NewsBean> newsList1 = LitePal.findAll(NewsBean.class, 5, 10, 15); //或者定义一个数组 long[] ids = new long[]{5, 10, 15}; List<NewsBean> newsList2 = LitePal.findAll(NewsBean.class, ids); //⑤:查找title为张三的记录,并且以时长作排序(按时间desc倒序 asc 正序),where()方法接收任意个字符串参数, //其中第一个参数用于进行条件约束,从第二个参数开始,都是用于替换第一个参数中的占位符的。那这个where()方法就对应了一条SQL语句中的where部分。 List<NewsBean> movies = LitePal.where("title = ?", "张三"). order("time desc").find(NewsBean.class); //将查询出的新闻按照发布的时间倒序排列,只要title和content这两列数据,即最新发布的新闻放在最前面,那就可以这样写: List<NewsBean> newsList = LitePal.select("title", "content") .where("title > ?", "张三") .order("time desc").find(NewsBean.class); //设置查询的数量与偏移量 List<NewsBean> newsBeans = LitePal.select("title", "content") .where("title > ?", "张三") .order("time desc") .limit(30)//只查询前面30条 .offset(20)//分页查询,每次查20条 .find(NewsBean.class); }
5.3.2.异步查询记录
/** * 异步查询 * 默认情况每个数据库操作都在主线程上。如果您的操作可能花费很长时间则需要使用异步操作。 * Litepal支持对所有CRUD方法执行异步操作。 */ private void syncQueary() { //1、 异步查询示例 //使用findallasync() 代替 findall() ,然后调用 listen() 方法,查询完成就会回调onFinish()方法 LitePal.findAllAsync(NewsBean.class).listen(new FindMultiCallback<NewsBean>() { @Override public void onFinish(List<NewsBean> allSongs) { //查询结果 } }); //2、异步保存示例 NewsBean newsBean = new NewsBean(); newsBean.setTitle("张三"); newsBean.setContent("李四"); newsBean.saveAsync().listen(new SaveCallback() { @Override public void onFinish(boolean success) { } }); }
六. 数据库升级说明
进行升级处理:数据库版本号+1处理
6.1 升级情况
1.新增表(新增实体类)
2.修改表(修改实体类)
6.2 升级操作
修改litepal.xml中的配置,在映射列表中新增Cooment类,并将版本号1修改为2
<?xml version="1.0" encoding="utf-8"?><litepal> .... .... .... .... <!-- 定义数据库的版本。每次要升级数据库时,版本标记都会有所帮助。 修改您在映射标记中定义的模型,只需将版本值加1,即可自动处理数据库升级而无需担心。--> <version value="2" /> .... .... <list> <mapping class="com.litepal.sample.NewsBean" /> <mapping class="com.litepal.sample.PersonBean" /> ..... </list></litepal> .... ....
6.3 升级调用
这里还是需要调用一下,调用之后升级操作也就完成了
SQLiteDatabase db = Connector.getDatabase();
详细可参考
Android数据库高手秘籍(三)——使用LitePal升级表
七. 混淆配置
在app\proguard-rules.pro添加如下代码
-keep class org.litepal.** { *;}-keep class * extends org.litepal.crud.DataSupport { *;}-keep class * extends org.litepal.crud.LitePalSupport { *;}
插入重复数据解决
作者:maiduoduo
链接:https://www.jianshu.com/p/bf53e7364a03