继上一篇GreenDao后,本文将带领大家学习下基于注解的orm框架:LiteOrm,注意不是Ormlite,作者是马天宇,不是那个歌手哦,现在在阿里巴巴任职。好了闲话不多扯了。
LiteOrm是一个小巧、强大、比系统自带数据库操作性能快1倍的 android ORM 框架类库,开发者一行代码实现数据库的增删改查操作,以及实体关系的持久化和自动映射。
LiteOrm对数据库的操作有两种方式
- 独立操作:使用 LiteOrm 的 single 实例,可与 cascade 方式平滑切换,性能高,仅处理该对象数据,其关系、和关联对象忽略;
- 级联操作:使用 LiteOrm 的 cascade 实例,可与 single 方式平滑切换,全递归,该对象数据,及其关系、和关联对象都被处理;
如何使用:
1 . 首先导入需要的 lite-orm-1.9.1.jar,下载地址在文章结尾。一个数据库对应一个LiteOrm的实例,如果一个App只有一个数据库,那么LiteOrm应该是全局单例的。 如果多次新建LiteOrm实例,系统会提示你应该关闭之前的数据库,也可能会引起其他未知错误。可以在自定义的Application类中这样写:
static LiteOrm liteOrm;
if (liteOrm == null) {
DataBaseConfig config = new DataBaseConfig(this, "liteorm.db");
//"liteorm.db"是数据库名称,名称里包含路径符号"/"则将数据库建立到该路径下,可以使用sd卡路径。 不包含则在系统默认路径下创建DB文件。
//例如 public static final String DB_NAME = SD_CARD + "/lite/orm/liteorm.db"; DataBaseConfig config = new DataBaseConfig(this, DB_NAME);
config.dbVersion = 1; // set database version
config.onUpdateListener = null; // set database update listener
//独立操作,适用于没有级联关系的单表操作,
liteOrm = LiteOrm.newSingleInstance(config);
//级联操作,适用于多表级联操作
// liteOrm=LiteOrm.newCascadeInstance(config);
}
liteOrm.setDebugged(true); // open the log
2 .单表,新建类TestMode
@Table("test_model")
public class TestModel {
// 指定自增,每个对象需要有一个主键
@PrimaryKey(AssignType.AUTO_INCREMENT)
private int id;
// 非空字段
@NotNull
private String name;
//忽略字段,将不存储到数据库
@Ignore
private String password;
// 默认为true,指定列名
@Default("true")
@Column("login")
private Boolean isLogin;
//什么都不做,也会存储到数据库,列名就是"token"
private String token;
}
3 .多表 Man(男人),Boss(女优。。。),Address(地址),Wife(妻子),Company(公司),关系如下:
- Man-Boss:多对多关系
- Man-Address:一对多关系
- Man-Wife:一对一关系
- Man-Company:多对一关系
/** * ********** 四种映射关系示例 ************** */ @Mapping(Relation.ManyToMany) public ArrayList<Boss> bosses; //使用任何其他容器 @Mapping(Relation.OneToMany) public ConcurrentLinkedQueue<Address> addrList; @Mapping(Relation.OneToOne) public Wife wife; @Mapping(Relation.ManyToOne) public Company company;
4 . 常用操作:
- 保存(插入or更新)
School school = new School("hello");
liteOrm.save(school);
- 插入
Book book = new Book("good");
liteOrm.insert(book, ConflictAlgorithm.Abort);
- 更新
book.setIndex(1988);
book.setAuthor("hehe");
liteOrm.update(book);
- 更新指定列
// 把所有书的author强制批量改为liter
HashMap<String, Object> bookIdMap = new HashMap<String, Object>();
bookIdMap.put(Book.COL_AUTHOR, "liter");
liteOrm.update(bookList, new ColumnsValue(bookIdMap), ConflictAlgorithm.Fail);
// 仅 author 这一列更新为该对象的最新值。
//liteOrm.update(bookList, new ColumnsValue(new String[]{Book.COL_AUTHOR}, null), ConflictAlgorithm.Fail);
- 查询
List list = liteOrm.query(Book.class);
OrmLog.i(TAG, list);
- 查找 使用QueryBuilder
List<Student> list = liteOrm.query(new QueryBuilder<Student>(Student.class)
.where(Person.COL_NAME + " LIKE ?", new String[]{"%0"})
.whereAppendAnd()
.whereAppend(Person.COL_NAME + " LIKE ?", new String[]{"%s%"}));
OrmLog.i(TAG, list);
- 查询 根据ID
Student student = liteOrm.queryById(student1.getId(), Student.class);
OrmLog.i(TAG, student);
- 查询 任意
List<Book> books = liteOrm.query(new QueryBuilder<Book>(Book.class)
.columns(new String[]{"id", "author", Book.COL_INDEX})
.distinct(true)
.whereGreaterThan("id", 0)
.whereAppendAnd()
.whereLessThan("id", 10000)
.limit(6, 9)
.appendOrderAscBy(Book.COL_INDEX));
OrmLog.i(TAG, books);
- 删除 实体
// 删除 student-0
liteOrm.delete(student0);
- 删除 指定数量
// 按id升序,删除[2, size-1],结果:仅保留第一个和最后一个
// 最后一个参数可为null,默认按 id 升序排列
liteOrm.delete(Book.class, 2, bookList.size() - 1, "id");
- 删除 使用WhereBuilder
// 删除 student-1
liteOrm.delete(new WhereBuilder(Student.class)
.where(Person.COL_NAME + " LIKE ?", new String[]{"%1%"})
.and()
.greaterThan("id", 0)
.and()
.lessThan("id", 10000));
- 删除全部
// 连同其关联的classes,classes关联的其他对象一带删除
liteOrm.deleteAll(School.class);
liteOrm.deleteAll(Book.class);
// 顺带测试:连库文件一起删掉
liteOrm.deleteDatabase();
// 顺带测试:然后重建一个新库
liteOrm.openOrCreateDatabase();
// 满血复活
5 . 常用注解:
@Table("class")指定表名是class
@Ignore 忽略字段不被保存到数据库中
@Column("_id") 标明字段在数据中的列名是_id
@Mapping(Relation.XX)用于多表映射
@Check("check > 99")//大于99才存储
private int check = 100;
@Collate("NOCASE") 排序规则,nocase就是大小写无关
private String _collate;
@Default("SQL默认值") 指定字段缺省值
@NotNull 字段不能为空
@PrimaryKey(AssignType.AUTO_INCREMENT) 主键自增长
@Conflict(Strategy.FAIL) 冲突的时候不存储
@Unique 唯一,确保某列中的所有值是不同的。
@UniqueCombine(1) UniqueCombine 值为1,和 UniqueCombine同值 的属性联合唯一
private int mIndex;
@UniqueCombine(1) UniqueCombine值为1,和 mIndex联合唯一
private String author;
@Mapping(Relation.ManyToMany)
@MapCollection(ConcurrentLinkedQueue.class) 表示Queue的具体容器是ConcurrentLinkedQueue
private Queue<Student> studentLinkedQueue;
6 .最后讲一下约束冲突这个知识点
什么是sql约束?比如@NotNull,@Unique,@Check等。不满足这些约束就会产生冲突,解决约束冲突的算法。有五个选择:ROLLBACK、ABORT、FAIL、IGNORE和REPLACE,缺省方案是ABORT,它并不是标准的SQL语言。选项含义如下:
ROLLBACK
当发生约束冲突,立即ROLLBACK,即结束当前事务处理,命令中止并返回SQLITE_CONSTRAINT代码。若当前无活动事务(除了每一条命令创建的默认事务以外),则该算法与ABORT相同。
ABORT
当发生约束冲突,命令收回已经引起的改变并中止返回SQLITE_CONSTRAINT。但由于不执行ROLLBACK,所以前面的命令产生的改变将予以保留。缺省采用这一行为。
FAIL
当发生约束冲突,命令中止返回SQLITE_CONSTRAINT。但遇到冲突之前的所有改变将被保留。例如,若一条UPDATE语句在100行遇到冲突100th,前99行的改变将被保留,而对100行或以后的改变将不会发生。
IGNORE
当发生约束冲突,发生冲突的行将不会被插入或改变。但命令将照常执行。在冲突行之前或之后的行将被正常的插入和改变,且不返回错误信息。
REPLACE
当发生UNIQUE约束冲突,先存在的,导致冲突的行在更改或插入发生冲突的行之前被删除。这样,更改和插入总是被执行。命令照常执行且不返回错误信息。当发生NOT NULL约束冲突,导致冲突的NULL值会被字段缺省值取代。若字段无缺省值,执行ABORT算法。当冲突应对策略为满足约束而删除行时,它不会调用删除触发器。但在新版中这一特性可能被改变。INSERT或UPDATE的OR子句定义的算法会覆盖CREATE TABLE所定义的。ABORT算法将在没有定义任何算法时缺省使用。