Android的LitePal数据库ORM使用总结(避坑指南)

LitePal是Android《第一行代码》作者郭神的开源ORM框架,一个很好用的ORM。

虽然好用,但是如果不加注意,会遇到很多坑。所谓坑,并不是说框架不好,只是说有一些细节注意不到可能会犯错。

这不是bug,但是教程也好,示例demo中也罢,很少有提到,只能在使用过程中一一总结了。

以下总结自己使用中遇到的问题,逐步完善。

先介绍下简单使用:

app目录下的build.gradle中增加依赖:

//litepal数据库ORM
implementation 'org.litepal.guolindev:core:3.2.3'

在assets文件夹下创建一个相应的litepal.xml文件夹::

<?xml version="1.0" encoding="utf-8"?>
<litepal>
    <dbname value="testdb"/>
    <version value="1"/>
    <list>
        <mapping class="com.test.model.User"/>
    </list>
   <storage value="mydir" />
</litepal>

 在Application的onCreate中,增加初始化:LitePal.initialize(this);引入完毕。

问题一:

默认的数据库存储位置问题,可在litepal.xml文件中指定storage value="external"或者 "internal",默认是internal,文件浏览器查看是不可见或无权限的。external则在Android/data/目录下能找到数据库文件。但是,无论设置为哪种,只要应用卸载,数据库就跟着清除掉了。

如何能够持久保留数据库文件,不受是否卸载的影响呢?也简单,改下storage即可。

如:storage value="mydir" ,就会在根目录下的mydir目录下找到数据库文件。但前提是这个mydir已经提前创建好吧,若未创建会怎样,试下就知道。

问题二:

多表关联问题,关联的表无法存入数据。

这里有个隐藏的秘密,很难发现。建立一对一关联或一对多关联后,首先你要记得把关联表的数据save!!并不是你直接把数据set赋值之后,关联表就有数据了。set只是给两个表建立关联的。并且,除了save外,那个set也一样不能漏,否则你会看到关联的表里那个外键字段内容为空。

正解如:

News news=new News();
        news.setTitle("这是一条新闻标题");
        news.setContent("这是一条新闻内容");
        news.setPublishDate(new Date());
        Introduction introduction=new Introduction();
        introduction.setGuide("这是新闻导语");
        introduction.setDigest("这是新闻摘要");
        news.setIntroduction(introduction);//只是建立关联
        introduction.save();//重点
        news.save();

问题三:

有多表关联的实体,查询时查出来的关联的表内容为空。

比如定义了一个实体,内部还关联了其他实体类。查询时如果不加注意,只能查到本实体的内容,关联的实体查到的为空。

举例如:

public  class OrderDishTransdtlRecord extends LitePalSupport {

    @Column(nullable = false)
    private String billno;// 点餐单号
    @Nullable
    private String goodsid;//菜品编号 char(16)
    @Nullable
    private String typename; //菜品类别名称
    private int orderno;// 每笔订单菜品序列号
    private int price;
    private int qty;
    @Column(ignore = true)
    private List<OrderComboFoodRecord> comboFoods;// 套餐详情,不存数据库
    private  List<OrderDishTransdtlRecord> dtlList;// 细节  关联OrderDishDtlRecord
.....
}

如果只是想当然的  LitePal.find(OrderTransdtlRecord.class,10),这样查到的dtlList为null,没有数据。而应该如下写法:

 OrderTransdtlRecord recc = LitePal.find(OrderTransdtlRecord.class,10,true);//重点,第三个参数必须有,且为true
 Log.d(TAG,recc.toString());

问题四:

删除一条记录,关联的表里内容本该跟着删除的,但是数据还在,删除不掉的问题。如:

 OrderTransdtlRecord recc = LitePal.find(OrderTransdtlRecord.class,10);
 recc.delete();

这样是删不掉OrderTransdtlRecord的关联表OrderDishTransdtlRecord中的数据的。原因跟上个类似,这里的查询没增加第三个参数,isEager:True to load the associated models, false not.加上第三个参数,查询成功后,再删除,这样关联表才会跟着删除。或者使用这种方式,LitePal.delete(OrderTransdtlRecord.class,18),关联表会跟着删除。

或者使用这种方式,关联的表也会随之删除:

LitePal.deleteAll(OrderTransdtlRecord.class,"id = ? ","19");

问题五:

LitePal中不支持枚举类型。如果你的model里使用了枚举类型,在生成的表结构里枚举类型的字段会被忽略。

常用的类型如String和int,long可以放心用,其他类型需做好测试,不能想当然。

LitePal支持的数据类型有8种,分别为:int、short、long、float、double、boolean、String和Date。其他不支持的如枚举,会被忽略。

并且,如果里面使用了表关联,需在litpal.xml中注册,否则,也会被忽略,而非生成关联的表结构。

在进行boolean类型操作的时候也需要注意。对于LitePal数据库,存储boolean值为true的时候可以直接用LitePal存储对象的方式存储,若存储的对象中boolean为false,需要调用setToDefault(String name)方法存储,其中参数name为对象中Boolean属性的名称,为字符串boolean值其实是以0和1的方式存到数据库中的,true=1,false=0,所以在查询的时候需要注意。

问题六:

LitePal数据库的操作,默认是在主线程中的,使用时需注意自己处理线程和异步问题。

虽然之前版本LitePal提供的有异步操作api,但是作者说了,尽量少用。后续版本可能废弃不再维护。推荐应用开发者自己处理异步问题,如使用RxJava异步库。

问题七:

LitePal不能更改数据库表名和字段名。默认的表名就是定义的实体类的类名,且都为小写,字段名都是实体类中定义的属性的小写。

问题八:

LitePal不支持自定义主键,默认的主键为id,不管一个实体类对象有没有设置id字段,数据库的表中都会创建一个id的主键,而这个id的值会在新记录插入时被自动置为表中的Id,也即是唯一值。如果你里面定义了个String id,运行会报错的。

问题九:

升级表结构时要格外注意,以防历史数据被清空。以下一些升级情况LitePal无法处理并且被升级表格里的所有数据将被清空:

添加了一个标注为 unique = true 的属性;
修改某个属性的标注为 unique = true;
修改某个属性的标注为 nullable = false;
以上情况会导致数据丢失,要格外注意。

不断总结中,欢迎补充......

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

特立独行的猫a

您的鼓励是我的创作动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值